绩效工作流_流绩效–您的想法
績效工作流
上周,我介紹了一些有關Java 8流性能的基準測試結果。 你們和gal足夠有興趣留下一些想法,還有哪些可以介紹。
這就是我所做的,這里是結果。
總覽
最后一篇文章的序言也適用于此。 閱讀它,以找出所有數字為何撒謊,我如何提出這些數字以及如何復制它們。
我在GitHub上的代碼中添加了一個新類CommentOperationsBenchmark ,其中包括本文中討論的基準。 我還更新了Google電子表格,以包括新的數字。
比較的影響
真好 長期以來一直在說要像Ansi C一樣寫Java更快(數組而不是列表)。
兔子洞的下一步是…
嘗試{for(int i = 0 ;;)做東西; } catch(ex ex ex){等等! }
根本不檢查循環,僅捕獲異常,非常適合高清像素處理。
混沌實驗室
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;} }也許他們應該停止,因為它看起來并不能改善性能:
| 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 |
看來,用于打破循環的機制沒有可衡量的影響。 這是有道理的,因為展開循環可以避免大多數比較,并且引發異常的代價在幾微秒的范圍內 ,因此比此處發生的情況小幾個數量級。
這是假設編譯器確實有更多技巧。 也許它在更深層次上理解循環,并且JIT將這兩種方法編譯為相同的指令。
附帶說明一下:看看在循環之后array_max_forWithException如何沒有return語句?
事實證明Java編譯器可以識別簡單的無限循環 。 哇! 因此,它知道具有有限計算的每個代碼路徑都會返回,而不關心無限的代碼路徑。
歸結為以下內容:
一無所有
public int infiniteLoop() {for(;;); }您永遠不會停止學習……
作業的影響
[F]或“最大”測試我希望每次迭代更新局部變量都會有一些阻力。 我很好奇是否發現最小值在可比較的時間內運行。b0b0b0b
這是指所有測試都是在數組或列表上運行的,這些數組或列表的元素等于結構中的索引,即[0,1,2,…,n-1]。 因此,找到最大值確實需要n個分配。
那找到一個只需要分配一次的最小值呢?
| 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 |
不,沒有區別。 我的猜測是,由于流水線作業,分配實際上是免費的。
由Khalid Albaih在CC-BY 2.0下發布 –視角被我改變了。
拳擊的影響
關于拳擊有兩條評論。
最好看到Integer []實現,以確認對拳擊的懷疑。
黏黏的
好吧,讓我們這樣做。 以下數字顯示了int [],Integer []和List <Integer>上的for循環和for-each循環:
| 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 |
我們可以清楚地看到,運行時的主要指標是數據結構是包含基元還是對象。 但是將Integer數組包裝到列表中會導致額外的速度降低。
Yann Le Tallec也對拳擊發表了評論:
intList.stream()。max(Math :: max); 造成不必要的拆箱。
intList.stream()。mapToInt(x-> x).max(); 速度大約是陣列版本的兩倍。
揚·勒·塔雷克(Yann Le Tallec)
此聲明與我們在上一篇文章中得出的結論一致:盡快對流進行拆箱可提高性能。
只是再次檢查:
| 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%) |
這似乎證實了這一說法。 但是結果看起來非常可疑,因為錯誤很大。 使用不同的設置反復運行這些基準測試顯示了一種模式:
- 存在兩種性能水平,一種是?3.8 ns / op,一種是?7.5 ns / op。
- 未裝箱的流只表現更好。
- 盒裝流的單個迭代通常在這兩個級別中的任何一個上運行,但很少在其他時間進行。
- 大多數情況下,行為只會在分支之間改變(即從一組迭代到下一組)。
這一切都令人懷疑我的測試設置存在問題。 聽到任何想法的人,我會很有趣。
更新資料
Yann確實有一個想法,并指出了這個有趣的問題和有關StackOverflow的出色答案 。 現在,我最好的猜測是裝箱的流可以在未裝箱的水平上運行,但可能會因意外的非優化而失敗。
硬件的影響
Redditor robi2106在他的“ i5-4310 @ 2Ghz w 8GB DDR2”上運行了500,000個元素的套件。 我將結果添加到電子表格中 。
很難從數據中得出結論。 Robi指出“在這2.5個小時中我也沒有停止使用我的系統”,這也許可以解釋巨大的誤差范圍。 他們的平均年齡是我的23倍,平均是我的168倍。 (另一方面,我也繼續使用我的系統,但是負載很低。)
如果斜視一下,您可以推斷出i5-4310在簡單計算上會稍快一些,但在更復雜的計算上會落后一些。 考慮到i7-4800的內核數量是原來的兩倍,通常可以達到并行性能。
語言的影響
這與Scala(帶有@specialized)相比,會很有趣。
加密貨幣6
我仍然沒有嘗試使用Scala,也不想為一個基準測試而努力。 也許經驗更豐富或更鮮美的人可以嘗試一下?
反射
在解釋這些數字時,請記住,這些迭代執行了非常便宜的操作。 上次我們發現,已經很簡單的算術運算會導致足夠的CPU負載, 幾乎完全抵消了迭代機制的差異 。 因此,像往常一樣,不要過早優化!
總之,我會說:沒有新發現。 但是,我很喜歡與您討論您的想法,如果您有更多想法,請發表評論。 甚至更好的是,自己嘗試一下并發布結果。
翻譯自: https://www.javacodegeeks.com/2015/09/stream-performance-your-ideas.html
績效工作流
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的绩效工作流_流绩效–您的想法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓手机验机软件(安卓手机验机)
- 下一篇: 通用编程_通用编程准则