C ++中的快速差异实现,以获取大文件中的行差异

时间:2012-09-07 14:57:06

标签: c++ performance diff

搜索但似乎没有找到我需要的确切内容。

我正在寻找运行以下命令的快速C ++:

diff file1.log file2.log | wc -l

目前,我使用文件管道从命令行运行diff,但是我需要在一个大型的多嵌套循环中执行此操作,并且它需要的时间比我预期的要长。被传播的文件大约每个150-200mb,每个差异大约需要1-2分钟。

是否有一个可以由C ++推出的更快的解决方案?

以下是我目前调用它的方法:

static std::string run_cmd(std::string in)
{
  // run command
  FILE* pipe = popen(in.c_str(), "r");
  if (!pipe)  return "err";

  char buff[128];
  std::string res = "";
  while (!feof(pipe))
  {
    if (fgets(buff, 128, pipe) != NULL)
      res += buff;
  }
  pclose(pipe);
  return res;
}

// diff 2 given files and return line number differences
std::string fileDiff(std::string file1, std::string file2)
{
  std::string f1 = base + file1;
  std::string f2 = base + file2;
  std::string cmd = "diff " + f1 + " " + f2 + " | wc -l";

  std::string res = run_cmd(cmd);
  if (res == "err") 
    return "E: Diff on [" + f1 + "] and [" + f2 + "]";

  return res;
}

编辑:

我实际上在做的是记录代码覆盖率。我已将日志记录语句插入到我工作的代码库的每个角落中,并将每个运行写入其自己的日志文件。我试图通过不将它们包含在构造函数,循环等中来最小化写入惩罚,并且已经缓冲了实际的写入过程。

我通常需要大约10分钟的程序才能运行。随着我添加的日志记录和差异调用,它缩放到大约1天。

我只关心这种情况下的线差异量,因为它在遗传算法中提供了适应度函数。此时迭代之间执行路径的传播非常重要。

2 个答案:

答案 0 :(得分:2)

启动外部流程很快。每个文件1-2分钟,产生开销的过程是微不足道的一小部分。您必须受到以下限制:1)diff命令的性能或2)低效读取和存储管道输出数据。尝试在shell中运行diff命令并输出到文件中。它快得多吗?如果没有,那么1)。如果是,那么2)。

我对Unix管道知之甚少,但128字节的缓冲区听起来很小。 diff命令是旧的并且被广泛使用,因此你不可能编写更快的版本。

答案 1 :(得分:1)

我可以看到两种可能性。

一个是简化问题。 diff做了很多工作来找到将一个文件转换为另一个文件的最小编辑集。如果您只想知道两个文件之间有多少行不同,并且不关心如何将其转换为另一个文件,那么可以通过简单地构建一组来获得一些速度每个文件中的行,并获得它们之间set_symmetric_difference的大小。

第二个问题是,如果您正在查找(例如)最相似/最不相似的文件,那么现在您可能正在重新执行每个文件和每个其他文件之间的差异。换句话说,你有一个二次问题,给定N个文件,你会重新读取每个文件N次。

根据您要完成的工作和文件数量,您很有可能只能阅读一次文件。例如,如果您对每一行进行散列,并且只存储一组散列,则可以同时为内存中的所有文件拟合数据,因此操作的二次部分可以完全在内存中发生,而不是重新读取每个文件次。