意外分配– JIT编译抖动
在研究ByteWatcher時 (請參閱我的上一篇 文章 ),我遇到了一些非常奇怪的事情。
這是實際的代碼段,用于找出特定線程上的分配量:
return (long) mBeanServer.invoke(name,GET_THREAD_ALLOCATED_BYTES,PARAMS,SIGNATURE );- 有關完整上下文,請參見此處 。
(ByteWatcher的工作方式是定期調用此方法以監視分配。)
需要注意的一個重要方面,尤其是當想要為程序的分配提供準確的數字時,就是調用上面的代碼本身–導致分配。
此調用引起的分配必須從返回的數中扣除,以便我們隔離程序導致的分配,即, 調用meanBeanServer =程序線程分配+調用開銷
我注意到的是,此分配量通常為336個字節。 但是,當我在循環中調用此方法時,發現了一些有趣的東西。 每隔一段時間,它將分配不同的金額。
對于此測試:
@Testpublic void testQuietMeasuringThreadAllocatedBytes() {ByteWatcherSingleThread am = new ByteWatcherSingleThread();System.out.println("MeasuringCostInBytes = " + am.getMeasuringCostInBytes());long[] marks = new long[1_000_000];for (int i = 0; i < 1_000_000; i++) {marks[i] = am.threadAllocatedBytes();}long prevDiff = -1;for (int i = 1; i < 1_000_000; i++) {long diff = marks[i] - marks[i - 1];if (prevDiff != diff)System.out.println("Allocation changed at iteration " + i + "->" + diff);prevDiff = diff;}}這是典型的結果:
MeasuringCostInBytes = 336 Allocation changed at iteration 1->336 Allocation changed at iteration 12->28184 Allocation changed at iteration 13->360 Allocation changed at iteration 14->336 Allocation changed at iteration 1686->600 Allocation changed at iteration 1687->336 Allocation changed at iteration 2765->672 Allocation changed at iteration 2766->336 Allocation changed at iteration 5458->496 Allocation changed at iteration 5459->336 Allocation changed at iteration 6213->656 Allocation changed at iteration 6214->336 Allocation changed at iteration 6535->432 Allocation changed at iteration 6536->336 Allocation changed at iteration 6557->8536 Allocation changed at iteration 6558->336 Allocation changed at iteration 7628->576 Allocation changed at iteration 7629->336 Allocation changed at iteration 8656->4432 Allocation changed at iteration 8657->336 Allocation changed at iteration 9698->968 Allocation changed at iteration 9699->336 Allocation changed at iteration 11881->1592 Allocation changed at iteration 11882->336 Allocation changed at iteration 12796->1552 Allocation changed at iteration 12797->336 Allocation changed at iteration 13382->456 Allocation changed at iteration 13383->336 Allocation changed at iteration 14844->608 Allocation changed at iteration 14845->336 Allocation changed at iteration 36685->304 Allocation changed at iteration 52522->336 Allocation changed at iteration 101440->400 Allocation changed at iteration 101441->336鑒于程序中肯定沒有分配,所以為什么同一調用有時分配不同的金額對我來說是一個謎。
總的來說,超過1,000,000次運行,該程序分配了大約25次不同的數量。 值得注意的是,經過10萬次迭代后沒有峰值。
我與亨氏·卡布茲(Heinz Kabutz)和克里斯·紐蘭(Chris Newland)分享了這個問題。 Chris注意到分配是由JIT編譯抖動引起的。 通過使用標志-Xint重新運行測試可以很清楚地看出這一點(僅以解釋模式運行,即沒有JIT編譯)。 現在只有2個峰值。
MeasuringCostInBytes = 336 Allocation changed at iteration 1->336 Allocation changed at iteration 12->28184 Allocation changed at iteration 13->360 Allocation changed at iteration 14->336同樣使用-Xcomp標志運行(僅編譯):
MeasuringCostInBytes = 336 Allocation changed at iteration 1->336 Allocation changed at iteration 12->29696 Allocation changed at iteration 13->360 Allocation changed at iteration 14->336因此,現在我們可以非常有信心,正是導致準入分配的JIT編譯抖動。
我不完全理解為什么會這樣,但是我想這是可以理解的。 為了彌補這一點,我在ByteWatcher的構造函數中引入了一個校準階段,Heinz進一步完善了該校準階段。
您可以在此處看到校準代碼,但是它包含兩個階段:
在構造函數中使用此代碼,即使沒有特殊標志運行也不會出現分配高峰。
結論
- JIT編譯抖動導致一些分配
- 在沒有編譯抖動(即僅解釋或僅編譯)的情況下運行程序會大大減少分配,但并不能完全消除分配。
- 在100k運行之后,分配停止,這表明需要100k運行才能停止抖動。 這很有趣,因為我們知道代碼應該在10k次迭代后進行編譯。
翻譯自: https://www.javacodegeeks.com/2015/09/an-unexpected-allocation-jit-compilation-jitter.html
總結
以上是生活随笔為你收集整理的意外分配– JIT编译抖动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux服务器安装图形化界面(linu
- 下一篇: DDOS网页端(ddos网页端大全)