我有一些我正在分析的代碼,並且驚訝於在Math.min(float, float)
上花了多少時間。爲什麼Java的Math.min在我的Android應用程序中如此緩慢?
在我的使用情況下,我需要獲取3個浮點值的最小值,每個值爲保證不是NAN
或另一個邊緣情況的浮點值。
我原來的方法是:
private static float min2(float v1, float v2, float v3) {
return Math.min(Math.min(v1,v2),v3);
}
但是我發現,這是約5倍的速度更快:
private static float min1(float v1, float v2, float v3) {
if (v1 < v2 && v1 < v3) {
return v1;
}
else if (v2 < v3) {
return v2;
}
else {
return v3;
}
}
僅供參考這是Math.min代碼:
public static float min(float f1, float f2) {
if (f1 > f2) {
return f2;
}
if (f1 < f2) {
return f1;
}
/* if either arg is NaN, return NaN */
if (f1 != f2) {
return Float.NaN;
}
/* min(+0.0,-0.0) == -0.0 */
/* 0x80000000 == Float.floatToRawIntBits(-0.0f) */
if (Float.floatToRawIntBits(f1) == 0x80000000) {
return -0.0f;
}
return f2;
}
注意:我的用例是對稱的,上面的所有對於max而不是min都是正確的。
EDIT1: 原來〜5倍就言過其實了,但我仍然看到我的應用程序內的速度差。雖然我懷疑這可能是由於沒有進行適當的時間測試。
發佈這個問題後,我寫了一個適當的微觀優化速度測試在一個單獨的項目。在隨機浮標上測試每種方法1000次,它們都花費相同的時間。我認爲發佈該代碼不會很有用,因爲它只是確認我們所有人已經想到的。
必須有一些特定的項目,我正在致力於導致速度差異。
我在Android應用程序中做了一些圖形工作,我從3個觸摸事件中找到了最小值/最大值。再次,邊緣案例如-0.0f
和不同的infinities是這裏不是一個問題。值在0.0f和3000f之間。
最初我使用Android設備監視器的方法分析工具對我的代碼進行了分析,該分析工具確實顯示出約5倍的差異。但是,這並不是像我現在學到的那樣微調代碼的最佳方式。
我加入了下面的代碼我的應用程序中,試圖獲得更好的數據:
long min1Times = 0L;
long min2Times = 0L;
...
// loop assigning touch values to v1, v2, v3
long start1 = System.nanoTime();
float min1 = min1(v1, v2, v3);
long end1 = System.nanoTime();
min1Times += end1 - start1;
long start2 = System.nanoTime();
float min2 = min2(v1, v2, v3);
long end2 = System.nanoTime();
min2Times += end2 - start2;
double ratio = (double) (min1Times)/(double) (min2Times);
Log.d("", "ratio: " + ratio);
打印帶有每個新觸摸事件正在運行的比率。當我在屏幕上旋動手指時,記錄的第一個比率爲0.0
或Infinity
或NaN
。這讓我覺得這個測試不是很準確地衡量時間。隨着更多數據的收集,比率往往會在.85
和1.15
之間變化。
你使用了什麼測試值?兩個或更多人平等的情況出現了嗎? – 2015-02-10 23:51:30
你使用的是什麼版本的java? – bhspencer 2015-02-10 23:52:08
你可以發佈你執行的測試嗎?如果有人跑了5毫秒。另一個在1毫秒內,它的確說得很多。 – 2015-02-10 23:53:28