为何BinaryFormatter序列化单个int的字节占用比序列化int数组更高?
BinaryFormatter序列化长度差异原因说明
核心原理
BinaryFormatter的设计目标是完整保留.NET类型系统的所有信息,确保反序列化后能得到和原始对象完全一致的类型实例,因此序列化结果中类型元数据的占比远高于实际数据本身,小对象序列化时元数据开销会远超过数据本身的大小。
具体问题解答
1. 单个int序列化后占用58字节的原因
你序列化单个int值时,数值会被装箱为object对象,BinaryFormatter需要完整记录以下信息:
- 固定8字节的序列化头(魔术字+版本标识)
- 根对象的类型全限定信息:包括
System.Int32的命名空间、类型名、所属程序集的完整信息(版本、公钥标记等) - Int32类型的可序列化字段定义(仅一个
m_value字段) - 最后才是4字节的实际int值
前面三类元数据总开销就达到了54字节,加上4字节的实际值,总长度刚好为58字节。
序列化单个int的代码你已经给出:
MemoryStream stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, 5);
2. 长度为5的int数组序列化后仅48字节的原因
int数组属于.NET预定义的基元类型数组,BinaryFormatter对这类序列化对象有元数据优化:
- 同样保留8字节固定头
- 仅需要记录一次数组类型信息:
System.Int32[]、一维数组标识、数组长度为5 - 不需要单独存储每个int元素的类型信息,直接连续写入5个int的实际值(共20字节)
这部分的类型元数据开销仅为20字节,加上20字节的实际数据,总开销为48字节,反而低于单个int的序列化长度。
序列化数组的代码如下:
int[] values = new int[5]{1,2,3,4,5};
3. 你关心的其他问题解答
- 是否有忽略的底层规则:BinaryFormatter的序列化开销完全由类型元数据决定,小对象的元数据占比极高是其固有特性,不是使用方式有误
- 是不是整个Int32结构体都被序列化:不是,实际仅序列化了存储数值的
m_value字段,剩下的字节全部是类型元数据开销 - 为什么数组序列化后更短:因为数组的元数据描述开销比单个装箱int的元数据描述开销更低,5个int的实际数据仅20字节,加总后总长度反而更小
额外提示
BinaryFormatter目前已被.NET官方标记为不安全API,不推荐在生产环境使用。如果你需要低开销的紧凑序列化方案,可以选择Protobuf、MessagePack等专门为性能优化的序列化库。
内容的提问来源于stack exchange,提问作者Ixiodor
相关产品推荐
相关产品推荐

