You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zipkin.apache.org by an...@apache.org on 2019/05/11 08:49:44 UTC
[incubator-zipkin] branch master updated: Reuse char[] buffer when
decoding hex fields. (#2582)
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 5592e82 Reuse char[] buffer when decoding hex fields. (#2582)
5592e82 is described below
commit 5592e82cbc743b2263e74cf34c724685c5337ad1
Author: Anuraag Agrawal <an...@gmail.com>
AuthorDate: Sat May 11 17:49:37 2019 +0900
Reuse char[] buffer when decoding hex fields. (#2582)
* Reuse char[] buffer when decoding hex fields.
* Better(?) threadlocal
* Better exception type.
* Extract ID buffer for potential use in other locations.
* Remove unneessary change.
* Remove unused variable.
---
.../java/zipkin2/codec/ProtobufSpanDecoder.java | 13 +++++++++---
.../main/java/zipkin2/codec/WireSpanDecoder.java | 24 +++++++++++++++++++++-
.../src/main/java/zipkin2/internal/Platform.java | 16 +++++++++++++++
.../main/java/zipkin2/internal/Proto3Fields.java | 10 +++++++--
4 files changed, 57 insertions(+), 6 deletions(-)
diff --git a/benchmarks/src/main/java/zipkin2/codec/ProtobufSpanDecoder.java b/benchmarks/src/main/java/zipkin2/codec/ProtobufSpanDecoder.java
index f63d62c..0df0d03 100644
--- a/benchmarks/src/main/java/zipkin2/codec/ProtobufSpanDecoder.java
+++ b/benchmarks/src/main/java/zipkin2/codec/ProtobufSpanDecoder.java
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.logging.Logger;
import zipkin2.Endpoint;
import zipkin2.Span;
+import zipkin2.internal.Platform;
public class ProtobufSpanDecoder {
static final Logger LOG = Logger.getLogger(ProtobufSpanDecoder.class.getName());
@@ -271,16 +272,22 @@ public class ProtobufSpanDecoder {
private static String readHexString(CodedInputStream input) throws IOException {
int size = input.readRawVarint32();
+ int length = size * 2;
- char[] result = new char[size * 2];
+ // All our hex fields are at most 32 characters.
+ if (length > 32) {
+ throw new AssertionError("hex field greater than 32 chars long: " + length);
+ }
+
+ char[] result = Platform.get().idBuffer();
- for (int i = 0; i < result.length; i += 2) {
+ for (int i = 0; i < length; i += 2) {
byte b = input.readRawByte();
result[i] = HEX_DIGITS[(b >> 4) & 0xf];
result[i + 1] = HEX_DIGITS[b & 0xf];
}
- return new String(result);
+ return new String(result, 0, length);
}
static void logAndSkip(CodedInputStream input, int tag) throws IOException {
diff --git a/benchmarks/src/main/java/zipkin2/codec/WireSpanDecoder.java b/benchmarks/src/main/java/zipkin2/codec/WireSpanDecoder.java
index a7e7a24..d5b1f84 100644
--- a/benchmarks/src/main/java/zipkin2/codec/WireSpanDecoder.java
+++ b/benchmarks/src/main/java/zipkin2/codec/WireSpanDecoder.java
@@ -26,8 +26,10 @@ import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import okio.Buffer;
+import okio.ByteString;
import zipkin2.Endpoint;
import zipkin2.Span;
+import zipkin2.internal.Platform;
public class WireSpanDecoder {
static final Logger LOG = Logger.getLogger(WireSpanDecoder.class.getName());
@@ -279,8 +281,28 @@ public class WireSpanDecoder {
return spans;
}
+ static final char[] HEX_DIGITS =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+ // https://github.com/square/wire/issues/958
private static String readHexString(ProtoReader input) throws IOException {
- return input.readBytes().hex();
+ ByteString bytes = input.readBytes();
+ int length = bytes.size() * 2;
+
+ // All our hex fields are at most 32 characters.
+ if (length > 32) {
+ throw new AssertionError("hex field greater than 32 chars long: " + length);
+ }
+
+ char[] result = Platform.get().idBuffer();
+
+ for (int i = 0; i < bytes.size(); i ++) {
+ byte b = bytes.getByte(i);
+ result[2 * i] = HEX_DIGITS[(b >> 4) & 0xf];
+ result[2 * i + 1] = HEX_DIGITS[b & 0xf];
+ }
+
+ return new String(result, 0, length);
}
static void logAndSkip(ProtoReader input, int tag) throws IOException {
diff --git a/zipkin/src/main/java/zipkin2/internal/Platform.java b/zipkin/src/main/java/zipkin2/internal/Platform.java
index fad3606..6e10fb8 100644
--- a/zipkin/src/main/java/zipkin2/internal/Platform.java
+++ b/zipkin/src/main/java/zipkin2/internal/Platform.java
@@ -27,9 +27,25 @@ import org.jvnet.animal_sniffer.IgnoreJRERequirement;
public abstract class Platform {
private static final Platform PLATFORM = findPlatform();
+ private static final ThreadLocal<char[]> ID_BUFFER = new ThreadLocal<>();
+
Platform() {
}
+ /**
+ * Returns a {@link ThreadLocal} reused {@code char[]} for use when decoding bytes into a hex
+ * string. The buffer should be immediately copied into a {@link String} after decoding within the
+ * same method.
+ */
+ public char[] idBuffer() {
+ char[] idBuffer = ID_BUFFER.get();
+ if (idBuffer == null) {
+ idBuffer = new char[32];
+ ID_BUFFER.set(idBuffer);
+ }
+ return idBuffer;
+ }
+
public RuntimeException uncheckedIOException(IOException e) {
return new RuntimeException(e);
}
diff --git a/zipkin/src/main/java/zipkin2/internal/Proto3Fields.java b/zipkin/src/main/java/zipkin2/internal/Proto3Fields.java
index 24076db..ba2df27 100644
--- a/zipkin/src/main/java/zipkin2/internal/Proto3Fields.java
+++ b/zipkin/src/main/java/zipkin2/internal/Proto3Fields.java
@@ -190,7 +190,13 @@ final class Proto3Fields {
@Override String readValue(Buffer buffer, int length) {
length *= 2;
- char[] result = new char[length];
+
+ // All our hex fields are at most 32 characters.
+ if (length > 32) {
+ throw new IllegalArgumentException("hex field greater than 32 chars long: " + length);
+ }
+
+ char[] result = Platform.get().idBuffer();
for (int i = 0; i < length; i += 2) {
byte b = buffer.readByte();
@@ -198,7 +204,7 @@ final class Proto3Fields {
result[i + 1] = HEX_DIGITS[b & 0xf];
}
- return new String(result);
+ return new String(result, 0, length);
}
}