日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用Unsafe真的是关于速度或功能吗?

發(fā)布時間:2023/12/3 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Unsafe真的是关于速度或功能吗? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

總覽

大約6年前,我開始使用一個類,直到那時,它只是一個好奇心sun.misc.Unsafe 。 我曾使用它進行反序列化和重新拋出Exception,但沒有使用它的全部功能或公開談論它。

我看到的第一個嚴重使用Unsafe的開源庫是Disruptor。 這使我感到鼓舞,它可以在穩(wěn)定的庫中使用。 大約一年后,我發(fā)布了我的第一個開源庫SharedHashMap(后來的Chronicle Map)和Chronicle(后來的Chronicle Queue)。 這使用Unsafe來訪問Java 6中的堆外內存。這對堆外內存的性能產生了真正的影響,但更重要的是,我可以使用共享內存來做。 即跨JVM共享的數(shù)據(jù)結構。

但是今天有什么不同呢? 使用不安全總是更快嗎?

我們正在尋找引人注目的性能差異。 如果差異不那么明顯,則使用盡可能簡單的代碼更有意義。 即使用自然的Java。

測試

在這些測試中,我對源自堆外內存的數(shù)據(jù)進行了簡單的累積。 這是一個簡單的測試,它對解析數(shù)據(jù)(或哈希數(shù)據(jù))建模,這些數(shù)據(jù)是從堆(例如,TCP連接或文件系統(tǒng))中生成的。 數(shù)據(jù)大小為128個字節(jié)。 下面的結果可能受數(shù)據(jù)大小的影響,但這被認為具有代表性。

我看的是不同大小的訪問,一次訪問一個字節(jié),一次int或一次long。 我還研究了使用ByteBuffer還是在堆上復制數(shù)據(jù)并使用自然Java(我假設這是大多數(shù)程序執(zhí)行此操作的方式)。

我還比較了使用Java 6更新45,Java 7更新79,Java 8更新51的情況,以查看不同版本之間使用不同方法的方式。

逐字節(jié)處理

處理器設計中真正改善的一點是它可以復制大型數(shù)據(jù)塊的速度。 這意味著復制大量數(shù)據(jù),以便可以更有效地處理它是有意義的。 也就是說,冗余副本可能足夠便宜,從而可以帶來更快的解決方案。

逐字節(jié)處理就是這種情況。 在此示例中,“在堆上”包括在處理之前在堆上復制數(shù)據(jù)的副本。 這些數(shù)字是在i7-3790X上每微秒的操作數(shù)。

Java 6 Java 7 Java 8
字節(jié)緩沖區(qū) 15.8 16.9 16.4
不安全 17.2 17.5 16.9
在堆上 20.9 22.0 21.9


這樣做的重要意義在于,“堆上”不僅使用自然Java,而且在所有三個版本的Java中都是最快的。最可能的解釋是,JIT具有在堆上情況下可以進行的優(yōu)化。如果您直接或間接使用不安全,則不會這樣做。

由int處理int。

解析詳細的有線協(xié)議的更快方法是一次讀取一個int。 例如,您可以通過一次讀取一個int而不是單獨查看每個字節(jié)來編寫已知格式的XML解析器。 這樣可以將解析速度提高2到3倍。 這種方法最適合已知結構的內容。

Java 6 Java 7 Java 8
字節(jié)緩沖區(qū) 12.6 36.2 35.1
不安全 44.5 52.7 54.7
在堆上 46.0 49.5 56.2


同樣,這是i7-3790X上每微秒的操作。 有趣的是,在復制后使用自然Java大約與使用Unsafe一樣快。 對于此用例,也沒有令人信服的理由使用Unsafe。

長期加工

雖然您可以編寫一個解析器一次讀取一個64位長的值,但我發(fā)現(xiàn)這比使用32位int值解析要困難得多。 我也沒有發(fā)現(xiàn)結果要快得多。 但是,只要設計散列算法時就考慮到了這一點,則對散列數(shù)據(jù)結構進行散列可以受益于讀取??長值。

Java 6 Java 7 Java 8
字節(jié)緩沖區(qū) 12.1 56.7 53.3
不安全 66.7 83.0 94.9
在堆上 60.9 61.2 70.0


有趣的是,使用ByteBuffer的速度提高了多少。 最可能的解釋是在ByteBuffer中增加了將little-endian交換為默認big-endian的優(yōu)化。 x86有一條交換字節(jié)的指令,但是我懷疑Java 6沒有使用它,而是使用了更昂貴的移位操作。 為了能夠確認這一點,將需要進行更多測試并檢查生成的匯編代碼。

在這種情況下,使用“不安全”的速度始終更快,無論您是否認為這種改進值得直接使用“不安全”的風險是另一回事。

補充筆記

這些測試假設使用字節(jié),整數(shù)或長整數(shù)的統(tǒng)一數(shù)據(jù)類型。

在大多數(shù)實際情況下,這些數(shù)據(jù)類型是結合在一起的,這就是在堆上掙扎的地方。 例如,如果您需要解析字節(jié),短褲,整數(shù),長整數(shù),浮點數(shù),雙精度數(shù)的任意組合。 ByteBuffer是執(zhí)行此操作的好方法,但是在每種情況下,它都是最慢的選項。 只有不安全才能讓您靈活地混合和匹配類型,而不會產生開銷。

對于這些混合類型,很難對堆進行公平的測試,因為自然Java不直接支持這些操作。

結論

即使性能是您最關心的問題,在某些情況下,自然Java的性能還是更好,或與使用Unsafe一樣快。 它經常執(zhí)行ByteBuffer,因為JIT可以更好地優(yōu)化開銷,例如對自然Java代碼進行邊界檢查。

自然的Java代碼依賴于我們可以將數(shù)據(jù)建模為byte [],int []或long []的事實。 沒有數(shù)組或原始類型混合的選項。

自然Java掙扎的地方在于對這兩種方式的支持

  • 不同原始類型的任意組合,例如字節(jié),整數(shù),長整數(shù),雙精度數(shù)。
  • 共享/本機內存上的線程安全操作。

不幸的是,由于缺乏自然Java支持,因此很難創(chuàng)建公平的基準來比較性能。

總之,如果您可以用自然Java實現(xiàn)算法,則它可能是最快也是最簡單的。 如果您需要混合使用數(shù)據(jù)類型或線程安全堆來解析數(shù)據(jù),那么仍然沒有很好的方法來使用自然Java。

注意:這是Java 9中的VarHandles應該能夠提供幫助的區(qū)域,因此請觀看此空間以獲取VarHandles的更新。

翻譯自: https://www.javacodegeeks.com/2015/08/is-using-unsafe-really-about-speed-or-functionality.html

總結

以上是生活随笔為你收集整理的使用Unsafe真的是关于速度或功能吗?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。