mirror of https://github.com/grpc/grpc-java.git
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
This commit is contained in:
parent
893ef44b4c
commit
ca5a402fe6
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright 2016, Google Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package io.grpc.netty;
|
||||
|
||||
import io.grpc.InternalKnownTransport;
|
||||
import io.grpc.InternalMethodDescriptor;
|
||||
import io.grpc.MethodDescriptor;
|
||||
import io.netty.util.AsciiString;
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Benchmark for Method Descriptors.
|
||||
*/
|
||||
@State(Scope.Benchmark)
|
||||
public class MethodDescriptorBenchmark {
|
||||
|
||||
private static final MethodDescriptor.Marshaller<Void> marshaller =
|
||||
new MethodDescriptor.Marshaller<Void>() {
|
||||
@Override
|
||||
public InputStream stream(Void value) {
|
||||
return new ByteArrayInputStream(new byte[]{});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void parse(InputStream stream) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
MethodDescriptor<Void, Void> method = MethodDescriptor.create(
|
||||
MethodDescriptor.MethodType.UNARY, "Service/Method", marshaller, marshaller);
|
||||
|
||||
InternalMethodDescriptor imd = new InternalMethodDescriptor(InternalKnownTransport.NETTY);
|
||||
|
||||
byte[] directBytes = new AsciiString("/" + method.getFullMethodName()).toByteArray();
|
||||
|
||||
/** Foo bar. */
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.SampleTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
public AsciiString old() {
|
||||
return new AsciiString("/" + method.getFullMethodName());
|
||||
}
|
||||
|
||||
/** Foo bar. */
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.SampleTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
public AsciiString transportSpecific() {
|
||||
AsciiString path;
|
||||
if ((path = (AsciiString) imd.geRawMethodName(method)) != null) {
|
||||
path = new AsciiString("/" + method.getFullMethodName());
|
||||
imd.setRawMethodName(method, path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/** Foo bar. */
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.SampleTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
public AsciiString direct() {
|
||||
return new AsciiString(directBytes, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2016, Google Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package io.grpc;
|
||||
|
||||
/**
|
||||
* All known transports.
|
||||
*/
|
||||
@Internal
|
||||
public enum InternalKnownTransport {
|
||||
NETTY,
|
||||
;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 2016, Google Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package io.grpc;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Accesses internal data. Do not use this.
|
||||
*/
|
||||
@Internal
|
||||
public final class InternalMethodDescriptor {
|
||||
private final InternalKnownTransport transport;
|
||||
|
||||
public InternalMethodDescriptor(InternalKnownTransport transport) {
|
||||
// TODO(carl-mastrangelo): maybe restrict access to this.
|
||||
this.transport = checkNotNull(transport, "transport");
|
||||
}
|
||||
|
||||
public Object geRawMethodName(MethodDescriptor<?, ?> md) {
|
||||
return md.getRawMethodName(transport);
|
||||
}
|
||||
|
||||
public void setRawMethodName(MethodDescriptor<?, ?> md, Object o) {
|
||||
md.setRawMethodName(transport, o);
|
||||
}
|
||||
}
|
||||
|
|
@ -34,6 +34,7 @@ package io.grpc;
|
|||
import com.google.common.base.Preconditions;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
|
@ -55,6 +56,17 @@ public class MethodDescriptor<ReqT, RespT> {
|
|||
private final Marshaller<RespT> responseMarshaller;
|
||||
private final boolean idempotent;
|
||||
|
||||
private final AtomicReferenceArray<Object> rawMethodNames =
|
||||
new AtomicReferenceArray<Object>(InternalKnownTransport.values().length);
|
||||
|
||||
final Object getRawMethodName(InternalKnownTransport t) {
|
||||
return rawMethodNames.get(t.ordinal());
|
||||
}
|
||||
|
||||
final void setRawMethodName(InternalKnownTransport t, Object o) {
|
||||
rawMethodNames.lazySet(t.ordinal(), o);
|
||||
}
|
||||
|
||||
/**
|
||||
* The call type of a method.
|
||||
*/
|
||||
|
|
@ -152,10 +164,11 @@ public class MethodDescriptor<ReqT, RespT> {
|
|||
type, fullMethodName, requestMarshaller, responseMarshaller, false);
|
||||
}
|
||||
|
||||
private MethodDescriptor(MethodType type, String fullMethodName,
|
||||
Marshaller<ReqT> requestMarshaller,
|
||||
Marshaller<RespT> responseMarshaller,
|
||||
boolean idempotent) {
|
||||
private MethodDescriptor(
|
||||
MethodType type, String fullMethodName,
|
||||
Marshaller<ReqT> requestMarshaller,
|
||||
Marshaller<RespT> responseMarshaller,
|
||||
boolean idempotent) {
|
||||
this.type = Preconditions.checkNotNull(type, "type");
|
||||
this.fullMethodName = Preconditions.checkNotNull(fullMethodName, "fullMethodName");
|
||||
this.requestMarshaller = Preconditions.checkNotNull(requestMarshaller, "requestMarshaller");
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
|
||||
|
||||
import io.grpc.InternalKnownTransport;
|
||||
import io.grpc.InternalMethodDescriptor;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.MethodDescriptor;
|
||||
import io.grpc.Status;
|
||||
|
|
@ -56,6 +58,10 @@ import javax.annotation.Nullable;
|
|||
* Client stream for a Netty transport.
|
||||
*/
|
||||
abstract class NettyClientStream extends Http2ClientStream implements StreamIdHolder {
|
||||
|
||||
private static final InternalMethodDescriptor methodDescriptorAccessor =
|
||||
new InternalMethodDescriptor(InternalKnownTransport.NETTY);
|
||||
|
||||
private final MethodDescriptor<?, ?> method;
|
||||
/** {@code null} after start. */
|
||||
private Metadata headers;
|
||||
|
|
@ -94,7 +100,11 @@ abstract class NettyClientStream extends Http2ClientStream implements StreamIdHo
|
|||
super.start(listener);
|
||||
|
||||
// Convert the headers into Netty HTTP/2 headers.
|
||||
AsciiString defaultPath = new AsciiString("/" + method.getFullMethodName());
|
||||
AsciiString defaultPath = (AsciiString) methodDescriptorAccessor.geRawMethodName(method);
|
||||
if (defaultPath == null) {
|
||||
defaultPath = new AsciiString("/" + method.getFullMethodName());
|
||||
methodDescriptorAccessor.setRawMethodName(method, defaultPath);
|
||||
}
|
||||
headers.removeAll(GrpcUtil.USER_AGENT_KEY);
|
||||
Http2Headers http2Headers
|
||||
= Utils.convertClientHeaders(headers, scheme, defaultPath, authority, userAgent);
|
||||
|
|
|
|||
Loading…
Reference in New Issue