java - Java中的冗余分配与分配前检查
问题描述
在长循环之前,冗余分配相同的值会花费更多(处理器+内存),还是在分配前检查?
int count = 0;
for(int i=0; i<100_000; i++){
if (...) {
count++
doLogic(count); // logic is strictly related with count
} else {
count = 0; //50.000 redundant assignment
}
}
VS。
int count = 0;
for(int i=0; i<10_000; i++){
if (...) {
count++
doLogic(count); // logic is strictly related with count
} else {
if(count > 0) { // 50.000 checks
count = 0;
}
}
}
如果count
将存在于不同的对象中(在 Spring 上下文中作为单例注入)并且增量/检查/重置将如下所示,它的成本是否相同:
config.incrementCount();
config.getCount();
config.resetCount();
解决方案
对您的问题的简短回答是没关系。任何一种方法都将具有大致相同的性能,并且很可能会被doLogic
.
您的首选应该始终是编写简单且惯用的代码,而不是过早地进行优化。
长答案是它取决于(它总是这样,不是吗?)。
首先,你真的不知道JIT会对你的代码做什么样的优化。适用于一个平台和 Java 版本的情况可能不适用于另一种平台。你不能依赖任何没有明确保证的东西。
其次,您知道他们所说的过早优化。对代码进行基准测试和分析总是一个好主意,但即使基准测试也不是 100% 可靠的。
好的,让我们进行基准测试:
# First case, variable counter
Benchmark Mode Cnt Score Error Units
Benchmark1.testCounter avgt 8 0.149 ± 0.026 ms/op
Benchmark1.testCounterIf avgt 8 0.190 ± 0.036 ms/op
# Second case, counter in the wrapper class
Benchmark Mode Cnt Score Error Units
Benchmark1.testCounterClass avgt 8 0.198 ± 0.025 ms/op
Benchmark1.testCounterClassIf avgt 8 0.181 ± 0.016 ms/op
虽然对于简单计数器变量的情况,“如果优化”似乎失败了,但在第二种情况下,差异在误差范围内。
在我的基准测试中,我只使用了一个简单的静态字段持有Counter
类。查看由 JIT 生成的 ASM,方法调用似乎是内联的。您的情况可能会有所不同,因为企业级 java 和 Spring 因在幕后使用晦涩难懂的魔法而臭名昭著(例如,通过代理和字节码操作)。不仅方法可能没有内联,而且一些隐藏的开销可能会意外出现。
PS 如果您对 JVM 的性能和微优化感兴趣,我建议您阅读Alexey Shipilev 的 JVM Anatomy Quarks 系列。
推荐阅读
- r - 如果在另一列中找到特定值 1 次或更多次,如何保留列 ID 的所有实例
- python - 自动连接边的 Python 图形方法
- karate - Can we call other TestRunner file in the karate feature file
- javascript - 如何限制 .map()
- python - Web Scraping 没有得到所有的表
- python - 取消选择并选择 PyQt5 中的所有复选框
- java - 我得到了必需的类型:Double 和提供的类型:Void
- android - 使用 WorkManager 更新数据
- python - Pytorch - 在使用 Dataloader 之前连接数据集
- javascript - 添加和删除相同的类后,Chrome 将输入字段变为多行