C ++ writing in csv, performance

This is probably a simple question, but I could not find specific information about this, or at least the information in a readable format. Most of the information I found relates to reading data from .csv.

I have a function that should save data in a CSV file. This is not an ideal format in terms of performance, but suppose it cannot change. My data is stored in the rxcxs data structure and should be output in the form r, c, s, value and stored in .csv. At the moment I have:

char delimiter = ',';
ofstream ofs(file, ofstream::out);

for (int r = 0; r < P.n_rows; r++)
{
    for (int c = 0; c < P.n_cols; c++)
    {
        for (int s = 0; s < P.n_slices; s++)
        {
            ofs << r + 1 << delimiter << c + 1 << delimiter << s + 1 << delimiter << P(c, s, s) << endl;
            count++;
        }
    }
}
ofs.close();

100 x 100 x 50 6 , , . , , .

+4
3

, endl , - .

os , os.put(os.widen('\n')), os.flush().

. .

+11

, :

char delimiter = ',';
stringstream ss;

for (int r = 0; r < P.n_rows; r++)
{
    for (int c = 0; c < P.n_cols; c++)
    {
        for (int s = 0; s < P.n_slices; s++)
        {
            ss << r + 1 << delimiter << c + 1 << delimiter << s + 1 << delimiter << P(r, c, s) << endl;
        }
    }
}
ofstream ofs(file, ofstream::out);
ofs << ss.str();
ofs.close();

endl "\n" :

char delimiter = ',';
ofstream ofs(file, ofstream::out);

for (int r = 0; r < P.n_rows; r++)
{
    for (int c = 0; c < P.n_cols; c++)
    {
        for (int s = 0; s < P.n_slices; s++)
        {
            ofs << r + 1 << delimiter << c + 1 << delimiter << s + 1 << delimiter << P(r, c, s) << "\n";
        }
    }
}
ofs.close();

2X :

string delimiter = ",";
string ss;
ss.reserve(P.n_rows * P.n_cols * P.n_slices * 20);

int max_idx = max(P.n_rows, max(P.n_cols, P.n_slices));
vector<string> idx_str(max_idx);
for(int i=0;i<max_idx;++i) idx_str[i] = std::to_string(i+1);

for (int r = 0; r < P.n_rows; r++)
{
  auto& rstr = idx_str[r];
    for (int c = 0; c < P.n_cols; c++)
    {
      auto& cstr = idx_str[c];
      string thisline = rstr + delimiter + cstr + delimiter;

        for (int s = 0; s < P.n_slices; s++)
        {
          auto& sstr = idx_str[s];
            ss += thisline
                + sstr + delimiter
                + std::to_string(data[r][c][s]) + "\n";
        }
    }
}
ofstream ofs(file, ofstream::out);
ofs.write(ss.c_str(), sizeof(char)*ss.size());
ofs.close();
+1

As mentioned (and accepted) above, a drop endlreduces the time by 50-60% (in my case, from 7 seconds to 2 seconds, more than 70%).

However, there is still room for improvement: formatting the overall stream. The following code further reduces execution time by another 75%, to 500 ms:

int a[100][100][50];
int main(int argc, char** argv)
{
    char buff[64];
    memset(a, 1, 100 * 100 * 50 * sizeof(int));
    int count(0);
    char delimiter = ',';
    auto start = std::chrono::steady_clock::now();
    std::ofstream ofs("test.csv", std::ofstream::out);
    for (int r = 0; r < 100; r++)
    {
        for (int c = 0; c < 100; c++)
        {
            for (int s = 0; s < 50; s++)
            {
                sprintf_s(buff, "%d,%d,%d,%d\n", r, c, s, a[c][r][s]);
                ofs << buff;
                //ofs << r + 1 << delimiter << c + 1 << delimiter << s + 1 << delimiter << a[c][r][s] << '\n';
                count++;
            }
        }
    }
    ofs.close();
    auto end = std::chrono::steady_clock::now();
    std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << endl;
    return count;
}
+1
source

Source: https://habr.com/ru/post/1627924/


All Articles