流绩效–您的想法
上周,我介紹了一些有關(guān)Java 8流性能的基準(zhǔn)測(cè)試結(jié)果。 你們和gal足夠感興趣,可以留下一些想法,還有哪些可以介紹。
這就是我所做的,這是結(jié)果。
總覽
最后一篇文章的序言也適用于此。 閱讀它,以找出所有數(shù)字為何撒謊,我如何提出這些數(shù)字以及如何復(fù)制它們。
我在GitHub上的代碼中添加了一個(gè)新類(lèi)CommentOperationsBenchmark ,其中包括本文中討論的基準(zhǔn)。 我還更新了Google電子表格,以包括新的數(shù)字。
比較的影響
真好 長(zhǎng)期以來(lái)一直在說(shuō)將Java寫(xiě)成Ansi C更快(數(shù)組而不是列表)。
兔子洞的下一步是…
嘗試{for(int i = 0 ;;)做東西; } catch(ex ex ex){等等! }
根本不檢查循環(huán),僅捕獲異常,非常適合高清像素處理。
混沌實(shí)驗(yàn)室
WAT? 人們正在這樣做嗎?
打破ArrayIndexOotOfBoundsException
public int array_max_forWithException() {int m = Integer.MIN_VALUE;try {for (int i = 0; ; i++)if (intArray[i] > m)m = intArray[i];} catch (ArrayIndexOutOfBoundsException ex) {return m;} }也許他們應(yīng)該停下來(lái),因?yàn)樗雌饋?lái)并不能改善性能:
| array_max_for | 0.261 | 0.261 | 0.277 | 0.362 | 0.347 | 0.380 |
| array_max_forWithException | 0.265 | 0.265 | 0.273 | 0.358 | 0.347 | 0.386 |
看來(lái),用于打破循環(huán)的機(jī)制沒(méi)有可衡量的影響。 這是有道理的,因?yàn)檠h(huán)展開(kāi)可以避免大多數(shù)比較,并且引發(fā)異常的代價(jià)在幾微秒的范圍內(nèi) ,因此比此處發(fā)生的情況小幾個(gè)數(shù)量級(jí)。
這是假設(shè)編譯器確實(shí)有更多技巧。 也許它更深刻地理解了循環(huán),并且JIT將這兩種方法編譯為相同的指令。
附帶說(shuō)明一下:看看循環(huán)后array_max_forWithException如何沒(méi)有return語(yǔ)句?
事實(shí)證明Java編譯器可以識(shí)別簡(jiǎn)單的無(wú)限循環(huán) 。 哇! 因此,它知道具有有限計(jì)算的每個(gè)代碼路徑都會(huì)返回,而不關(guān)心無(wú)限的代碼路徑。
歸結(jié)為以下內(nèi)容:
一無(wú)所有
public int infiniteLoop() {for(;;); }您永不停止學(xué)習(xí)……
作業(yè)的影響
[F]或“最大”測(cè)試我希望每次迭代更新局部變量都會(huì)有一些阻力。 我很好奇尋找最小值是否在可比較的時(shí)間內(nèi)運(yùn)行。b0b0b0b
這是指所有測(cè)試都是在數(shù)組或列表上運(yùn)行的,這些數(shù)組或列表的元素等于結(jié)構(gòu)中的索引,即[0,1,2,…,n-1]。 因此,找到最大值確實(shí)需要n個(gè)分配。
那找到一個(gè)只需要一個(gè)作業(yè)的最小值呢?
| array_max_for | 0.261 | 0.261 | 0.277 | 0.362 | 0.347 | 0.380 |
| array_min_for | 0.264 | 0.260 | 0.280 | 0.353 | 0.348 | 0.359 |
不,沒(méi)有區(qū)別。 我的猜測(cè)是,由于流水線作業(yè),分配實(shí)際上是免費(fèi)的。
由Khalid Albaih在CC-BY 2.0下發(fā)布 –我改變了視野。
拳擊的影響
關(guān)于拳擊有兩條評(píng)論。
最好看到Integer []實(shí)現(xiàn),以確認(rèn)對(duì)拳擊的懷疑。
黏黏的
好吧,讓我們這樣做。 以下數(shù)字顯示了int [],Integer []和List <Integer>上的for循環(huán)和for-each循環(huán):
| array_max_for | 0.261 | 0.261 | 0.277 | 0.362 | 0.347 | 0.380 |
| array_max_forEach | 0.269 | 0.262 | 0.271 | 0.349 | 0.349 | 0.356 |
| boxedArray_max_for | 0.804 | 1.180 | 1.355 | 1.387 | 1.306 | 1.476 |
| boxedArray_max_forEach | 0.805 | 1.195 | 1.338 | 1.405 | 1.292 | 1.421 |
| list_max_for | 0.921 | 1.306 | 1.436 | 1.644 | 1.509 | 1.604 |
| list_max_forEach | 1.042 | 1.472 | 1.579 | 1.704 | 1.561 | 1.629 |
我們可以清楚地看到,運(yùn)行時(shí)的主要指標(biāo)是數(shù)據(jù)結(jié)構(gòu)是包含基元還是對(duì)象。 但是將Integer數(shù)組包裝到列表中會(huì)導(dǎo)致額外的速度降低。
Yann Le Tallec也對(duì)拳擊發(fā)表了評(píng)論:
intList.stream()。max(Math :: max); 造成不必要的拆箱。
intList.stream()。mapToInt(x-> x).max(); 速度大約是陣列版本的兩倍。
揚(yáng)·勒·塔雷克(Yann Le Tallec)
此聲明與我們?cè)谏弦黄恼轮械贸龅慕Y(jié)論一致:盡快對(duì)流取消裝箱可能會(huì)提高性能。
只是再次檢查:
| boxedArray_max _stream | 4.231(43%) | 5.715(3%) | 5.004(27%) | 5.461(53%) | 5.307(56%) | 5.507(54%) |
| boxedArray_max _stream_unbox | 3.367(<1%) | 3.515(<1%) | 3.548(2%) | 3.632(1%) | 3.547(1%) | 3.600(2%) |
| list_max _stream | 7.230(7%) | 6.492(<1%) | 5.595(36%) | 5.619(48%) | 5.852(45%) | 5.631(51%) |
| list_max _stream_unbox | 3.370(<1%) | 3.515(1%) | 3.527(<1%) | 3.668(3%) | 3.807(2%) | 3.702(5%) |
這似乎證實(shí)了這一說(shuō)法。 但是結(jié)果看起來(lái)非常可疑,因?yàn)殄e(cuò)誤很大。 使用不同的設(shè)置反復(fù)運(yùn)行這些基準(zhǔn)測(cè)試顯示了一種模式:
- 存在兩種性能水平,一種是?3.8 ns / op,一種是?7.5 ns / op。
- 未裝箱的流只表現(xiàn)更好。
- 盒裝流的單個(gè)迭代通常在這兩個(gè)級(jí)別中的任何一個(gè)上運(yùn)行,但很少在另一個(gè)時(shí)間運(yùn)行。
- 大多數(shù)情況下,行為只會(huì)在分支之間變化(即從一組迭代到下一組)。
這一切都令人懷疑我的測(cè)試設(shè)置存在問(wèn)題。 聽(tīng)到任何想法的人,我會(huì)很有趣。
更新資料
Yann確實(shí)有一個(gè)主意,并指出了這個(gè)有趣的問(wèn)題和有關(guān)StackOverflow的出色答案 。 現(xiàn)在,我最好的猜測(cè)是,裝箱的流可以在未裝箱的水平上運(yùn)行,但可能會(huì)因意外的非優(yōu)化而祈禱。
硬件的影響
Redditor robi2106在其“ i5-4310 @ 2Ghz w 8GB DDR2”上運(yùn)行了500'000個(gè)元素的套件。 我將結(jié)果添加到電子表格中 。
很難從數(shù)據(jù)中得出結(jié)論。 Robi指出“在這2.5個(gè)小時(shí)中我也沒(méi)有停止使用我的系統(tǒng)”,這也許可以解釋巨大的誤差范圍。 他們的平均年齡是我的23倍,平均是我的168倍。 (另一方面,我也繼續(xù)使用我的系統(tǒng),但是負(fù)載很低。)
如果斜視一下,可以推斷出i5-4310在簡(jiǎn)單的計(jì)算上會(huì)稍快一些,但在更復(fù)雜的計(jì)算上會(huì)落后一些。 考慮到i7-4800的內(nèi)核數(shù)量是原來(lái)的兩倍,通常可以達(dá)到并行性能。
語(yǔ)言的影響
這與Scala(帶有@specialized)相比,會(huì)很有趣。
加密貨幣6
我仍然沒(méi)有嘗試使用Scala,也不想為一個(gè)基準(zhǔn)測(cè)試而努力。 也許經(jīng)驗(yàn)更豐富或更鮮美的人可以嘗試一下?
反射
在解釋這些數(shù)字時(shí),請(qǐng)記住,這些迭代執(zhí)行了非常便宜的操作。 上次我們發(fā)現(xiàn)已經(jīng)很簡(jiǎn)單的算術(shù)運(yùn)算會(huì)導(dǎo)致足夠的CPU負(fù)載, 幾乎完全抵消了迭代機(jī)制的差異 。 因此,像往常一樣,不要過(guò)早優(yōu)化!
總而言之,我會(huì)說(shuō):沒(méi)有新發(fā)現(xiàn)。 但是,我很喜歡與您討論您的想法,如果您有更多想法,請(qǐng)發(fā)表評(píng)論。 甚至更好的是,自己嘗試一下并發(fā)布結(jié)果。
翻譯自: https://www.javacodegeeks.com/2015/09/stream-performance-your-ideas.html
總結(jié)
- 上一篇: eclipselink_Java EE
- 下一篇: 在没有复杂插件的情况下从Eclipse启