在C#中序列化和反序列化V.Large字典

时间:2010-06-25 12:35:39

标签: c# dictionary

我们有一个v.large Dictionary<long,uint>(数百万条目)作为高性能C#应用程序的一部分。当应用程序关闭时,我们使用BinaryFormatterMemoryStream.ToArray()将字典序列化到磁盘。序列化在大约30秒内返回并生成大小约为200MB的文件。然后,当我们尝试使用以下代码对字典进行反序列化时:

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),即在1秒内从硬盘驱动器(高性能SSD)读取字节。

有人可以指出我们做错了什么,因为我们希望加载时间与保存时间相同。

此致 马克

4 个答案:

答案 0 :(得分:11)

您可以结帐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);
            }
        }
    }
}

结果文件的大小=&gt; 90M字节(85.8MB)。

答案 1 :(得分:5)

通过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);
        }
    }
}

大小:83meg - 但最重要的是,您不必手动完成所有操作,引入错误。也快(在“v2”中会更快)。

答案 2 :(得分:2)

您可能希望使用分析器来查看反序列化程序是否正在执行一系列即时反射。

目前,如果您不想使用数据库,请尝试将对象存储为自定义格式的flatfile。例如,文件的第一行给出字典中的条目总数,允许您实例化具有预定大小的字典。将剩余行作为一系列固定宽度的键值对,表示字典中的所有条目。

使用新的文件格式,使用StreamReader逐行或固定块读取文件,看看是否允许您更快地读入字典。

答案 3 :(得分:1)

有几种快速的Key-Value NoSQL解决方案,为什么不试试呢? 作为ESENT的一个例子,有人在SO上发布了它。 managedesent