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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

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

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

使用 unsafe

總覽

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

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

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

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

測試

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

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

我還比較了使用Java 6更新45,Java 7更新79,Java 8更新51的情況,以了解不同發行版之間使用不同方法的變化。

逐字節處理

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

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

Java 6 Java 7 Java 8
字節緩沖區 15.8 16.9 16.4
不安全 17.2 17.5 16.9
在堆上 20.9 22.0 21.9


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

由int處理的int。

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

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


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

長期加工

盡管您可以編寫一個解析器一次讀取一個64位長的值,但我發現這比使用32位int值解析要困難得多。 我也沒有發現結果要快得多。 但是,只要在設計散列算法時考慮到這一點,就可以從讀取長值中受益于對數據結構進行散列。

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


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

在這種情況下,使用Unsafe的速度總是更快,無論您是否認為這種改進值得直接使用Unsafe帶來的風險是另一回事。

補充筆記

這些測試假設使用字節,整數或長整數的統一數據類型。

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

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

結論

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

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

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

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

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

總而言之,如果您可以用自然Java實現算法,那么它可能是最快也是最簡單的。 如果您需要混合使用數據類型或線程安全堆進行語法分析,那么仍然沒有很好的方法來使用自然Java。

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

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

使用 unsafe

總結

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

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