-
Enhancement
-
Resolution: Unresolved
-
P4
-
None
-
None
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
The reason is that StringBuilder::compareTo ends up calling
StringLatin1::compareTo(byte[] value, byte[] other, int len1, int len2)
Which is not intrinsified nor vectorized.
String::comapreTo ends up calling StringLatin1::compareTo(byte[] value, byte[] other) which is intrinsified and vectorized.
A simple solution can be to replace the code in
StringLatin1::compareTo(byte[] value, byte[] other, int len1, int len2)
with Arrays::compare.
Below are benchmark results comparing String::compareTo, StringBuilder::compareTo and Arrays::compare.
####### TEST CODE #######
@Fork(2)
public class CompareToBenchmark {
private static final String string1 = new String(new byte[1023]);
private static final String string2 = new String(new byte[1023]) + "a";
private static final StringBuilder stringBuilder1 = new StringBuilder(string1);
private static final StringBuilder stringBuilder2 = new StringBuilder(string2);
private static final byte[] bytes1 = string1.getBytes();
private static final byte[] bytes2 = string2.getBytes();
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int compareStrings() {
return string1.compareTo(string2);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int compareStringBuilders() {
return stringBuilder1.compareTo(stringBuilder2);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int compareByteArrays() {
return Arrays.compare(bytes1,0, bytes1.length, bytes2, 0, bytes2.length);
}
}
####### RESULTS #######
Benchmark Mode Cnt Score Error Units
CompareToBenchmark.compareByteArrays avgt 10 32.179 ± 5.666 ns/op
CompareToBenchmark.compareStringBuilders avgt 10 353.890 ± 115.107 ns/op
CompareToBenchmark.compareStrings avgt 10 29.072 ± 1.037 ns/op
The reason is that StringBuilder::compareTo ends up calling
StringLatin1::compareTo(byte[] value, byte[] other, int len1, int len2)
Which is not intrinsified nor vectorized.
String::comapreTo ends up calling StringLatin1::compareTo(byte[] value, byte[] other) which is intrinsified and vectorized.
A simple solution can be to replace the code in
StringLatin1::compareTo(byte[] value, byte[] other, int len1, int len2)
with Arrays::compare.
Below are benchmark results comparing String::compareTo, StringBuilder::compareTo and Arrays::compare.
####### TEST CODE #######
@Fork(2)
public class CompareToBenchmark {
private static final String string1 = new String(new byte[1023]);
private static final String string2 = new String(new byte[1023]) + "a";
private static final StringBuilder stringBuilder1 = new StringBuilder(string1);
private static final StringBuilder stringBuilder2 = new StringBuilder(string2);
private static final byte[] bytes1 = string1.getBytes();
private static final byte[] bytes2 = string2.getBytes();
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int compareStrings() {
return string1.compareTo(string2);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int compareStringBuilders() {
return stringBuilder1.compareTo(stringBuilder2);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public int compareByteArrays() {
return Arrays.compare(bytes1,0, bytes1.length, bytes2, 0, bytes2.length);
}
}
####### RESULTS #######
Benchmark Mode Cnt Score Error Units
CompareToBenchmark.compareByteArrays avgt 10 32.179 ± 5.666 ns/op
CompareToBenchmark.compareStringBuilders avgt 10 353.890 ± 115.107 ns/op
CompareToBenchmark.compareStrings avgt 10 29.072 ± 1.037 ns/op