在.NET中使用BinaryFormatter序列化多维数组时出现性能问题
我正在使用在.NET中使用BinaryFormatter序列化多维数组时出现性能问题,.net,performance,serialization,multidimensional-array,binaryformatter,.net,Performance,Serialization,Multidimensional Array,Binaryformatter,我正在使用BinaryFormatter序列化一个相当简单的多维浮点数组,尽管我怀疑任何基元类型都会出现问题。我的多维阵列包含10000x16浮点(160k),在我的PC上串行化运行速度约为8 MB/s(60秒基准测试将约500 MB写入SSD驱动器)。代码: 秒表秒表=新秒表(); 浮动[,]数据=新浮动[10000,16];//160000个浮点数的二维数组。 //或 浮点[]数据=新浮点[10000*16];//160000个浮点数的一维数组。 var formatter=新的二进制格式化
BinaryFormatter
序列化一个相当简单的多维浮点数组,尽管我怀疑任何基元类型都会出现问题。我的多维阵列包含10000x16浮点(160k),在我的PC上串行化运行速度约为8 MB/s(60秒基准测试将约500 MB写入SSD驱动器)。代码:
秒表秒表=新秒表();
浮动[,]数据=新浮动[10000,16];//160000个浮点数的二维数组。
//或
浮点[]数据=新浮点[10000*16];//160000个浮点数的一维数组。
var formatter=新的二进制格式化程序();
var stream=new FileStream(“C:\\Temp\\test\u serialization.data”,FileMode.Create,FileAccess.Write);
//将阵列序列化到磁盘1000次。
秒表复位();
秒表。开始();
对于(int i=0;i<1000;i++)
{
序列化(流、数据);
}
stream.Close();
秒表;
TimeSpan ts=秒表。已用时间;
//格式化并显示TimeSpan值。
string elapsedTime=string.Format(“{0:00}:{1:00}:{2:00}.{3:000}”,
时,分,秒,
ts毫秒);
Console.WriteLine(“运行时”+elapsedTime);
var info=新文件信息(stream.Name);
WriteLine(“速度:{0:0.00}MB/s”,info.Length/ts.TotalSeconds/1024.0/1024.0);
做同样的事情,但使用160k浮点的一维数组,相同数量的数据以约179MB/s的速度序列化到磁盘。快20倍以上为什么使用BinaryFormatter
序列化二维数组的性能如此差?内存中两个数组的底层存储应该是相同的。(我已经在C++/CLI中完成了不安全的本机pin_ptr和向2D数组复制以及从2D数组复制)
黑客的解决方案是实现
ISerializable
,并将2D数组进行memcopy(不安全/ptr钉扎/block memcopy)操作,将其转换为1D数组,然后将其和维度序列化。我正在考虑的另一个选择是切换到protobuf net无需放弃数据结构或复制值,您可以使用以下代码实现相同的性能:
fixed (float* ptr = data)
{
byte* arr = (byte*)ptr;
int size = sizeof(float);
for (int j = 0; j < data.Length * size; j++)
{
stream.WriteByte(arr[j]);
}
}
固定(浮动*ptr=数据)
{
字节*arr=(字节*)ptr;
int size=sizeof(float);
对于(int j=0;j
基本上,您是自己编写输出流的,正如您所说的,您只是将float[]用作byte[],因为内存结构是相同的
反序列化是相同的,您可以使用StreamReader来读取浮点值,也可以使用不安全的方法将数据加载到内存中
如果您有这样的基本需求,我强烈反对使用protobuf.net。开发速度减慢,而且只基于一个人,因此风险很大(当我试图帮助解决性能问题时,他甚至懒得看我提出的更改)。
然而,如果您想序列化复杂的数据结构,二进制序列化不会比protobuf慢很多,尽管后者在.NET平台上没有得到官方支持(Google发布了Java、Python和C++的代码)。它在反射上花费了太多时间。数组很麻烦,因为它们在.NET中是协变的。您可以使用锯齿阵列加快速度。
fixed (float* ptr = data)
{
byte* arr = (byte*)ptr;
int size = sizeof(float);
for (int j = 0; j < data.Length * size; j++)
{
stream.WriteByte(arr[j]);
}
}