1

次を使用してテキストファイルに文字列を書き込んでいます。

ofstream ofs("ofs.txt", ios_base::binary);
std::string str = "Hi";
for (int i = 0 ; i < 10000000 ; i++) {
    ofs << str.c_str();
    ofs << "\n" ;
}

ただし、これは実行に時間がかかります。上記のパフォーマンスを改善する方法を教えてください。または、文字列をファイルに書き込む他の高速な方法。

ありがとう。

4

3 に答える 3

1

いくつかのケースでは、C ++ I/OストリームはCよりも遅い傾向があることがわかりました<stdio.h> FILE*

次のテストでも確認がありました。

#define _CRT_SECURE_NO_WARNINGS // for stupid fopen_s warning
#include <stdio.h>
#include <exception>
#include <fstream>
#include <iostream>
#include <ostream>
#include <stdexcept>
#include <string>
#include <vector>
#include <windows.h>
using namespace std;

long long Counter() 
{
  LARGE_INTEGER li;
  QueryPerformanceCounter(&li);
  return li.QuadPart;
}

long long Frequency() 
{
  LARGE_INTEGER li;
  QueryPerformanceFrequency(&li);
  return li.QuadPart;
}

void PrintTime(long long start, long long finish, const char * s) 
{
  cout << s << ": " << (finish - start) * 1000.0 / Frequency() << " ms" << endl;
}

// RAII wrapper to FILE*
class File
{
public:
  explicit File(FILE * f)
    : m_file(f)
  {}

  ~File()
  {
    fclose(m_file);
  }

  FILE* Get() const
  {
    return m_file;
  }

  bool IsOpen() const
  {
    return (m_file != nullptr);
  }

private:
  FILE* m_file;

  File(const File&);
  File& operator=(const File&);
};

void TestIoStream(const vector<string>& lines)
{
  ofstream ofs("ofs.txt", ios_base::binary);
  for(auto it = lines.begin(); it != lines.end(); ++it)
  {
    ofs << it->c_str();
    ofs << "\n" ;
  }
}

void TestStdioFile(const vector<string>& lines)
{
  File file( fopen("cfile.txt", "wt") );
  if (! file.IsOpen())
    throw runtime_error("Can't open C FILE*.");

  for(auto it = lines.begin(); it != lines.end(); ++it)
  {
    fputs( it->c_str(), file.Get());
    fputs( "\n", file.Get());
  }
}

int main()
{
  static const int kExitOk = 0;
  static const int kExitError = 1;
  try
  {
    cout << "Building test lines...";
    vector<string> lines;
    for (int i = 0; i < 10000000; i++)
      lines.push_back("Hi");
    cout << "done. ";
    cout << "(Count = " << lines.size() << ")" << endl;

    long long start = 0;
    long long finish = 0;

    start = Counter();  
    TestIoStream(lines);
    finish = Counter();
    PrintTime(start, finish, "C++ I/O stream");

    start = Counter();
    TestStdioFile(lines);
    finish = Counter();
    PrintTime(start, finish, "C FILE*");

    return kExitOk;
  }
  catch(const exception& e)
  {
    cerr << "\n*** ERROR: " << e.what() << endl;
    return kExitError;
  }
}

VS2010 SP1(VC10)でコンパイル:

cl /EHsc /W4 /nologo /MT /O2 /GL test.cpp

テスト結果:

Building test lines...done. (Count = 10000000)
C++ I/O stream: 2892.39 ms
C FILE*: 2131.09 ms
于 2013-02-08T12:01:56.380 に答える
1

を使用するだけofs << str;で、わずかに高速になる可能性があります (またはそうではないかもしれませんが、確かに慣用的です)。しかし、20 メガバイトのデータを書き込んでいます。方法に関係なく、それには時間がかかります。

あなたは何をしようとしているのか正確には言いません。(実際の問題は 1000 万回には及ばないと推測してい"Hi"ます。) それによっては、低レベル IO を使用することも可能かもしれませんmmap。ただし、これらはどちらもフォーマットを行いません。ostringstream最初にフォーマットする必要がある場合は、大幅に高速化されていないことに気付くかもしれません。

于 2013-02-08T11:17:50.233 に答える
1

多くの文字列をファイルに書き込む最速の方法は、(ほとんどの場合) CFILE *インターフェイスを使用することです。C++ ストリーム インターフェイスがFILE *.

理想的には、数 KB (一度に完全に 4KB) のバッファーを構築し、それを を使用して書き込むとfwrite(buffer, size_of_buffer, 1, outfile);、システムが生成できるパフォーマンスにかなり近づくはずです。はい、 Linux/Unix および Windowsのネイティブ インターフェイスwriteまたはそれぞれのネイティブ インターフェイスを使用して、おそらく 0.5% 以上調整できます。WriteFile

もちろん、欠点は、任意の新しい型の出力メソッドを単純に追加する簡単な方法がないことです。

いつものように、パフォーマンスに関しては、さまざまなオプションを測定し、どれが最適かを確認してください。さまざまな状況で多くのマシンで使用されるものである場合は、さまざまなハードウェア、さまざまな量のメモリ、およびシステム負荷でテストして、自分のマシンだけを高速化するだけでなく、実際にさまざまな条件のシステムで合理的な改善が得られます [または少なくとも悪い欠点はありません]。

于 2013-02-08T11:51:39.553 に答える