这篇博客旨在对 2025 年 ECOOP 发表的论文《Type-safe and portable support for packed data》进行简短易懂的总结。
引言:打包数据
- 程序持久化数据或通过网络发送数据时需序列化,接收或读取数据时需反序列化,因为内存中的数据表示不能直接用于文件或网络传输,序列化和反序列化有成本,会导致网络负载增大和传输时间变慢。
- 引入“打包”数据格式,一种二进制格式,无需反序列化步骤即可直接使用数据,遍历打包树比非打包树更快,一些项目使用或利用了这种方法,但没有语言原生支持,Haskell 虽支持紧凑范式但
Compact
数据类型不允许使用打包值,存在研究编译器Gibbon
可生成使用打包数据的程序,但打包数据的使用局限于研究项目。
库及其特性和 API
packed-data
Haskell 库利用类型的力量,无需编组步骤或编译器修改,即可实现数据的打包、解包和遍历。- 通过 Template Haskell 生成必要代码,对于任意类型,可进行打包、解包和遍历操作,例如对于二叉树类型
Tree
,生成了相关类实例和函数。 NeedsBuilder
用于构建打包数据,受Linear Haskell
论文启发,通过幻影类型参数限制输入数据,构建过程是单子式的,还提供了finish
和pack
函数。PackedReader
表示对打包数据的读取操作,是索引单子,其“状态”反映在类型中,用于抽象指针操作并确保类型正确的读取操作,避免了没有PackedReader
时的丑陋代码。case
函数为每个mkPacked
调用生成,用于模式匹配数据类型的构造函数,例如对于Tree
ADT 生成caseTree
函数,用于Unpackable
实例的定义。- 解决访问打包数据结构中字段的挑战,有两种方式,一是遍历前面的字段(可能导致性能问题),二是在每个字段前添加间接引用(
FieldSize
),库会自动插入这些间接引用并修改case
函数的签名。
基准测试
- 对简单树遍历操作进行基准测试,包括求和、获取最右值、评估 AST 和递增叶子值,与 C、“非打包”Haskell 和 Gibbon 比较执行时间。
- 总结测试结果,求和操作有小的提速,获取最右值操作较慢,评估 AST 操作较快,递增值操作与非打包树相同,且基准结果因机器 CPU 架构而异。
- 解释结果,使用打包布局应提供更快的遍历,但
PackedReader
的单子式方法导致计算开销,非单子式版本的遍历速度有所提升但仍慢于原生 Haskell。
未来工作和结论
- 由于库的浅嵌入存在计算开销,未来可将库重写为生成 C 代码的 AST,避免单子式方法的开销,还可在其他强类型语言中尝试这种基于库的方法,以及探索在 Web 服务中使用 JSON 而无需反序列化步骤的可能性。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。