小二进制blob的二元diff算法

时间:2018-02-19 17:40:48

标签: algorithm network-programming diff binary-diff

对于相当大的文件(1MB +),有很多关于二进制diff算法的信息。但是,我的用例不同。 这就是为什么它不重复。

我有许多对象的集合,每个对象在5到100个字节范围内。我想通过网络发送有关这些对象的更新。我想将更新编译成单独的TCP数据包(合理的MTU为~1400)。我想尝试在每个数据包中尽可能多地更新数据:首先添加它们的ID,然后将所有二进制对象的二进制差异组合起来。

用于此目的的最佳二进制差分算法是什么?

2 个答案:

答案 0 :(得分:1)

简单的答案是将您的许多小对象组合成一个大对象,然后使用现有的二进制差异算法有效地在该组合对象上发送差异。

但是没有必要自己动手。我个人通过将所有对象放入文件系统,然后使用rsync发送diff来解决这个问题。

这在理论上不是最佳的。但请考虑以下事项:

  1. 实施很简单。
  2. 代码经过严格测试 - 您的代码需要很长时间才能达到类似的可靠性。
  3. 此实现涵盖了接收方的状态不是发送方期望的边缘情况。如果接收器发生崩溃/重启,就会发生这种情况。
  4. 有些情况下这是错误的解决方案。但是我会坚持让这个直截了当的解决方案失败,然后再巧妙而复杂。

答案 1 :(得分:1)

使用这些小对象,您可以使用经典的最长公共子序列算法来创建“差异”。

然而,这不是解决问题的最佳方法。 LCS算法受限于在匹配目标序列时仅使用每个原始字节一次的要求。你可能并不真的需要这个约束来编码你的压缩数据包,所以除了有点慢之外,它还会导致次优解决方案。

您的目标实际上是使用原始对象的示例来压缩新对象,您应该用这些术语来考虑它。

有许多方法,但您可能对如何编码这些新对象有所了解。您可能正在考虑使用对原始对象的部分的引用来替换新对象的部分。

在这种情况下,为每个原始对象(https://en.wikipedia.org/wiki/Suffix_array)创建一个后缀数组是切实可行的。然后,当您对相应的新对象进行编码时,在每个字节处可以使用后缀数组来查找旧对象的最长匹配段。如果它足够长,可以节省成本,那么您可以用引用替换相应的字节。