同步问题调用ofstream写入自定义缓冲区(pubsetbuf)

时间:2016-10-19 00:38:07

标签: c++ buffer ofstream

我正在使用std::ofstream向网络位置写入可能较大(多千兆字节)的二进制文件。以前我经常冲洗缓冲区,这会影响性能,特别是在高峰时段 - 降低冲洗频率有帮助。我有兴趣找到其他方法来进一步提高写入性能。

根据各种在线资源,直接通过streambuf直接写入与流stream.rdbuf()->pubsetbuf(buffer)对象关联的缓冲区,避免了here所描述的写入开销。

不是将每个值依次传递给ofstream::write,而是填充并传递一个具有8192字节固定大小的字节缓冲区。我原本以为直接填充缓冲区会避免调用write,但省略写入会导致没有写入文件。在任何情况下,我的测试表明使用pubsetbuf with write比使用pubsetbuf并且一次写一个8字节值要快得多。

不幸的是,如果我在每次写入调用后都没有刷新流,则缓冲区的内容都会附加到文件并在开始时写入,并覆盖先前在该位置的数据。如果flush紧跟write次呼叫,则生成的文件正确无误。我每次发生写操作时都检查过流指针是否正确。

或者,如果我根本不打扰调用stream.rdbuf()->pubsetbuf(buffer)并继续将预先填充的字节缓冲区传递给write,我就不需要刷新了。我目前正在分析这两种方法中哪一种表现更好:

  • pubsetbuf每次写入+ flush(怀疑网络性能不佳)
  • 没有pubsetbuf,写作和最后一次冲洗

这说明了覆盖率大大降低的问题(注释stream.flush()重新使用,以使其正常运行):

vector<double> data;
for (int i = 0; i < 400; ++i) data.push_back(111.0);
for (int i = 0; i < 400; ++i) data.push_back(222.0);
for (int i = 0; i < 400; ++i) data.push_back(333.0);

bool lastPoint;
size_t numPoints = data.size();
size_t bytesPerValue = sizeof(data[0]);

// Create a byte buffer
static const size_t BUFFER_SIZE = 8192;
vector<unsigned char> buffer;
buffer.resize(BUFFER_SIZE);
size_t bufferIndex = 0;
bool bufferFull = false;

// Create output stream
ofstream stream("\\\\server\\networkpath\\output.dat", ios::binary);

// Set stream buffer to avoid write calls
stream.rdbuf()->pubsetbuf(reinterpret_cast<char*>(&buffer[0]), BUFFER_SIZE);

for (size_t i = 0; i < numPoints; i++)
{
    lastPoint = i == (numPoints - 1);

    // Write to buffer
    memcpy(&buffer[bufferIndex], reinterpret_cast<const unsigned char*>(&data[i]), bytesPerValue);

    // Find next empty index
    bufferIndex += bytesPerValue;

    bufferFull = ((bufferIndex + bytesPerValue) > BUFFER_SIZE);

    if (lastPoint || bufferFull)
    {
        stream.write(reinterpret_cast<const char*>(&buffer[0]), bufferIndex);

        //stream.flush();

        // If the line above is commented back in, the content of the output file is correct.
        // However, I wish to avoid flushing often when writing across network.
        // Without commenting back in, the file contains the expected number of bytes (9600) but the data in the second write call 
        // (bytes 8193-9600) appears both at the start and end of the file.

        bufferIndex = 0;
    }
}
stream.flush();
stream.close();

有没有办法通过pubsetbuf使用缓冲技术,而不需要每次执行写入时刷新?

0 个答案:

没有答案