Запись ostream в поток байтов (или другое решение для повышения производительности записи) - PullRequest
0 голосов
/ 05 августа 2020

У меня есть старый код, который записывает файлы составных блоков, которые очень медленно записываются в файл из-за интенсивного использования tellp и seekp, которые уничтожают все буферы.

Это работает так (псевдокод) :

WriteFile()
{
    ostream ofStream = GetStream(strBlockFileName);
    WriteFileHeader(ofStream);

    // Write a directory
    WriteDirStart(ofStream); 
    auto realItemInfo = WriteAllData(ofStream); // Write all data to the file
    UpdateDirOnClose(ofStream, realItemInfo);
    
    // Write next directory
    WriteDirStart(ofStream);
    auto realItemInfo = WriteAllData(ofStream);
    UpdateDirOnClose(ofStream, realItemInfo);

    // Write third directory
    ...
    ofStrem.close();
}

WriteAllData(...)
{
    for (auto& rItem : allItems)
    {
        rItem.Write(ofStream); // Also a bit slow since it writes just small data chunks
    }
}

WriteDirStart(...)
{
    // Write directory in compound file
    startPos = ofStream.tellp(); // Save the start position of the directory
    WriteStartPos(ofStream, startPos);

    // Write dummy info to reserv the correct space
    WriteDummyNumIntemInfo(ofStream, numItems);
    WriteDummyDirectoryEndPos(ofStream, startPos);
}

UpdateDirOnClose(...)
{
    // This is the slow part when updating the header at the end when the information 
    // is known due to changing positions in the file stream.
    auto pos = ofStream.tellp();
    ofStream.seekp(startPos); // Change to beginning of the directory
    WriteStartPos(ofStream, startPos);
    WriteRealNumIntemInfo(ofStream, realItemInfo);
    WriteRealDirectoryEndPos(ofStream, pos);
    ofStream.seekp(pos); // Change back so next directory can continue to write at correct position
}

Я подумал, можно ли записать каждый "каталог" из потока в буфер памяти, а затем записать весь буфер в файл, так как я предполагаю, что tellp и seekp не будут такими плохими влияние на буфер памяти. Итак, если есть какой-то байтовый буфер, который растет, может быть, как stringstream, или если есть что-то более эффективное, совместимое с ofstream.

Есть ли у вас какие-либо предложения, как это реализовать (или использовать что-то существующее, например, boost) или другие предложения, чтобы ускорить процесс? 70% времени тратится на seekp при обновлении заголовка каталога.

(Для чтения я "решил" это, используя файлы с отображением в память, так как при чтении как ну, но я не могу этого сделать для записи, поскольку размер заранее не известен. Это старый формат файла, поэтому я не могу многое сделать с файловой структурой.)

Все идеи приветствуются!

...