From 7bfb05bef68db0ff49eb4b7eded94936d13c697f Mon Sep 17 00:00:00 2001 From: David Walluck Date: Wed, 2 Apr 2025 11:28:29 -0400 Subject: [PATCH 1/2] fix: Fix some issues with `StringUtilBenchmark` * Make `Random` static even though in practice it should only be created once already (fixes SpotBugs warning) * Initialize fields to empty to prevent warning "`@NullMarked` fields must be initialized" * Iterate over `decodedData` directly instead of using the `DATA_COUNT` constant even though in practice these should always have the same length * Fill data fields directly instead of using a local variables/parameters with the same names --- .../internal/StringUtilBenchmark.java | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/test/java/com/github/packageurl/internal/StringUtilBenchmark.java b/src/test/java/com/github/packageurl/internal/StringUtilBenchmark.java index e05b534..dc7fc3a 100644 --- a/src/test/java/com/github/packageurl/internal/StringUtilBenchmark.java +++ b/src/test/java/com/github/packageurl/internal/StringUtilBenchmark.java @@ -54,43 +54,45 @@ @OutputTimeUnit(TimeUnit.MICROSECONDS) @State(Scope.Benchmark) public class StringUtilBenchmark { + private static final Random RANDOM = new Random(); private static final int DATA_COUNT = 1000; + private static final int DECODED_LENGTH = 256; + private static final byte[] UNRESERVED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~".getBytes(StandardCharsets.US_ASCII); @Param({"0", "0.1", "0.5"}) private double nonAsciiProb; - private String[] decodedData; - private String[] encodedData; + private String[] decodedData = {}; + + private String[] encodedData = {}; @Setup public void setup() { - decodedData = createDecodedData(); - encodedData = encodeData(decodedData); + createDecodedData(); + createEncodedData(); } - private String[] createDecodedData() { - Random random = new Random(); - String[] decodedData = new String[DATA_COUNT]; + private void createDecodedData() { + decodedData = new String[DATA_COUNT]; for (int i = 0; i < DATA_COUNT; i++) { char[] chars = new char[DECODED_LENGTH]; for (int j = 0; j < DECODED_LENGTH; j++) { - if (random.nextDouble() < nonAsciiProb) { - chars[j] = (char) (Byte.MAX_VALUE + 1 + random.nextInt(Short.MAX_VALUE - Byte.MAX_VALUE - 1)); + if (RANDOM.nextDouble() < nonAsciiProb) { + chars[j] = (char) (Byte.MAX_VALUE + 1 + RANDOM.nextInt(Short.MAX_VALUE - Byte.MAX_VALUE - 1)); } else { - chars[j] = (char) UNRESERVED[random.nextInt(UNRESERVED.length)]; + chars[j] = (char) UNRESERVED[RANDOM.nextInt(UNRESERVED.length)]; } } decodedData[i] = new String(chars); } - return decodedData; } - private static String[] encodeData(String[] decodedData) { - String[] encodedData = new String[decodedData.length]; + private void createEncodedData() { + encodedData = new String[decodedData.length]; for (int i = 0; i < encodedData.length; i++) { encodedData[i] = StringUtil.percentEncode(decodedData[i]); if (!StringUtil.percentDecode(encodedData[i]).equals(decodedData[i])) { @@ -100,13 +102,12 @@ private static String[] encodeData(String[] decodedData) { + StringUtil.percentDecode(encodedData[i])); } } - return encodedData; } @Benchmark public void baseline(Blackhole blackhole) { - for (int i = 0; i < DATA_COUNT; i++) { - byte[] buffer = decodedData[i].getBytes(StandardCharsets.UTF_8); + for (String decodedStr : decodedData) { + byte[] buffer = decodedStr.getBytes(StandardCharsets.UTF_8); // Prevent JIT compiler from assuming the buffer was not modified for (int idx = 0; idx < buffer.length; idx++) { buffer[idx] ^= 0x20; From 2be9a8158c517bf6d81b771a733904d7ebcc2a18 Mon Sep 17 00:00:00 2001 From: David Walluck Date: Thu, 3 Apr 2025 08:12:14 -0400 Subject: [PATCH 2/2] Move data creation to a single method --- .../packageurl/internal/StringUtilBenchmark.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/test/java/com/github/packageurl/internal/StringUtilBenchmark.java b/src/test/java/com/github/packageurl/internal/StringUtilBenchmark.java index dc7fc3a..66235eb 100644 --- a/src/test/java/com/github/packageurl/internal/StringUtilBenchmark.java +++ b/src/test/java/com/github/packageurl/internal/StringUtilBenchmark.java @@ -72,15 +72,14 @@ public class StringUtilBenchmark { @Setup public void setup() { - createDecodedData(); - createEncodedData(); + createData(); } - private void createDecodedData() { + private void createData() { decodedData = new String[DATA_COUNT]; - for (int i = 0; i < DATA_COUNT; i++) { + for (int i = 0; i < decodedData.length; i++) { char[] chars = new char[DECODED_LENGTH]; - for (int j = 0; j < DECODED_LENGTH; j++) { + for (int j = 0; j < chars.length; j++) { if (RANDOM.nextDouble() < nonAsciiProb) { chars[j] = (char) (Byte.MAX_VALUE + 1 + RANDOM.nextInt(Short.MAX_VALUE - Byte.MAX_VALUE - 1)); } else { @@ -89,9 +88,7 @@ private void createDecodedData() { } decodedData[i] = new String(chars); } - } - private void createEncodedData() { encodedData = new String[decodedData.length]; for (int i = 0; i < encodedData.length; i++) { encodedData[i] = StringUtil.percentEncode(decodedData[i]);