1

検索しましたが、必要なものが正確に見つからないようです。

次のコマンドを実行するのと同等の高速な C++ を探しています。

diff file1.log file2.log | wc -l

現在、コマンド ラインから diff を実行するためにファイル パイプを使用していますが、これを複数のネストされた大規模なループで実行する必要があり、予想よりもかなり時間がかかります。差分をとるファイルはそれぞれ約 150 ~ 200 MB で、各差分には約 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 日程度にスケールアップされます。

この場合、遺伝的アルゴリズムで適合度関数を供給しているため、行の違いの量だけを気にします。この時点では、反復間の実行パスの広がりが重要です。

4

2 に答える 2

2

外部プロセスの起動は高速です。ファイルごとに1〜2分で、プロセススポーンのオーバーヘッドはごくわずかです。1)diffコマンドのパフォーマンス、または2)パイプの出力データの非効率的な読み取りと保存によって制限される必要があります。シェルでdiffコマンドを実行し、ファイルに出力してみてください。それははるかに速いですか?そうでない場合は、1)。もしそうなら、2)。

Unixパイプについてはよくわかりませんが、128バイトのバッファは小さいように聞こえます。diffコマンドは古く、広く使用されているため、より高速なバージョンを作成できる可能性はほとんどありません。

于 2012-09-07T15:06:59.267 に答える
1

私は2つの可能性を見ることができます。

1つは、問題を単純化することです。diffあるファイルを別のファイルに変換するための最小限の編集セットを見つけるために、かなりの作業を行います。2つのファイル間で何行が異なるかを知りたいだけで、一方が他方にどのように変換されるかを気にしない場合は、各ファイルに一連の行を作成するだけで、ある程度の速度を得ることができますそれらの間のサイズを取得しset_symmetric_differenceます。

2つ目は、(たとえば)最も類似している/最も類似していないファイルを探している場合、現在、すべてのファイルと他のすべてのファイルの間で差分を再実行している可能性があります。つまり、2次問題があり、N個のファイルが与えられた場合、各ファイルをN回再読み取りします。

達成しようとしていることとファイルの数によっては、各ファイルを1回だけ読み取ることができる可能性が高くなります。たとえば、各行をハッシュし、ハッシュのセットを格納するだけで、メモリ内のすべてのファイルのデータを一度に収めることができるため、操作の2次部分は、すべてのファイルを何度も再読み取りするのではなく、完全にメモリ内で実行できます。回数。

于 2012-09-07T15:27:15.577 に答える