2013-05-12 61 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