Сериализация и десериализация словарь V.Large в C#

У нас есть v.large Dictionary<long,uint> (несколько миллионов записей) как часть высокопроизводительного приложения C#. Когда приложение закрывается, мы сериализируем словарь к дисковому использованию BinaryFormatter и MemoryStream.ToArray(). Сериализация возвращается приблизительно через 30 секунд и производит файл приблизительно 200 МБ в размере. Когда мы затем пытаемся десериализовать словарь с помощью следующего кода:

BinaryFormatter bin = new BinaryFormatter();
Stream stream = File.Open("filePathName", FileMode.Open);
Dictionary<long, uint> allPreviousResults =
    (Dictionary<long, uint>)bin.Deserialize(stream);
stream.Close();

Требуется приблизительно 15 минут для возврата. Мы попробовали альтернативы, и медленная часть определенно bin.Derserialize(stream), т.е. байты читаются из жесткого диска (высокопроизводительный SSD) за менее чем 1 секунду.

Может кто-то указывать на то, что мы делаем неправильно, поскольку мы хотим время загрузки на том же порядке как сэкономить время.

С уважением, Marc

11
задан LukeH 25 June 2010 в 12:43
поделиться

4 ответа

Вы можете оформить заказ protobuf-net или просто сериализовать его самостоятельно что, вероятно, будет самым быстрым из возможных.

class Program
{
    public static void Main()
    {
        var dico = new Dictionary<long, uint>();
        for (long i = 0; i < 7500000; i++)
        {
            dico.Add(i, (uint)i);
        }

        using (var stream = File.OpenWrite("data.dat"))
        using (var writer = new BinaryWriter(stream))
        {
            foreach (var key in dico.Keys)
            {
                writer.Write(key);
                writer.Write(dico[key]);
            }
        }

        dico.Clear();
        using (var stream = File.OpenRead("data.dat"))
        using (var reader = new BinaryReader(stream))
        {
            while (stream.Position < stream.Length)
            {
                var key = reader.ReadInt64();
                var value = reader.ReadUInt32();
                dico.Add(key, value);
            }
        }
    }
}

размер результирующего файла => 90 МБ (85,8 МБ).

11
ответ дан 3 December 2019 в 06:20
поделиться

Просто чтобы показать аналогичную сериализацию (к принятому ответу) через protobuf-net:

using System.Collections.Generic;
using ProtoBuf;
using System.IO;

[ProtoContract]
class Test
{
    [ProtoMember(1)]
    public Dictionary<long, uint> Data {get;set;}
}

class Program
{
    public static void Main()
    {
        Serializer.PrepareSerializer<Test>();
        var dico = new Dictionary<long, uint>();
        for (long i = 0; i < 7500000; i++)
        {
            dico.Add(i, (uint)i);
        }
        var data = new Test { Data = dico };
        using (var stream = File.OpenWrite("data.dat"))
        {
            Serializer.Serialize(stream, data);
        }
        dico.Clear();
        using (var stream = File.OpenRead("data.dat"))
        {
            Serializer.Merge<Test>(stream, data);
        }
    }
}

Размер: 83 мегабайта - но, что наиболее важно, вам не пришлось делать все это вручную, представляя ошибки. Тоже быстро (будет еще быстрее в "v2").

5
ответ дан 3 December 2019 в 06:20
поделиться

Есть несколько быстрых решений NoSQL для ключей и значений, почему бы не попробовать их? Например, ESENT, кто-то разместил его здесь, на SO. managedesent

1
ответ дан 3 December 2019 в 06:20
поделиться

Возможно, вы захотите использовать профилировщик, чтобы проверить, не выполняет ли десериализатор за кулисами кучу рефлексии на лету.

Пока что, если вы не хотите использовать базу данных, попробуйте хранить свои объекты как плоский файл в пользовательском формате. Например, в первой строке файла указывается общее количество записей в словаре, что позволяет инстанцировать словарь с заранее заданным размером. Остальные строки будут представлять собой серию пар ключ-значение фиксированной ширины, представляющих все записи в вашем словаре.

С новым форматом файла используйте StreamReader для чтения файла построчно или фиксированными блоками, посмотрите, позволяет ли это быстрее читать словарь.

2
ответ дан 3 December 2019 в 06:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: