Skip to content

Commit

Permalink
Avoid String.split when parsing header to reduce some garbage generat… (
Browse files Browse the repository at this point in the history
#160)

* Avoid String.split when parsing header to reduce some garbage generation.

* Optimize trace ID parse too.

* Error prone

Co-authored-by: William Armiros <54150514+willarmiros@users.noreply.github.com>
  • Loading branch information
Anuraag Agrawal and willarmiros authored Jun 5, 2020
1 parent 230115b commit f18c002
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 com.amazonaws.xray.entities;

import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

@Measurement(iterations = 5, time = 1)
@Warmup(iterations = 10, time = 1)
@Fork(3)
@BenchmarkMode(Mode.SampleTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class TraceHeaderBenchmark {

private static final String HEADER = "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=1";

@Benchmark
public TraceHeader parse() {
return TraceHeader.fromString(HEADER);
}

// Convenience main entry-point
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.addProfiler("gc")
.include(".*" + TraceHeaderBenchmark.class.getSimpleName())
.build();

new Runner(opt).run();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,46 +100,44 @@ public TraceHeader(TraceID rootTraceId, String parentId, SampleDecision sampled)
*/
public static TraceHeader fromString(String string) {
TraceHeader traceHeader = new TraceHeader();
if (null != string) {
String[] parts = string.split(";");
for (String part : parts) {
String trimmedPart = part.trim();
String value = valueFromKeyEqualsValue(trimmedPart);
if (trimmedPart.startsWith(ROOT_PREFIX)) {
traceHeader.setRootTraceId(TraceID.fromString(value));
} else if (trimmedPart.startsWith(PARENT_PREFIX)) {
traceHeader.setParentId(value);
} else if (trimmedPart.startsWith(SAMPLED_PREFIX)) {
traceHeader.setSampled(SampleDecision.fromString(trimmedPart));
} else if (!trimmedPart.startsWith(SELF_PREFIX)) {
String key = keyFromKeyEqualsValue(trimmedPart);
if (null != key && null != value) {
traceHeader.putAdditionalParam(key, value);
}
}
}
}
return traceHeader;
}

private static String keyFromKeyEqualsValue(String keyEqualsValue) {
int equalsIndex = keyEqualsValue.indexOf(EQUALS);
if (-1 != equalsIndex) {
return keyEqualsValue.substring(0, equalsIndex);
} else {
logger.error(MALFORMED_ERROR_MESSAGE);
return null;
if (string == null) {
return traceHeader;
}
}

private static String valueFromKeyEqualsValue(String keyEqualsValue) {
int equalsIndex = keyEqualsValue.indexOf(EQUALS);
if (-1 != equalsIndex) {
return keyEqualsValue.substring(equalsIndex + 1);
} else {
logger.error(MALFORMED_ERROR_MESSAGE);
return null;
int pos = 0;
while (pos < string.length()) {
int delimiterIndex = string.indexOf(';', pos);
final String part;
if (delimiterIndex >= 0) {
part = string.substring(pos, delimiterIndex);
pos = delimiterIndex + 1;
} else {
// Last part.
part = string.substring(pos);
pos = string.length();
}
String trimmedPart = part.trim();
int equalsIndex = trimmedPart.indexOf('=');
if (equalsIndex < 0) {
logger.error(MALFORMED_ERROR_MESSAGE);
continue;
}

String value = trimmedPart.substring(equalsIndex + 1);

if (trimmedPart.startsWith(ROOT_PREFIX)) {
traceHeader.setRootTraceId(TraceID.fromString(value));
} else if (trimmedPart.startsWith(PARENT_PREFIX)) {
traceHeader.setParentId(value);
} else if (trimmedPart.startsWith(SAMPLED_PREFIX)) {
traceHeader.setSampled(SampleDecision.fromString(trimmedPart));
} else if (!trimmedPart.startsWith(SELF_PREFIX)) {
String key = trimmedPart.substring(0, equalsIndex);
traceHeader.putAdditionalParam(key, value);
}
}
return traceHeader;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public class TraceID {

private static final char VERSION = '1';
private static final char DELIMITER = '-';
private static final String HEX_PREFIX = "0x";

private BigInteger number;
private long startTime;
Expand All @@ -39,14 +38,37 @@ public TraceID(long startTime) {
}

public static TraceID fromString(String string) {
string = string.trim();
TraceID traceId = new TraceID();
String[] parts = string.trim().split(DELIMITER + "");

if (parts.length >= 3) {
traceId.setStartTime(Long.decode(HEX_PREFIX + parts[1]));
traceId.setNumber(new BigInteger(parts[2], 16));
long startTime;

int delimiterIndex;

// Skip version number
delimiterIndex = string.indexOf(DELIMITER);
if (delimiterIndex < 0) {
return traceId;
}

int valueStartIndex = delimiterIndex + 1;
delimiterIndex = string.indexOf(DELIMITER, valueStartIndex);
if (delimiterIndex < 0) {
return traceId;
} else {
startTime = Long.valueOf(string.substring(valueStartIndex, delimiterIndex), 16);
}

valueStartIndex = delimiterIndex + 1;
delimiterIndex = string.indexOf(DELIMITER, valueStartIndex);
if (delimiterIndex < 0) {
// End of string
delimiterIndex = string.length();
}

traceId.setNumber(new BigInteger(string.substring(valueStartIndex, delimiterIndex), 16));
traceId.setStartTime(startTime);

return traceId;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private <T> T sendRequest(URL endpoint, Object request, Class<T> responseClass)

try (OutputStream outputStream = connection.getOutputStream()) {
OBJECT_MAPPER.writeValue(outputStream, request);
} catch (IOException e) {
} catch (IOException | IllegalArgumentException e) {
throw new XrayClientException("Could not serialize and send request.", e);
}

Expand Down

0 comments on commit f18c002

Please sign in to comment.