c# - 复杂 .Net 对象图的快速读/写

标签 c# performance serialization file-io

我有自己的用 C# 编写的数据结构(结构相当复杂)。我需要序列化和反序列化结构。磁盘中序列化文件的大小有时可能非常大(接近 1 GB),但也可能很小(基于存储的记录数)。我有以下要求:

  1. 序列化和反序列化应该非常快
  2. 我应该能够部分反序列化一个大文件(即只访问一些相关记录),因为如果我从磁盘反序列化整个文件,内存使用率会太高。
  3. 应该是线程安全的,因为多个进程可以从文件写入/读取记录

我知道这听起来像是我需要一个数据库,但由于多种原因我不能使用它。我尝试通过实现 ISerializable 来满足要求 1,这使得它比使用内置在二进制/XML 序列化程序中的 .net 快得多,但速度不够快。因为要求 2 完全难住了我。

有人知道如何解决这个问题吗?我认为任何不得不保存自己的大文件格式的人都必须处理类似的问题。

问候, 山姆

最佳答案

是数据,还是完整的 - 即是否有任何循环引用?如果没有,protobuf-net是一个高性能的二叉序列化器。它支持可枚举项目的流式传输(因此您可以跳过记录等 - 而不是缓冲所有内容),但要高效寻找随机元素,我希望您需要某种索引。

读取/写入单个文件非常困难;特别是,写入可能需要移动比您预期更多的磁盘……读取也很棘手,可能需要同步。使用单独的文件会更容易......


跳过早期项目的例子;我可能会添加一个辅助方法,但是 TryDeserializeWithLengthPrefix 方法会起作用...关键是要注意在序列化和反序列化之间我们只创建一个额外的对象。

using System;
using System.IO;
using System.Threading;
using ProtoBuf;

[ProtoContract]
class Foo {
    static int count;
    public static int ObjectCount { get { return count; } }
    public Foo() { // track how many objects have been created...
        Interlocked.Increment(ref count);
    }
    [ProtoMember(1)]
    public int Id { get; set; }
    [ProtoMember(2)]
    public double Bar { get; set; }    
}
static class Program {
    static void Main() {
        MemoryStream ms = new MemoryStream();
        Random rand = new Random();
        for (int i = 1; i <= 5000; i++) {
            Foo foo = new Foo { Bar = rand.NextDouble(), Id = i };
            Serializer.SerializeWithLengthPrefix(ms, foo,PrefixStyle.Base128, 1);
        }
        ms.Position = 0;
        // skip 1000
        int index = 0;
        object obj;
        Console.WriteLine(Foo.ObjectCount);
        Serializer.NonGeneric.TryDeserializeWithLengthPrefix(
            ms, PrefixStyle.Base128,
            tag => ++index == 1000 ? typeof(Foo) : null, out obj);
        Console.WriteLine(Foo.ObjectCount);
        Console.WriteLine(((Foo)obj).Id);
    }
}

关于c# - 复杂 .Net 对象图的快速读/写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/950471/

相关文章:

c# - 如何在 C# 中截取全尺寸窗口的屏幕截图

java - SEAM:有效使用@BypassInterceptors?

performance - OpenMP程序性能低下

powershell - 在什么情况下需要当 -NoTypeInformation *不* 传递给 ConvertTo-Csv 或 Export-Csv 时发出的信息?

serialization - ViewScoped Bean 中 SessionScope 的 ManagedProperty - transient ?

c# - 清除 Linqpad 中的所有实习字符串?

c# - 如何在数据上下文中使用事务

c# - 在 Windows 10 中检测到布局循环,但在 Windows 8.1 中未检测到

java - C2 编译器在启动时使 CPU 饱和

java - 如何将数组放入 Hashmap 中以编码 JSON 对象