From commits-return-1363-archive-asf-public=cust-asf.ponee.io@zipkin.apache.org Wed May 15 09:40:58 2019 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [207.244.88.153]) by mx-eu-01.ponee.io (Postfix) with SMTP id 7DE4F180675 for ; Wed, 15 May 2019 11:40:58 +0200 (CEST) Received: (qmail 65334 invoked by uid 500); 15 May 2019 09:40:57 -0000 Mailing-List: contact commits-help@zipkin.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@zipkin.apache.org Delivered-To: mailing list commits@zipkin.apache.org Received: (qmail 65325 invoked by uid 99); 15 May 2019 09:40:57 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 15 May 2019 09:40:57 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id 181268739A; Wed, 15 May 2019 09:40:57 +0000 (UTC) Date: Wed, 15 May 2019 09:40:57 +0000 To: "commits@zipkin.apache.org" Subject: [incubator-zipkin] branch master updated: Add benchmark of jackson span decoder. (#2592) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <155791325693.31826.7651540103489684800@gitbox.apache.org> From: anuraaga@apache.org X-Git-Host: gitbox.apache.org X-Git-Repo: incubator-zipkin X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: feb151f2f9e5a1a10020c8c7eb5c6129112663da X-Git-Newrev: 41225ba98a1f9dfe8d64cf12b76c00500dbf70d4 X-Git-Rev: 41225ba98a1f9dfe8d64cf12b76c00500dbf70d4 X-Git-NotificationType: ref_changed_plus_diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated This is an automated email from the ASF dual-hosted git repository. anuraaga pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-zipkin.git The following commit(s) were added to refs/heads/master by this push: new 41225ba Add benchmark of jackson span decoder. (#2592) 41225ba is described below commit 41225ba98a1f9dfe8d64cf12b76c00500dbf70d4 Author: Anuraag Agrawal AuthorDate: Wed May 15 18:40:50 2019 +0900 Add benchmark of jackson span decoder. (#2592) * Add benchmark of jackson span decoder. * Header --- .../java/zipkin2/codec/JacksonSpanDecoder.java | 243 +++++++++++++++++++++ .../java/zipkin2/codec/JsonCodecBenchmarks.java | 10 +- ...ecoderTest.java => JacksonSpanDecoderTest.java} | 30 ++- .../java/zipkin2/codec/MoshiSpanDecoderTest.java | 8 +- 4 files changed, 284 insertions(+), 7 deletions(-) diff --git a/benchmarks/src/main/java/zipkin2/codec/JacksonSpanDecoder.java b/benchmarks/src/main/java/zipkin2/codec/JacksonSpanDecoder.java new file mode 100644 index 0000000..7f55e21 --- /dev/null +++ b/benchmarks/src/main/java/zipkin2/codec/JacksonSpanDecoder.java @@ -0,0 +1,243 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 zipkin2.codec; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import zipkin2.Annotation; +import zipkin2.Endpoint; +import zipkin2.Span; +import zipkin2.internal.ReadBuffer; + +public final class JacksonSpanDecoder { + + static final JsonFactory JSON_FACTORY = new JsonFactory(); + + public static List decodeList(byte[] spans) { + try { + return decodeList(JSON_FACTORY.createParser(spans)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static List decodeList(ByteBuffer spans) { + try { + return decodeList(JSON_FACTORY.createParser(ReadBuffer.wrapUnsafe(spans))); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static Span decodeOne(byte[] span) { + try { + return decodeOne(JSON_FACTORY.createParser(span)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static Span decodeOne(ByteBuffer span) { + try { + return decodeOne(JSON_FACTORY.createParser(ReadBuffer.wrapUnsafe(span))); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + static List decodeList(JsonParser jsonParser) { + List out = new ArrayList<>(); + + try { + if (jsonParser.nextToken() != JsonToken.START_ARRAY) { + throw new IOException("Not a valid JSON array, start token: " + jsonParser.currentToken()); + } + + while (jsonParser.nextToken() != JsonToken.END_ARRAY) { + out.add(parseSpan(jsonParser)); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + return out; + } + + static Span decodeOne(JsonParser jsonParser) { + try { + if (!jsonParser.hasCurrentToken()) { + jsonParser.nextToken(); + } + return parseSpan(jsonParser); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + static Span parseSpan(JsonParser jsonParser) throws IOException { + if (!jsonParser.isExpectedStartObjectToken()) { + throw new IOException("Not a valid JSON object, start token: " + + jsonParser.currentToken()); + } + + Span.Builder result = Span.newBuilder(); + + while (jsonParser.nextToken() != JsonToken.END_OBJECT) { + String fieldName = jsonParser.currentName(); + JsonToken value = jsonParser.nextToken(); + if (value == JsonToken.VALUE_NULL) { + continue; + } + switch (fieldName) { + case "traceId": + result.traceId(jsonParser.getValueAsString()); + break; + case "parentId": + result.parentId(jsonParser.getValueAsString()); + break; + case "id": + result.id(jsonParser.getValueAsString()); + break; + case "kind": + result.kind(Span.Kind.valueOf(jsonParser.getValueAsString())); + break; + case "name": + result.name(jsonParser.getValueAsString()); + break; + case "timestamp": + result.timestamp(jsonParser.getValueAsLong()); + break; + case "duration": + result.duration(jsonParser.getValueAsLong()); + break; + case "localEndpoint": + result.localEndpoint(parseEndpoint(jsonParser)); + break; + case "remoteEndpoint": + result.remoteEndpoint(parseEndpoint(jsonParser)); + break; + case "annotations": + if (!jsonParser.isExpectedStartArrayToken()) { + throw new IOException("Invalid span, expecting annotations array start, got: " + + value); + } + while (jsonParser.nextToken() != JsonToken.END_ARRAY) { + Annotation a = parseAnnotation(jsonParser); + result.addAnnotation(a.timestamp(), a.value()); + } + break; + case "tags": + if (value != JsonToken.START_OBJECT) { + throw new IOException("Invalid span, expecting tags object, got: " + value); + } + while (jsonParser.nextToken() != JsonToken.END_OBJECT) { + result.putTag(jsonParser.currentName(), jsonParser.nextTextValue()); + } + break; + case "debug": + result.debug(jsonParser.getBooleanValue()); + break; + case "shared": + result.shared(jsonParser.getBooleanValue()); + break; + default: + jsonParser.skipChildren(); + } + } + + return result.build(); + } + + static Endpoint parseEndpoint(JsonParser jsonParser) throws IOException { + if (!jsonParser.isExpectedStartObjectToken()) { + throw new IOException("Not a valid JSON object, start token: " + + jsonParser.currentToken()); + } + + String serviceName = null, ipv4 = null, ipv6 = null; + int port = 0; + + while (jsonParser.nextToken() != JsonToken.END_OBJECT) { + String fieldName = jsonParser.currentName(); + JsonToken value = jsonParser.nextToken(); + if (value == JsonToken.VALUE_NULL) { + continue; + } + + switch (fieldName) { + case "serviceName": + serviceName = jsonParser.getValueAsString(); + break; + case "ipv4": + ipv4 = jsonParser.getValueAsString(); + break; + case "ipv6": + ipv6 = jsonParser.getValueAsString(); + break; + case "port": + port = jsonParser.getValueAsInt(); + break; + default: + jsonParser.skipChildren(); + } + } + + if (serviceName == null && ipv4 == null && ipv6 == null && port == 0) return null; + return Endpoint.newBuilder() + .serviceName(serviceName) + .ip(ipv4) + .ip(ipv6) + .port(port) + .build(); + } + + static Annotation parseAnnotation(JsonParser jsonParser) throws IOException { + if (!jsonParser.isExpectedStartObjectToken()) { + throw new IOException("Not a valid JSON object, start token: " + + jsonParser.currentToken()); + } + + long timestamp = 0; + String value = null; + + while (jsonParser.nextToken() != JsonToken.END_OBJECT) { + String fieldName = jsonParser.currentName(); + + switch (fieldName) { + case "timestamp": + timestamp = jsonParser.getValueAsLong(); + break; + case "value": + value = jsonParser.getValueAsString(); + break; + default: + jsonParser.skipChildren(); + } + } + + if (timestamp == 0 || value == null) { + throw new IllegalStateException("Incomplete annotation at " + jsonParser.currentToken()); + } + return Annotation.create(timestamp, value); + } +} diff --git a/benchmarks/src/main/java/zipkin2/codec/JsonCodecBenchmarks.java b/benchmarks/src/main/java/zipkin2/codec/JsonCodecBenchmarks.java index abe5cbd..d68c3e8 100644 --- a/benchmarks/src/main/java/zipkin2/codec/JsonCodecBenchmarks.java +++ b/benchmarks/src/main/java/zipkin2/codec/JsonCodecBenchmarks.java @@ -68,6 +68,10 @@ public class JsonCodecBenchmarks { encodedBuf.release(); } + @Benchmark public List bytes_jacksonDecoder() { + return JacksonSpanDecoder.decodeList(encodedBytes); + } + @Benchmark public List bytes_moshiDecoder() { return MOSHI.decodeList(encodedBytes); } @@ -76,6 +80,10 @@ public class JsonCodecBenchmarks { return SpanBytesDecoder.JSON_V2.decodeList(encodedBytes); } + @Benchmark public List bytebuffer_jacksonDecoder() { + return JacksonSpanDecoder.decodeList(encodedBuf.nioBuffer()); + } + @Benchmark public List bytebuffer_moshiDecoder() { return MOSHI.decodeList(encodedBuf.nioBuffer()); } @@ -87,7 +95,7 @@ public class JsonCodecBenchmarks { // Convenience main entry-point public static void main(String[] args) throws Exception { Options opt = new OptionsBuilder() - .include(".*" + JsonCodecBenchmarks.class.getSimpleName()) + .include(".*" + JsonCodecBenchmarks.class.getSimpleName() + ".*") .addProfiler("gc") .build(); diff --git a/benchmarks/src/test/java/zipkin2/codec/MoshiSpanDecoderTest.java b/benchmarks/src/test/java/zipkin2/codec/JacksonSpanDecoderTest.java similarity index 61% copy from benchmarks/src/test/java/zipkin2/codec/MoshiSpanDecoderTest.java copy to benchmarks/src/test/java/zipkin2/codec/JacksonSpanDecoderTest.java index 7e61f8e..dab51a7 100644 --- a/benchmarks/src/test/java/zipkin2/codec/MoshiSpanDecoderTest.java +++ b/benchmarks/src/test/java/zipkin2/codec/JacksonSpanDecoderTest.java @@ -21,20 +21,42 @@ import io.netty.buffer.PooledByteBufAllocator; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; +import static zipkin2.TestObjects.CLIENT_SPAN; import static zipkin2.TestObjects.TRACE; -public class MoshiSpanDecoderTest { +public class JacksonSpanDecoderTest { byte[] encoded = SpanBytesEncoder.JSON_V2.encodeList(TRACE); + byte[] encodedSpan = SpanBytesEncoder.JSON_V2.encode(CLIENT_SPAN); @Test public void decodeList_bytes() { - assertThat(new MoshiSpanDecoder().decodeList(encoded)) + assertThat(JacksonSpanDecoder.decodeList(encoded)) .isEqualTo(TRACE); } @Test public void decodeList_byteBuffer() { ByteBuf encodedBuf = PooledByteBufAllocator.DEFAULT.buffer(encoded.length); encodedBuf.writeBytes(encoded); - assertThat(new MoshiSpanDecoder().decodeList(encoded)) - .isEqualTo(TRACE); + try { + assertThat(JacksonSpanDecoder.decodeList(encodedBuf.nioBuffer())) + .isEqualTo(TRACE); + } finally { + encodedBuf.release(); + } + } + + @Test public void decodeOne() { + assertThat(JacksonSpanDecoder.decodeOne(encodedSpan)) + .isEqualTo(CLIENT_SPAN); + } + + @Test public void decodeOne_byteBuffer() { + ByteBuf encodedBuf = PooledByteBufAllocator.DEFAULT.buffer(encodedSpan.length); + encodedBuf.writeBytes(encodedSpan); + try { + assertThat(JacksonSpanDecoder.decodeOne(encodedBuf.nioBuffer())) + .isEqualTo(CLIENT_SPAN); + } finally { + encodedBuf.release(); + } } } diff --git a/benchmarks/src/test/java/zipkin2/codec/MoshiSpanDecoderTest.java b/benchmarks/src/test/java/zipkin2/codec/MoshiSpanDecoderTest.java index 7e61f8e..62bee5f 100644 --- a/benchmarks/src/test/java/zipkin2/codec/MoshiSpanDecoderTest.java +++ b/benchmarks/src/test/java/zipkin2/codec/MoshiSpanDecoderTest.java @@ -34,7 +34,11 @@ public class MoshiSpanDecoderTest { @Test public void decodeList_byteBuffer() { ByteBuf encodedBuf = PooledByteBufAllocator.DEFAULT.buffer(encoded.length); encodedBuf.writeBytes(encoded); - assertThat(new MoshiSpanDecoder().decodeList(encoded)) - .isEqualTo(TRACE); + try { + assertThat(new MoshiSpanDecoder().decodeList(encodedBuf.nioBuffer())) + .isEqualTo(TRACE); + } finally { + encodedBuf.release(); + } } }