簡體   English   中英

用Java序列化Longs數組的最緊湊方法

[英]Most Compact way to Serialize an Array of Longs in Java

我有很多longs long[]數組,我需要對其進行序列化並將它們保存到磁盤以供以后讀取,請注意,每個數組都需要不時修改,但是在頻繁讀取的情況下寫入並不頻繁。 通常,我的應用程序只需要同時將少數幾個加載到內存中。 在將每個陣列存儲回磁盤之前,可以在內存中批量進行每個陣列的編輯。 每個陣列具有數百至一百萬個元素。 在我的應用程序中,將所需的數組加載到內存中的速度非常快至關重要。

在我的情況下,每個數組中的長值平均而言彼此非常接近,即,從一個值到下一個值的差(如果在單個數組中排序)小於整數。

采用此處所示的特里樣結構的解決方案似乎不適用於我的情況,因為在該解決方案中,數組值是已知的,並且永遠不會改變。

這里的解決方案告訴我使用ByteBufferLongBuffer來加速I / O,但是我的想法是也以最緊湊的方式存儲這樣的數組,以便通過減少存儲空間來加快將它們加載到主存儲器中所需的時間。我需要閱讀的大小。 直覺是存儲排序的值,並存儲一個值和下一個值之間的差,該差值(通常)在Integer范圍內,因此占用的空間較小。 但是由於並非總是如此,所以我仍然不能將所有值都存儲為整數,因此這個方向似乎沒有希望。 我是否缺少明顯的東西?

在I / O時間內,最有效的方法是什么?


編輯通常,僅將性能視為I / O時間,而不考慮磁盤空間, 此問題有更好的答案。

您似乎非常重視緊湊性和速度。 要使它們達到真正的最低水平,將需要進行大量優化。 在很多情況下,我的意思是比您典型的開發人員要處理的更多。

與其自己做,不如研究現有的數據庫解決方案。 這些數據庫的開發人員花了多年的時間來理解執行這些操作的最有效方法,並且開銷比您想象的要低得多。 更不用說您免費獲得的正確性和可靠性。

我將使用庫存數據庫解決方案(只需撥出mysql,maria或postgres實例,然后將其發送到城鎮),看看是否滿足您的性能指標。 如果不是,請找出不符合的特定指標,然后將其調整為適合的指標。 您要查詢的內容需要您對數據有專門的知識,並且需要具備進行數據實驗的能力,這是Internet上沒有人可以做的(或者應該免費做)。

您仍然可以將數組元素編碼為int,並添加以下內容:

    // The first int is the array length
    buf.putInt(array.length);

    long prev = 0;
    for (long next : array) {
        if (next - prev <= Integer.MAX_VALUE) {
            // Delta is small. Change the sign and encode as int.
            buf.putInt((int) (prev - next));
        } else {
            // Delta does not fit in 31 bits. Encode two parts of long.
            buf.putInt((int) (next >>> 32));
            buf.putInt((int) next);
        }
        prev = next;
    }

請注意,31位增量將被編碼為負int 在解碼期間,最高(符號)位將指示該值是delta還是原始63位long 在后一種情況下,您讀取了下一個int並由兩個int組成一個63位long

    // The first int is the array length
    long[] array = new long[buf.getInt()];

    long next = 0;
    for (int i = 0; i < array.length; i++) {
        int delta = buf.getInt();
        if (delta <= 0) {
            // Negative sign means the value is encoded as int delta.
            next -= delta;
        } else {
            // Positive sign means the value is encoded as raw long.
            // Read the second (lower) part of long and combine it with the higher part.
            next = (long) delta << 32 | (buf.getInt() & 0xffffffffL);
        }
        array[i] = next;
    }

如果數組中的所有值均為正,則此方法有效。 如果同時存在正值和負值,則將它們分成兩個數組。


順便說一句,如果鄰居值接近,像GZIP這樣的流式壓縮(或者像LZ4這樣的更快的壓縮方法)也可以很好地工作。 參見GZIPOutputStream

暫無
暫無

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

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