Haskell 中的打包数据支持

这篇博客旨在对 2025 年 ECOOP 发表的论文《Type-safe and portable support for packed data》进行简短易懂的总结。

  • 引言:打包数据

    • 程序持久化数据或通过网络发送数据时需序列化,接收或读取数据时需反序列化,因为内存中的数据表示不能直接用于文件或网络传输,序列化和反序列化有成本,会导致网络负载增大和传输时间变慢。
    • 引入“打包”数据格式,一种二进制格式,无需反序列化步骤即可直接使用数据,遍历打包树比非打包树更快,一些项目使用或利用了这种方法,但没有语言原生支持,Haskell 虽支持紧凑范式但Compact数据类型不允许使用打包值,存在研究编译器Gibbon可生成使用打包数据的程序,但打包数据的使用局限于研究项目。
  • 库及其特性和 API

    • packed-dataHaskell 库利用类型的力量,无需编组步骤或编译器修改,即可实现数据的打包、解包和遍历。
    • 通过 Template Haskell 生成必要代码,对于任意类型,可进行打包、解包和遍历操作,例如对于二叉树类型Tree,生成了相关类实例和函数。
    • NeedsBuilder用于构建打包数据,受Linear Haskell论文启发,通过幻影类型参数限制输入数据,构建过程是单子式的,还提供了finishpack函数。
    • PackedReader表示对打包数据的读取操作,是索引单子,其“状态”反映在类型中,用于抽象指针操作并确保类型正确的读取操作,避免了没有PackedReader时的丑陋代码。
    • case函数为每个mkPacked调用生成,用于模式匹配数据类型的构造函数,例如对于TreeADT 生成caseTree函数,用于Unpackable实例的定义。
    • 解决访问打包数据结构中字段的挑战,有两种方式,一是遍历前面的字段(可能导致性能问题),二是在每个字段前添加间接引用(FieldSize),库会自动插入这些间接引用并修改case函数的签名。
  • 基准测试

    • 对简单树遍历操作进行基准测试,包括求和、获取最右值、评估 AST 和递增叶子值,与 C、“非打包”Haskell 和 Gibbon 比较执行时间。
    • 总结测试结果,求和操作有小的提速,获取最右值操作较慢,评估 AST 操作较快,递增值操作与非打包树相同,且基准结果因机器 CPU 架构而异。
    • 解释结果,使用打包布局应提供更快的遍历,但PackedReader的单子式方法导致计算开销,非单子式版本的遍历速度有所提升但仍慢于原生 Haskell。
  • 未来工作和结论

    • 由于库的浅嵌入存在计算开销,未来可将库重写为生成 C 代码的 AST,避免单子式方法的开销,还可在其他强类型语言中尝试这种基于库的方法,以及探索在 Web 服务中使用 JSON 而无需反序列化步骤的可能性。
阅读 11
0 条评论