| /* |
| * Copyright 2016 The gRPC Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package io.grpc.netty; |
| |
| import static io.grpc.netty.Utils.CONTENT_TYPE_HEADER; |
| import static io.grpc.netty.Utils.TE_TRAILERS; |
| import static io.netty.util.AsciiString.of; |
| |
| import io.grpc.netty.GrpcHttp2HeadersUtils.GrpcHttp2RequestHeaders; |
| import io.grpc.netty.GrpcHttp2HeadersUtils.GrpcHttp2ResponseHeaders; |
| import io.netty.handler.codec.http2.DefaultHttp2Headers; |
| import io.netty.handler.codec.http2.Http2Headers; |
| import io.netty.util.AsciiString; |
| import java.util.concurrent.TimeUnit; |
| import org.openjdk.jmh.annotations.Benchmark; |
| import org.openjdk.jmh.annotations.BenchmarkMode; |
| import org.openjdk.jmh.annotations.CompilerControl; |
| 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 org.openjdk.jmh.infra.Blackhole; |
| |
| /** |
| * Benchmarks for {@link GrpcHttp2RequestHeaders} and {@link GrpcHttp2ResponseHeaders}. |
| */ |
| @State(Scope.Thread) |
| public class InboundHeadersBenchmark { |
| |
| private static AsciiString[] requestHeaders; |
| private static AsciiString[] responseHeaders; |
| |
| static { |
| setupRequestHeaders(); |
| setupResponseHeaders(); |
| } |
| |
| // Headers taken from the gRPC spec. |
| private static void setupRequestHeaders() { |
| requestHeaders = new AsciiString[18]; |
| int i = 0; |
| requestHeaders[i++] = of(":method"); |
| requestHeaders[i++] = of("POST"); |
| requestHeaders[i++] = of(":scheme"); |
| requestHeaders[i++] = of("http"); |
| requestHeaders[i++] = of(":path"); |
| requestHeaders[i++] = of("/google.pubsub.v2.PublisherService/CreateTopic"); |
| requestHeaders[i++] = of(":authority"); |
| requestHeaders[i++] = of("pubsub.googleapis.com"); |
| requestHeaders[i++] = of("te"); |
| requestHeaders[i++] = of("trailers"); |
| requestHeaders[i++] = of("grpc-timeout"); |
| requestHeaders[i++] = of("1S"); |
| requestHeaders[i++] = of("content-type"); |
| requestHeaders[i++] = of("application/grpc+proto"); |
| requestHeaders[i++] = of("grpc-encoding"); |
| requestHeaders[i++] = of("gzip"); |
| requestHeaders[i++] = of("authorization"); |
| requestHeaders[i] = of("Bearer y235.wef315yfh138vh31hv93hv8h3v"); |
| } |
| |
| private static void setupResponseHeaders() { |
| responseHeaders = new AsciiString[4]; |
| int i = 0; |
| responseHeaders[i++] = of(":status"); |
| responseHeaders[i++] = of("200"); |
| responseHeaders[i++] = of("grpc-encoding"); |
| responseHeaders[i] = of("gzip"); |
| } |
| |
| /** |
| * Checkstyle. |
| */ |
| @Benchmark |
| @BenchmarkMode(Mode.AverageTime) |
| @OutputTimeUnit(TimeUnit.NANOSECONDS) |
| public void grpcHeaders_serverHandler(Blackhole bh) { |
| serverHandler(bh, new GrpcHttp2RequestHeaders(4)); |
| } |
| |
| /** |
| * Checkstyle. |
| */ |
| @Benchmark |
| @BenchmarkMode(Mode.AverageTime) |
| @OutputTimeUnit(TimeUnit.NANOSECONDS) |
| public void defaultHeaders_serverHandler(Blackhole bh) { |
| serverHandler(bh, new DefaultHttp2Headers(true, 9)); |
| } |
| |
| /** |
| * Checkstyle. |
| */ |
| @Benchmark |
| @BenchmarkMode(Mode.AverageTime) |
| @OutputTimeUnit(TimeUnit.NANOSECONDS) |
| public void grpcHeaders_clientHandler(Blackhole bh) { |
| clientHandler(bh, new GrpcHttp2ResponseHeaders(2)); |
| } |
| |
| /** |
| * Checkstyle. |
| */ |
| @Benchmark |
| @BenchmarkMode(Mode.AverageTime) |
| @OutputTimeUnit(TimeUnit.NANOSECONDS) |
| public void defaultHeaders_clientHandler(Blackhole bh) { |
| clientHandler(bh, new DefaultHttp2Headers(true, 2)); |
| } |
| |
| @CompilerControl(CompilerControl.Mode.INLINE) |
| private static void serverHandler(Blackhole bh, Http2Headers headers) { |
| for (int i = 0; i < requestHeaders.length; i += 2) { |
| bh.consume(headers.add(requestHeaders[i], requestHeaders[i + 1])); |
| } |
| |
| // Sequence of headers accessed in NettyServerHandler |
| bh.consume(headers.get(TE_TRAILERS)); |
| bh.consume(headers.get(CONTENT_TYPE_HEADER)); |
| bh.consume(headers.method()); |
| bh.consume(headers.get(CONTENT_TYPE_HEADER)); |
| bh.consume(headers.path()); |
| |
| bh.consume(Utils.convertHeaders(headers)); |
| } |
| |
| @CompilerControl(CompilerControl.Mode.INLINE) |
| private static void clientHandler(Blackhole bh, Http2Headers headers) { |
| // NettyClientHandler does not directly access headers, but convert to Metadata immediately. |
| |
| bh.consume(headers.add(responseHeaders[0], responseHeaders[1])); |
| bh.consume(headers.add(responseHeaders[2], responseHeaders[3])); |
| |
| bh.consume(Utils.convertHeaders(headers)); |
| } |
| |
| // /** |
| // * Prints the size of the header objects in bytes. Needs JOL (Java Object Layout) as a |
| // * dependency. |
| // */ |
| // public static void main(String... args) { |
| // Http2Headers grpcRequestHeaders = new GrpcHttp2RequestHeaders(4); |
| // Http2Headers defaultRequestHeaders = new DefaultHttp2Headers(true, 9); |
| // for (int i = 0; i < requestHeaders.length; i += 2) { |
| // grpcRequestHeaders.add(requestHeaders[i], requestHeaders[i + 1]); |
| // defaultRequestHeaders.add(requestHeaders[i], requestHeaders[i + 1]); |
| // } |
| // long c = 10L; |
| // int m = ((int) c) / 20; |
| // |
| // long grpcRequestHeadersBytes = GraphLayout.parseInstance(grpcRequestHeaders).totalSize(); |
| // long defaultRequestHeadersBytes = |
| // GraphLayout.parseInstance(defaultRequestHeaders).totalSize(); |
| // |
| // System.out.printf("gRPC Request Headers: %d bytes%nNetty Request Headers: %d bytes%n", |
| // grpcRequestHeadersBytes, defaultRequestHeadersBytes); |
| // |
| // Http2Headers grpcResponseHeaders = new GrpcHttp2RequestHeaders(4); |
| // Http2Headers defaultResponseHeaders = new DefaultHttp2Headers(true, 9); |
| // for (int i = 0; i < responseHeaders.length; i += 2) { |
| // grpcResponseHeaders.add(responseHeaders[i], responseHeaders[i + 1]); |
| // defaultResponseHeaders.add(responseHeaders[i], responseHeaders[i + 1]); |
| // } |
| // |
| // long grpcResponseHeadersBytes = GraphLayout.parseInstance(grpcResponseHeaders).totalSize(); |
| // long defaultResponseHeadersBytes = |
| // GraphLayout.parseInstance(defaultResponseHeaders).totalSize(); |
| // |
| // System.out.printf("gRPC Response Headers: %d bytes%nNetty Response Headers: %d bytes%n", |
| // grpcResponseHeadersBytes, defaultResponseHeadersBytes); |
| // } |
| } |