C# 使用自定义序列化时OutOfMemory异常
在下面的代码中,我传递File对象的所有Block对象,并执行基于位转换的序列化。在某些情况下,我有OutOfMemory例外。有没有办法优化它 serialize() MemoryStream代替字节[],移位代替位转换器。GetBytes()方法: File.Serialize()文件 Block.Serialize()C# 使用自定义序列化时OutOfMemory异常,c#,.net,C#,.net,在下面的代码中,我传递File对象的所有Block对象,并执行基于位转换的序列化。在某些情况下,我有OutOfMemory例外。有没有办法优化它 serialize() MemoryStream代替字节[],移位代替位转换器。GetBytes()方法: File.Serialize()文件 Block.Serialize() 我想问的第一个问题是:数量和大小是多少?如果这些(当乘以)是大的,那么是的,它将咀嚼记忆。当然,序列化到大缓冲区总是会引起问题。最好看一下序列化到流的技术,这样可以使用一个
我想问的第一个问题是:数量和大小是多少?如果这些(当乘以)是大的,那么是的,它将咀嚼记忆。当然,序列化到大缓冲区总是会引起问题。最好看一下序列化到流的技术,这样可以使用一个中等大小的缓冲区。在您的例子中,可能每个“块”可以单独序列化并刷新为一个流,然后重复使用相同大小的缓冲区。就我个人而言,我尽量避免引入不必要的“块”——另一种技术是序列化到缓冲流,让它决定何时刷新到底层流
最后,BitConverter想要创建字节[],这总是让我失望。不管是谁写的API都需要一个严厉的谈话。适当的技术应该是有一个API,它接受缓冲区和偏移量,并写入现有的缓冲区。拨款少得多。我建议寻找不需要所有这些(公认是短暂的)分配的写作方法。这对于int/long etc很容易(您只需要使用移位操作),但是对于double etc,您需要不安全的代码或联合结构。我的第一个问题是:计数和大小是什么?如果这些(当乘以)是大的,那么是的,它将咀嚼记忆。当然,序列化到大缓冲区总是会引起问题。最好看一下序列化到流的技术,这样可以使用一个中等大小的缓冲区。在您的例子中,可能每个“块”可以单独序列化并刷新为一个流,然后重复使用相同大小的缓冲区。就我个人而言,我尽量避免引入不必要的“块”——另一种技术是序列化到缓冲流,让它决定何时刷新到底层流
最后,BitConverter想要创建字节[],这总是让我失望。不管是谁写的API都需要一个严厉的谈话。适当的技术应该是有一个API,它接受缓冲区和偏移量,并写入现有的缓冲区。拨款少得多。我建议寻找不需要所有这些(公认是短暂的)分配的写作方法。这对于int/long等来说很容易(您只需要使用移位操作),但是对于double等,您将需要不安全的代码或联合结构。Marc Gravell,首先感谢您的回答,count*size是大int。我实现了MemoryStream而不是byte[],移位而不是BitConverter.GetBytes()。同样的问题再次出现。我已经添加了我的实现,也许我有一些问题。@eugeneK当它爆炸时堆栈跟踪是什么?如果数据很大,那么
MemoryStream
仍然会遇到同样的问题:您可能需要在内存之外进行序列化。您希望它是什么尺寸的?请尝试序列化为文件。file.Size在8k到20MBSystem.OutOfMemoryException之间:引发了“System.OutOfMemoryException”类型的异常。在Entities.File.Serialize()@eugeneK ok;您作为容量
传递的值是多少?20MB对于内存工作来说并不是不合理的,但我怀疑您传递了更大的信息Arc Gravel,首先感谢您回答我,count*size是大整数。我实现了MemoryStream而不是byte[],移位而不是BitConverter.GetBytes()。同样的问题再次出现。我已经添加了我的实现,也许我有一些问题。@eugeneK当它爆炸时堆栈跟踪是什么?如果数据很大,那么MemoryStream
仍然会遇到同样的问题:您可能需要在内存之外进行序列化。您希望它是什么尺寸的?请尝试序列化为文件。file.Size在8k到20MBSystem.OutOfMemoryException之间:引发了“System.OutOfMemoryException”类型的异常。在Entities.File.Serialize()@eugeneK ok;您作为容量
传递的值是多少?20MB对于内存工作来说并不是不合理的,但我怀疑您传递了更大的内容
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;
}
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;
}
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;
}
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;
}