高效文本差异分析工具的开发与应用

本文旨在介绍一种高效的文本差异分析工具的开发过程。该工具能够快速准确地比较两个文本文件的差异,对于软件开发、文档编辑等领域具有重要的应用价值。本文将从算法选择、实现细节、性能优化以及软件应用等方面进行详细阐述。

本文再次使用了Douglas McIlroy在20世纪70年代初编写的diff算法的实现,并参考了Eugene W. Myers在其论文中对该算法的描述。与以往不同的是,这次对多个diff进行了运行。首先,像以前一样对完整行进行diff,以揭示两个输入文件之间的差异。这些差异可以被分组到由相同行分隔的不同部分。这些部分可以被分类为文件A的删除、文件B的插入,或者两者都有。

有趣的部分是那些既有删除行又有插入行的部分。在这些部分中,可能存在行内的匹配文本,以及更小的真实差异。对于行的情况,所有差异都可以被认为是文件A的删除或文件B的插入。

对于这些部分,diff算法将在部分中的字符上运行。这次,寻找两个版本之间的相似之处。这些相似之处被记录下来,并以更柔和的颜色显示在输出中,从而突出显示差异。

使用代码

下载的是一个WinForms应用程序,它将两个测试文件作为嵌入资源,默认加载。您还可以通过提供两个命令行参数的路径来diff任意两个文件。该应用程序运行所有必需的diff,并显示结果和一些计时测量。

输出

在第一篇文章中,使用了WebBrowser控件来呈现输出。这次,创建了一个自定义控件,它继承自ScrollableControl。它并不复杂,但可以在10毫秒多一点的时间内渲染测试文件的输出。

删除的文本以红色显示,而文件A中匹配的文本以浅红色显示。同样,插入的文本是绿色的,而文件B中匹配的文本是浅绿色的。认为这很好地突出了实际的变化。

结果

由于这是Lean and Mean竞赛的参赛作品,以下是一些指标:

  • 时间:测试用例的代表性时间测量显示在屏幕截图中。渲染输出的时间较长,但很高兴多个diff仍然在2毫秒以下。因此,结果的时间大约是15毫秒,包括JIT时间在内大约是70毫秒。
  • 空间:最大的空间需求仍然是将文件作为string[]保存在内存中。这大约需要390 KB的测试用例。两个主要的Int32数组都是大约(N + M)长,其中N是文件A的行数,M是文件B的行数。因此,计算出的空间需求仍然是大约420 KB的结果。很难计算显示所占用的空间,但可以说这是框架的责任。

Process.PeakWorkingSet64的变化始终在1.5 MB以下。

选择复制diff算法源代码来处理string[]和char[]的两种情况。这是因为算法中的热路径是等式运算符。可以使用泛型参数,用where T : IEquatable限制它,并调用Equals,但这将显著减慢算法。此外,JIT编译器仍然需要在两个版本上工作,因此没有收益。

保留了两个大的Int32数组,并在char diffs中重用它们。这很有帮助,因为在.NET中,内存分配和特别是收集是昂贵的。这也有助于在特定的测试用例中,两个char diffs所需的空间比第一个行diff少。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485