2013-05-12 66 views
1

在以下代碼中,我通過File對象的所有Block對象並執行基於BitConverted的序列化。在某些情況下,我有OutOfMemory異常。有什麼辦法可以優化它嗎?使用自定義序列化時的OutOfMemory異常

File.Serialze();

public byte[] Serialize() 
{ 
    byte[] bytes = new byte[Blocks.Count * Block.Size]; 

    for (int i = 0; i < Blocks.Count; i++) 
    { 
     Block block = Blocks[i]; 
     Buffer.BlockCopy(block.Serialize(), 0, bytes, i * Block.Size, Block.Size); 
    } 
    return bytes; 
} 

Block.Serialize()

public byte[] Serialize() 
{ 
    byte[] bytes = new byte[Size]; 

    Buffer.BlockCopy(BitConverter.GetBytes(fid), 0, bytes, 0, sizeof(long)); 
    Buffer.BlockCopy(BitConverter.GetBytes(bid), 0, bytes, sizeof(long), sizeof(long)); 
    Buffer.BlockCopy(BitConverter.GetBytes(oid), 0, bytes, sizeof(long) * 2, sizeof(long)); 
    Buffer.BlockCopy(BitConverter.GetBytes(iid), 0, bytes, sizeof(long) * 3, sizeof(long)); 
    Buffer.BlockCopy(BitConverter.GetBytes(did), 0, bytes, sizeof(long) * 4, sizeof(long)); 

    return bytes; 
} 

的MemoryStream代替字節[]和代替移位BitConverter.GetBytes()方法:

File.Serialize()

public MemoryStream Serialize() 
{ 
    MemoryStream fileMemoryStream = new MemoryStream(Blocks.Count * Block.Size); 
    foreach (Block block in Blocks) 
    { 
     using (MemoryStream blockMemoryStream = block.Serialize()) 
     { 
      blockMemoryStream.WriteTo(fileMemoryStream); 
     } 
    } 

    return fileMemoryStream; 
} 

Block.Serialize()

public MemoryStream Serialize() 
{ 
    MemoryStream memoryStream = new MemoryStream(Size); 

    memoryStream.Write(ConvertLongToByteArray(fid), 0, sizeof(long)); 
    memoryStream.Write(ConvertLongToByteArray(bid), 0, sizeof(long)); 
    memoryStream.Write(ConvertLongToByteArray(oid), 0, sizeof(long)); 
    memoryStream.Write(ConvertLongToByteArray(iid), 0, sizeof(long)); 
    memoryStream.Write(ConvertLongToByteArray(did), 0, sizeof(long)); 

    return memoryStream; 
} 

    private byte[] ConvertLongToByteArray(long number) 
    { 
     byte[] bytes = new byte[8]; 
     bytes[7] = (byte)((number >> 56) & 0xFF); 
     bytes[6] = (byte)((number >> 48) & 0xFF); 
     bytes[5] = (byte)((number >> 40) & 0XFF); 
     bytes[4] = (byte)((number >> 32) & 0XFF); 
     bytes[3] = (byte)((number >> 24) & 0xFF); 
     bytes[2] = (byte)((number >> 16) & 0xFF); 
     bytes[1] = (byte)((number >> 8) & 0XFF); 
     bytes[0] = (byte)((number & 0XFF)); 

     return bytes; 
    } 

回答

1

我想要的第一個問題是:什麼是計數和大小?如果這些(當乘以)大,那麼是它會咀嚼記憶。當然,序列化成一個大緩衝區總是會引起問題。最好查看序列化到Stream的技術,然後使用一箇中等大小的緩衝區。在你的情況下,也許每個「塊」可以分別序列化,並刷新到一個流,然後重新使用相同的中等大小的緩衝區。我個人儘量避免引入不必要的「塊」 - 另一種技術是序列化到緩衝流,並讓它決定何時刷新到底層流。

最後,BitConverter想要創建byte []總是令我失望。誰寫這個API需要一個嚴厲的談話。適當的技術將會有一個API來獲取緩衝區和偏移量,並寫入現有的緩衝區。分配的數量少得多。我建議在沒有所有這些(確實是短暫的)分配的情況下尋找寫作方法。這對於int/long等很簡單(你只需要使用shift操作) - 但是對於double等,你將需要不安全的代碼或union-struct。

+0

Marc Gravell,首先謝謝你回答我和計數*的大小是很大的。我已經實現了MemoryStream而不是byte [],而不是BitConverter.GetBytes()。同樣的問題再次出現。我已經添加了我的實現,也許我在那裏遇到了一些問題。 – eugeneK 2013-05-13 08:38:36

+0

@eugeneK什麼是爆炸時的堆棧跟蹤?如果數據是* large *,那麼'MemoryStream'仍然會有相同的問題:您可能需要序列化內存外*。你期待它是什麼樣的大小?嘗試序列化到文件。 – 2013-05-13 08:44:39

+0

File.Size介於8k到20MB之間 – eugeneK 2013-05-13 08:59:47