Skip to content

Commit ca5a402

Browse files
netty: cache method path conversion
Benchmark Mode Cnt Score Error Units MethodDescriptorBenchmark.direct sample 1179094 43.483 ± 0.610 ns/op MethodDescriptorBenchmark.old sample 1079285 66.210 ± 5.402 ns/op MethodDescriptorBenchmark.transportSpecific sample 1408070 36.800 ± 0.423 ns/op
1 parent 893ef44 commit ca5a402

File tree

5 files changed

+230
-5
lines changed

5 files changed

+230
-5
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright 2016, Google Inc. All rights reserved.
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are
6+
* met:
7+
*
8+
* * Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above
11+
* copyright notice, this list of conditions and the following disclaimer
12+
* in the documentation and/or other materials provided with the
13+
* distribution.
14+
*
15+
* * Neither the name of Google Inc. nor the names of its
16+
* contributors may be used to endorse or promote products derived from
17+
* this software without specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+
*/
31+
32+
package io.grpc.netty;
33+
34+
import io.grpc.InternalKnownTransport;
35+
import io.grpc.InternalMethodDescriptor;
36+
import io.grpc.MethodDescriptor;
37+
import io.netty.util.AsciiString;
38+
39+
import org.openjdk.jmh.annotations.Benchmark;
40+
import org.openjdk.jmh.annotations.BenchmarkMode;
41+
import org.openjdk.jmh.annotations.Mode;
42+
import org.openjdk.jmh.annotations.OutputTimeUnit;
43+
import org.openjdk.jmh.annotations.Scope;
44+
import org.openjdk.jmh.annotations.State;
45+
46+
import java.io.ByteArrayInputStream;
47+
import java.io.InputStream;
48+
import java.util.concurrent.TimeUnit;
49+
50+
/**
51+
* Benchmark for Method Descriptors.
52+
*/
53+
@State(Scope.Benchmark)
54+
public class MethodDescriptorBenchmark {
55+
56+
private static final MethodDescriptor.Marshaller<Void> marshaller =
57+
new MethodDescriptor.Marshaller<Void>() {
58+
@Override
59+
public InputStream stream(Void value) {
60+
return new ByteArrayInputStream(new byte[]{});
61+
}
62+
63+
@Override
64+
public Void parse(InputStream stream) {
65+
return null;
66+
}
67+
};
68+
69+
MethodDescriptor<Void, Void> method = MethodDescriptor.create(
70+
MethodDescriptor.MethodType.UNARY, "Service/Method", marshaller, marshaller);
71+
72+
InternalMethodDescriptor imd = new InternalMethodDescriptor(InternalKnownTransport.NETTY);
73+
74+
byte[] directBytes = new AsciiString("/" + method.getFullMethodName()).toByteArray();
75+
76+
/** Foo bar. */
77+
@Benchmark
78+
@BenchmarkMode(Mode.SampleTime)
79+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
80+
public AsciiString old() {
81+
return new AsciiString("/" + method.getFullMethodName());
82+
}
83+
84+
/** Foo bar. */
85+
@Benchmark
86+
@BenchmarkMode(Mode.SampleTime)
87+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
88+
public AsciiString transportSpecific() {
89+
AsciiString path;
90+
if ((path = (AsciiString) imd.geRawMethodName(method)) != null) {
91+
path = new AsciiString("/" + method.getFullMethodName());
92+
imd.setRawMethodName(method, path);
93+
}
94+
return path;
95+
}
96+
97+
/** Foo bar. */
98+
@Benchmark
99+
@BenchmarkMode(Mode.SampleTime)
100+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
101+
public AsciiString direct() {
102+
return new AsciiString(directBytes, false);
103+
}
104+
}
105+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2016, Google Inc. All rights reserved.
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are
6+
* met:
7+
*
8+
* * Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above
11+
* copyright notice, this list of conditions and the following disclaimer
12+
* in the documentation and/or other materials provided with the
13+
* distribution.
14+
*
15+
* * Neither the name of Google Inc. nor the names of its
16+
* contributors may be used to endorse or promote products derived from
17+
* this software without specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+
*/
31+
32+
package io.grpc;
33+
34+
/**
35+
* All known transports.
36+
*/
37+
@Internal
38+
public enum InternalKnownTransport {
39+
NETTY,
40+
;
41+
}
42+
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2016, Google Inc. All rights reserved.
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are
6+
* met:
7+
*
8+
* * Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above
11+
* copyright notice, this list of conditions and the following disclaimer
12+
* in the documentation and/or other materials provided with the
13+
* distribution.
14+
*
15+
* * Neither the name of Google Inc. nor the names of its
16+
* contributors may be used to endorse or promote products derived from
17+
* this software without specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+
*/
31+
32+
package io.grpc;
33+
34+
import static com.google.common.base.Preconditions.checkNotNull;
35+
36+
/**
37+
* Accesses internal data. Do not use this.
38+
*/
39+
@Internal
40+
public final class InternalMethodDescriptor {
41+
private final InternalKnownTransport transport;
42+
43+
public InternalMethodDescriptor(InternalKnownTransport transport) {
44+
// TODO(carl-mastrangelo): maybe restrict access to this.
45+
this.transport = checkNotNull(transport, "transport");
46+
}
47+
48+
public Object geRawMethodName(MethodDescriptor<?, ?> md) {
49+
return md.getRawMethodName(transport);
50+
}
51+
52+
public void setRawMethodName(MethodDescriptor<?, ?> md, Object o) {
53+
md.setRawMethodName(transport, o);
54+
}
55+
}

core/src/main/java/io/grpc/MethodDescriptor.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.google.common.base.Preconditions;
3535

3636
import java.io.InputStream;
37+
import java.util.concurrent.atomic.AtomicReferenceArray;
3738

3839
import javax.annotation.Nullable;
3940
import javax.annotation.concurrent.Immutable;
@@ -55,6 +56,17 @@ public class MethodDescriptor<ReqT, RespT> {
5556
private final Marshaller<RespT> responseMarshaller;
5657
private final boolean idempotent;
5758

59+
private final AtomicReferenceArray<Object> rawMethodNames =
60+
new AtomicReferenceArray<Object>(InternalKnownTransport.values().length);
61+
62+
final Object getRawMethodName(InternalKnownTransport t) {
63+
return rawMethodNames.get(t.ordinal());
64+
}
65+
66+
final void setRawMethodName(InternalKnownTransport t, Object o) {
67+
rawMethodNames.lazySet(t.ordinal(), o);
68+
}
69+
5870
/**
5971
* The call type of a method.
6072
*/
@@ -152,10 +164,11 @@ public static <RequestT, ResponseT> MethodDescriptor<RequestT, ResponseT> create
152164
type, fullMethodName, requestMarshaller, responseMarshaller, false);
153165
}
154166

155-
private MethodDescriptor(MethodType type, String fullMethodName,
156-
Marshaller<ReqT> requestMarshaller,
157-
Marshaller<RespT> responseMarshaller,
158-
boolean idempotent) {
167+
private MethodDescriptor(
168+
MethodType type, String fullMethodName,
169+
Marshaller<ReqT> requestMarshaller,
170+
Marshaller<RespT> responseMarshaller,
171+
boolean idempotent) {
159172
this.type = Preconditions.checkNotNull(type, "type");
160173
this.fullMethodName = Preconditions.checkNotNull(fullMethodName, "fullMethodName");
161174
this.requestMarshaller = Preconditions.checkNotNull(requestMarshaller, "requestMarshaller");

netty/src/main/java/io/grpc/netty/NettyClientStream.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import static com.google.common.base.Preconditions.checkState;
3636
import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
3737

38+
import io.grpc.InternalKnownTransport;
39+
import io.grpc.InternalMethodDescriptor;
3840
import io.grpc.Metadata;
3941
import io.grpc.MethodDescriptor;
4042
import io.grpc.Status;
@@ -56,6 +58,10 @@
5658
* Client stream for a Netty transport.
5759
*/
5860
abstract class NettyClientStream extends Http2ClientStream implements StreamIdHolder {
61+
62+
private static final InternalMethodDescriptor methodDescriptorAccessor =
63+
new InternalMethodDescriptor(InternalKnownTransport.NETTY);
64+
5965
private final MethodDescriptor<?, ?> method;
6066
/** {@code null} after start. */
6167
private Metadata headers;
@@ -94,7 +100,11 @@ public void start(ClientStreamListener listener) {
94100
super.start(listener);
95101

96102
// Convert the headers into Netty HTTP/2 headers.
97-
AsciiString defaultPath = new AsciiString("/" + method.getFullMethodName());
103+
AsciiString defaultPath = (AsciiString) methodDescriptorAccessor.geRawMethodName(method);
104+
if (defaultPath == null) {
105+
defaultPath = new AsciiString("/" + method.getFullMethodName());
106+
methodDescriptorAccessor.setRawMethodName(method, defaultPath);
107+
}
98108
headers.removeAll(GrpcUtil.USER_AGENT_KEY);
99109
Http2Headers http2Headers
100110
= Utils.convertClientHeaders(headers, scheme, defaultPath, authority, userAgent);

0 commit comments

Comments
 (0)