这是一个简单的java代码片段
float start = System.nanoTime();
for(int i=0;i<1000000000;i = i+1){}
float end = System.nanoTime();
System.out.println("Time taken : " + (end-start)/1000000000);
这将输出0.004194304
秒,其中as:
for(double i=0;i<1000000000;i = i+1){}
此代码我只是将i
的类型从int
更改为double
需要3.8970327
秒。我的问题是如何在java中改进这种双重的非常糟糕的性能
答案 0 :(得分:1)
首先,我认为你的int
基准正在给出一个似是而非的答案。这个数字完全没有常识测试!
从1增加到1,000,000,000应该执行10亿增量,10亿个商店,10亿个测试,10亿个分支。所有这些都是据说在~0.004秒内发生。这意味着在0.004秒内有40亿条指令,或1秒钟内的1万亿条指令......或者是1.0E12的某个倍数的时钟速率。但是最快的英特尔处理器的时钟频率低于10 GHz ......或1.0E10。
事实上,我认为发生的事情是JIT编译器已经发现你的循环没有做任何有用的工作,并且已经优化了它。
出于某种原因,JIT编译器还没有发现具有double
的版本也没有做有用的工作。
但无论如何,使用单个处理器在3秒内进行10亿次浮点运算是非常好的表现......
我的问题是如何在java中改进这个非常糟糕的双重性能
性能不是很差。
这是(近似)真实的表现......你所看到的int
表现是虚假的。
你无法改进它。
实际上,你很幸运double
循环终止了。考虑这个版本:
for (double i = 0; i < Integer.MAX_VALUE; i = i + 1){}
for (float i = 0; i < Integer.MAX_VALUE; i = i + 1){}
float
版本应该更快。正确?
错!
问题是float
只有24位(7.22位十进制数字)的精度。因此,介于1.0E7和1.0E8之间,由于四舍五入,您将得到i + 1
评估为i
的点。这会导致无限循环。
当你考虑它时,正是这种事情可能导致JIT编译器不优化掉浮点循环。
答案 1 :(得分:-1)
这是正常的,因为int占用4个字节的内存,而double占用8个字节(它有小数)。 也许你可以证明BigDecimal。