簡體   English   中英

Java:序列化為字節緩沖區的最快方法

[英]Java: fastest way to serialize to a byte buffer

我需要在Java中使用必須盡可能快的序列化庫。 我們的想法是創建各種方法,這些方法將序列化指定的值及其關聯的鍵,並將它們放在字節緩沖區中。 必須創建包裝此緩沖區的多個對象,因為需要序列化的對象可能很多。

注意事項:我知道每個JVM中可能都沒有實現Unsafe類,但這不是問題。 過早優化:這個庫必須快速,這個序列化是它唯一必須做的事情。 一旦序列化的對象非常小(小於10k)但它們很多並且它們可以高達2Gb。 底層緩沖區可以擴展/縮小,但我將跳過實現細節,該方法類似於ArrayList實現中使用的方法。

澄清我的情況:我有各種各樣的方法,如

public void putByte(short key, byte value);
public void putInt(short key, int value);
public void putFloat(short key, float value);

... and so on...

這些方法將鍵和值附加到字節流中,所以如果我調用putInt(-1,1234567890),我的緩沖區將如下所示:(流是大端)

     key       the integer value  
[0xFF, 0xFF, 0x49, 0x96, 0x02, 0xD2]

最后,必須調用類似toBytes()的方法來返回一個字節數組,該數組是底層緩沖區的修剪(如果需要)版本。

現在,我的問題是:在java中執行此操作的最快方法是什么?

我用谷歌搜索並偶然發現了各種頁面(其中一些是關於SO的)我也做了一些基准測試(但我在基准測試中並不是很有經驗,這也是我要求更多有經驗的程序員幫助解決這個問題的原因之一話題)。

我想出了以下解決方案:

1-最直接的: 一個字節數組

如果我必須序列化一個int,它將如下所示:

public void putInt(short key, int value)
{
    array[index]   = (byte)(key >> 8);
    array[index+1] = (byte) key;
    array[index+2] = (byte)(value >> 24);
    array[index+3] = (byte)(value >> 16);
    array[index+4] = (byte)(value >> 8);
    array[index+5] = (byte) value;
}

2- A ByteBuffer (直接或字節數組包裝)

putInt方法如下所示

public void putInt(short key, int value)
{
   byteBuff.put(key).put(value);
}

3- 通過不安全的本機內存分配

使用Unsafe類我會在本機內存上分配緩沖區,因此putInt看起來像:

public void putInt(short key, int value)
{
  Unsafe.putShort(address, key);
  Unsafe.putInt(address+2, value);
}

4-通過new byte []分配,通過Unsafe訪問

我在用java編寫的lz4壓縮庫中看到了這個方法。 基本上,一旦字節數組被實例化,我就按以下方式寫入字節:

public void putInt(short key, int value)
{
   Unsafe.putShort(byteArray, BYTE_ARRAY_OFFSET + 0, key);
   Unsafe.putInt(byteArray, BYTE_ARRAY_OFFSET + 2, value);
}

這里的方法是簡化的,但基本的想法是顯示的,我還必須實現getter方法。 現在,自從我開始工作以來,我學到了以下幾點:

1-如果JVM是安全的,JVM可以刪除數組邊界檢查(例如,在for循環中,計數器必須小於數組的長度)2-交叉JVM內存邊界(從本機內存讀取/寫入)有成本。 3-調用本機方法可能會產生成本。 4-不安全的推桿和吸氣劑不在本機存儲器中進行邊界檢查,也不在常規陣列上進行邊界檢查。 5- ByteBuffers包裝一個字節數組(非直接)或普通本機存儲區(直接),因此情況2內部看起來像情況1或3。

我運行了一些基准測試(但正如我所說,我希望得到其他開發人員的意見/經驗)並且看起來案例4在閱讀時略微(幾乎等於)案例1並且寫作速度提高了約3倍。 似乎帶有Unsafe讀寫的for循環(案例4)將數組復制到另一個(在時間復制8個字節)比System.arraycopy更快。

長篇故事很短(對不起長篇文章):

情況1似乎很快,但是這樣我每次都要寫一個字節+屏蔽操作,這讓我覺得可能不安全,即使它是對本機代碼的調用可能會更快。

案例2類似於案例1和案例3,所以我可以跳過它(如果我遺漏了某些東西,請糾正我)

情況3似乎是最慢的(至少從我的基准測試),同樣,我需要從本機內存復制到字節數組,因為這必須是輸出。 但是, 在這里這個程序員聲稱這是迄今為止最快的方式。 如果我理解正確,我錯過了什么?

案例4這里支持)似乎是最快的。

選擇的數量和一些矛盾的信息讓我感到困惑,所以有人能澄清這些疑惑嗎?

我希望我寫下所有必要的信息,否則只是要求澄清。

提前致謝。

案例5: DataOutputStream寫入ByteArrayOutputStream.

親:已經完成了; 它和你在這里提到的任何東西一樣快; 所有原語都已實現。 反過來是從ByteArrayInputStream讀取的DataInputStream。

騙局:我無法想到。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM