【问题标题】:How to minimize Protobuf.NET memory consumption如何最小化 Protobuf.NET 内存消耗
【发布时间】:2011-10-25 16:07:07
【问题描述】:

我正在使用 Protobuf.NET 序列化大量类,其中大部分作为引用(因为我的数据结构中有多个对相同类的引用)。

所有序列化的类都通过使用 ImplicitFirends.AllFields 进行序列化,以确保 一切都被倾倒了。

在我当前的测试用例中,我有 53 个文件,总和为 500MB。

当我使用 Protobuf.NET 反序列化器读取此数据时,我的私有字节/常驻内存会飙升至 9GB 并停留在那里(即,这不是在反序列化后释放/GC 的临时内存)。

另一个奇怪的事情是,如果我重写(重新序列化)所有数据,它仍然保持相同的大小。

这个 x20 在内存中爆炸有意义吗?

【问题讨论】:

    标签: c# .net protobuf-net


    【解决方案1】:

    我将运行一些测试,但它听起来就像是它为避免分配而保留的缓冲池。除了测试之外,我将在下一个版本中添加一个“转储池”方法(并禁用?)。其实想一想:我会把这些改成WeakReference,这样它们就可以在它们存在的时候被重新使用,但仍然被收集起来。

    您可能还会发现(作为合同的一个选项)对子对象和列表使用“组”编码可以大大减少这里的内容; length-prefixed 是默认值(也是 Google 的首选选项),但组的写入效率更高,因为它们可以直接写入而无需任何缓冲。让我知道你是否想要一个这样的例子。 Protobuf-net 的设计使得它们之间的切换不是一个重大变化,但 other protobuf 客户端不会那么宽容,如果您使用 protobuf 与其他系统进行互操作,那就更棘手了。

    【讨论】:

    • 我不确定这真的是缓冲池。当我转储堆时,我看到了多个(即 10,000 或更多)类实例,这些实例应该在个位数范围内。有没有办法验证 AsReference “功能”是否真的有效?我有一个特定的类被设置为被编码为 AsReference,我实际上应该有其中之一,但我似乎有超过 10,000 个......这让我怀疑 AsReference 功能......
    • @damageboy 从您的数据中验证肯定很容易 - 只需调用 ReferenceEquals。如果您可以展示您的场景的一个小示例,这将有所帮助,请注意,引用仅在单个图形操作期间有效 - 如果您分别调用 Deserialize 5 次,仍然是 5 个对象,而不是一个。是这里的情景吗?我是这样的,可能还有其他选项(包括我多年来一直想要实现的核心 .NET 引用交换接口,它可能允许你做你想做的事)。
    • 我想我正在解决这个问题...如果我有一个继承方案,其中 C 派生自 B,而 B 派生自 A...是否应该将所有这些类标记为参考?
    • 嗨,Marc,我的情况似乎有些复杂。我用“AsReference”标记的一些类确实被序列化为引用并通过了 ReferenceEquals 测试,而其他更复杂的类,可能具有继承的那些类不,并且基本上被复制......在有关的场景中支持 AsReference子类型和继承?
    • @damageboy 应该是,但这很复杂。我必须测试。
    猜你喜欢
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 2012-11-16
    • 2013-06-28
    • 2014-03-08
    • 1970-01-01
    • 2017-10-07
    相关资源
    最近更新 更多