代码之家  ›  专栏  ›  技术社区  ›  Greg Dean

基类型的最优序列化

  •  6
  • Greg Dean  · 技术社区  · 17 年前

    我们开始推出越来越多的产品广域网部署(带有IIS托管远程处理后端的.NET胖客户端)。因此,我们正试图减小传输线上的数据大小。

    我们通过实现ISerializable(类似于 this 除了显而易见的方式之外,是否有一种奇特的方式来序列化原始类型?

    例如,今天我们序列化一个int数组如下:

    对于布尔数组,最明显的显著改进是在每个字节中放入8个布尔值,我们已经这样做了。

    注:

    9 回复  |  直到 9 年前
        1
  •  5
  •   Marc Gravell    17 年前

    (涉及消息/类,而不仅仅是原语)

    在。NET世界,我可以推荐2个协议缓冲区实现:

    值得一提的是,protobuf net直接支持 ISerializable 远程处理(它是 unit tests ).有性能/规模指标 here .

    最重要的是,你所做的就是给你的类添加一些属性。

    警告:它并不声称是理论上的 -但实用且易于上手,是性能、可移植性和简单性之间的折衷。

        2
  •  2
  •   Greg Beech    17 年前

    看看 base-128 varint 谷歌协议缓冲区中使用的类型;这可能就是你要找的。

    (如果你搜索网络,有许多协议缓冲区的.NET实现可用,根据它们的许可证,你可能可以从中获取一些代码!)

        3
  •  2
  •   Peter Mortensen Pieter Jan Bonestroo    9 年前

    是的,有一种奇特的方法可以序列化原始类型。作为奖励,它也快得多(通常为20-40倍)。

    Simon Hewitt的开源库,请参阅 Optimizing Serialization in .NET - part 2 ,使用各种技巧。例如,如果知道一个数组包含小整数,那么序列化输出的整数就更少。这将被详细描述 in part 1 of the article 例如:

    …因此,一个较小的Int32 大于128的数据可以存储在一个字节中(通过使用7位 编码)。...

    完整整数和大小优化整数可以混合和匹配。这似乎是显而易见的,但还有其他事情;例如,对于整数值0进行优化以存储数值类型和零值,会发生特殊情况。

    第1部分指出:

    生成大量数据以供传输 ,并且可能会因内存不足异常而失败。实际执行序列化所需的时间也存在一个大问题——大量数据可能使其在应用程序中不可行。...

    我在使用这个图书馆时取得了巨大的成功 my application .

    为了确保。NET序列化从未被使用过 ASSERT 0 , Debug.WriteLine() 或类似进入该地点 它所依赖的库代码。NET序列化。 那是在功能结束时 WriteObject() 在文件中 FastSerializer.cs ,近 createBinaryFormatter().Serialize(BaseStream, value); .

        4
  •  1
  •   dreamlax    17 年前

    如果你的数组可以排序,你可以执行一个简单的RLE来节省空间。即使它们没有分类,RLE仍然是有益的。它对写作和阅读都很快实现。

        5
  •  1
  •   Vojislav Stojkovic    17 年前

    这里有一个我曾经用来编码整数数组的技巧:

    1. 将数组元素分组为4个一组。
    2. 在每个组前面加一个字节(我们称之为长度掩码),表示以下4个元素的长度。长度掩码是一个由双比特组成的位掩码,指示相应元素的长度(00-1字节,01-2字节,10-3字节,11-4字节)。
    3. 尽可能简短地写出这些元素。

    例如,要表示无符号整数0x0000017B、0x000000A9、0xC247E8AD和0x00032A64,您可以写(假设小端序):B1、7B、01、A9、AD、E8、47、C2、64、2A、03。

    在最佳情况下,它可以为您节省高达68.75%(11/16)的空间。在最坏的情况下,你实际上会浪费额外的6.25%(1/16)。

        6
  •  0
  •   ChrisW    17 年前

    如果你知道哪些int值更常见,你可以用更少的比特对这些值进行编码(并使用相应更多的比特对不太常见的值进行编码):这被称为“霍夫曼”编码/编码/压缩。

    总的来说,我建议你可以做的最简单的事情之一就是在你的数据上运行一个标准的“zip”或“压缩”实用程序。

        7
  •  0
  •   Coincoin    17 年前

    对于整数,如果你通常有小数字(低于127或32768),你可以使用MSB作为标志对数字进行编码,以确定它是否是最后一个字节。与UTF-8有点相似,但标志位实际上被浪费了(UTF-8的情况并非如此)

    示例( 大端序 ):

    125 which is usually encoded as 00 00 00 7D
    Could be encoded as 7D
    
    270 which is usually encoded as 00 00 01 0E
    Could be encoded as 82 0E
    

    主要限制是32位值的有效范围减小到28位。但对于小值,你通常会获得很多。

    这种方法实际上用于MIDI等旧格式,因为旧电子设备需要非常高效和简单的编码技术。

        8
  •  0
  •   Edward Brey    10 年前

    如果你想自己控制序列化格式,只需要库的帮助就可以实现紧凑的整数存储,那么从中派生一个类 BinaryWriter 使用 Write7BitEncodedInt .也这样做 BinaryReader.Read7BitEncodedInt .

        9
  •  -1
  •   Peter Mortensen Pieter Jan Bonestroo    9 年前

    推荐文章