Я использую BinaryFormatter
для сериализации довольно простого многомерного массива с плавающей точкой, хотя я подозреваю, что проблема возникает с любыми примитивными типами. Мой многомерный массив содержит 10000x16 операций с плавающей запятой (160 КБ), а сериализация на моем ПК работает со скоростью ~ 8 МБ / с (60-секундная запись теста ~ 500 МБ на SSD-накопитель). Код:
Stopwatch stopwatch = new Stopwatch();
float[,] data = new float[10000 , 16]; // Two-dimensional array of 160,000 floats.
// OR
float[] data = new float[10000 * 16]; // One-dimensional array of 160,000 floats.
var formatter = new BinaryFormatter();
var stream = new FileStream("C:\\Temp\\test_serialization.data", FileMode.Create, FileAccess.Write);
// Serialize to disk the array 1000 times.
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < 1000; i++)
{
formatter.Serialize(stream, data);
}
stream.Close();
stopwatch.Stop();
TimeSpan ts = stopwatch.Elapsed;
// Format and display the TimeSpan value.
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds);
Console.WriteLine("Runtime " + elapsedTime);
var info = new FileInfo(stream.Name);
Console.WriteLine("Speed: {0:0.00} MB/s", info.Length / ts.TotalSeconds / 1024.0 / 1024.0);
Если сделать то же самое, но с использованием одномерного массива с плавающей запятой 160 КБ, то же количество данных будет сериализовано на диск со скоростью ~ 179 МБ / с. Более чем в 20 раз быстрее! Почему сериализация двумерного массива с использованием BinaryFormatter
работает так плохо? Базовое хранилище двух массивов в памяти должно быть идентичным. (Я сделал небезопасный собственный pin_ptr и копирование в и из 2D-массивов в C ++ / CLI).
Хакерским решением было бы реализовать ISerializable
и сделать memcopy (небезопасное / ptr закрепление / block memcopy) 2D-массив в 1D-массив и сериализовать его и размеры. Другой вариант, который я рассматриваю, - это переключение на protobuf-net
.