注意:这不是关于性能问题的内容。我只观察到一种无法解释/理解的性能差异。
在对一些新开发的针对Java 9的代码进行基准测试时,我发现了一些奇怪的事情。使用5个键的HashMap的一个(非常)简单的基准测试表明,Java 9比Java 8慢得多。这可以解释吗?还是我的(基准)代码有问题?
代码:
在对一些新开发的针对Java 9的代码进行基准测试时,我发现了一些奇怪的事情。使用5个键的HashMap的一个(非常)简单的基准测试表明,Java 9比Java 8慢得多。这可以解释吗?还是我的(基准)代码有问题?
代码:
@Fork(
jvmArgsAppend = {"-Xmx512M", "-disablesystemassertions"}
)
public class JsonBenchmark {
@State(Scope.Thread)
public static class Data {
final static Locale RUSSIAN = new Locale("ru");
final static Locale DUTCH = new Locale("nl");
final Map<Locale, String> hashmap = new HashMap<>();
public Data() {
hashmap.put(Locale.ENGLISH, "Flat flashing adjustable for flat angled roof with swivel");
hashmap.put(Locale.FRENCH, "Solin pour toit plat inclinée");
hashmap.put(Locale.GERMAN, "Flachdachkragen Flach Schrägdach");
hashmap.put(DUTCH, "Plakplaat vlak/hellend dak inclusief glijschaal");
hashmap.put(RUSSIAN, "Проход через плоскую кровлю регулир. для накл. кровли");
}
}
@Benchmark
public int bmHashMap(JsonBenchmark.Data data) {
final Map<Locale, String> m = data.hashmap;
int sum = 0;
sum += m.get(Data.RUSSIAN).length();
sum += m.get(Locale.FRENCH).length();
sum += m.get(Data.DUTCH).length();
sum += m.get(Locale.ENGLISH).length();
sum += m.get(Locale.GERMAN).length();
return sum;
}
}
结果:
- Java 8_151: JsonBenchmark.bmHashMap thrpt 40 47948546.439 ± 560763.711 ops/s
- Java 9_181: JsonBenchmark.bmHashMap thrpt 40 34962904.479 ± 276045.691 ops/s (-/- 27%!)
更新
感谢答案和好的评论。
@Holger的建议。我的第一反应是:这一定是解释。然而,如果我只对
String#length()
函数进行基准测试,则性能没有显著差异。当我只对HashMap#get()
方法进行基准测试时(正如@Eugene所建议的),仍然存在大约10-12%的差异。@Eugene的建议。我改变了参数(更多的预热迭代,更多的内存),但我无法重现你的结果。我将堆大小增加到4G。但这不能解释差异,不是吗?
@Alan Bateman的建议。是的,这提高了性能!然而,仍有大约20%的差异。
.length
的复杂度比较?在理解时,将其呈现为答案和统计数据将会很好。我在这里查找了一些信息(http://cr.openjdk.java.net/~shade/8085796/notes.txt),但大部分都超出了我的理解范围。 - Namanarray.length
那样的,新实现是像arrays.length>>coder
这样的,其中coder是零或一,取决于字符串。在实际应用程序中的影响取决于length()
被实际调用的频率和拉丁1字符串与其他字符串之间的比率。对于拉丁1字符串,一些其他的字符串操作可能会更快(少量字节需要移动),这可能会更加补偿差距。 - Holgerjol
一起工作的人)说添加coder
字段不会使String类变得更大,因为由于8字节对齐而已经有了它的空间。 - Eugene