#c #performance #ofstream #file-writing
Вопрос:
Я создал функцию, которая сохраняет данные без знака char* в двоичный файл. Процесс реализуется в отдельном потоке и должен добавлять данные, полученные из очереди (boost::lockfree::очередь). Мой SSD-накопитель теоретически способен развивать скорость записи до ~5000 Мбит/с, однако я заметил, что она вряд ли когда-либо превышает 500 Мбит/с. Я нахожусь на платформе Windows, если это имеет значение. В чем может быть узкое место в приведенном ниже коде?
Настройка: канал камеры —> плата сбора изображений —>> запись данных в память —>>> данные очереди с помощью boost::без блокировки::очередь —>>>> всплывающие данные по требованию —>>>>> сохранить в двоичный файл
void SaveData::saveAsBinary(std::string filePath, DataFeed *d)
{
saveThreadADone = false; // std::atomic<bool> flag
std::thread storeDataThread([this, filePath, d] {
std::ofstream file = open(filePath, std::ios::beg | std::ofstream::out | std::ofstream::ate | std::ofstream::binary);
if(outputFile.fail()){
throw std::runtime_error("Cannot open file for saving.");
}
while(!d->isDataEmpty()) // Assume data collection is already done
{
auto bufferData = d->getData().get(); // getData returns std::unique_ptr<unsigned char[]>
size_t bufferDataSize = sizeof (bufferData);
file.write(reinterpret_cast<char const*>(bufferData), bufferDataSize);
if (!file.good())
{
throw std::runtime_error("There was an error while saving buffer data to file.");
}
}
file.close();
this->saveThreadADone = true;
});
storeDataThread.join();
}
std::unique_ptr<unsigned char[]> DataFeed::getData()
{
std::unique_ptr<unsigned char[]> output(nullptr);
if(!dataQueue.empty()){ // boost::lockfree::queue<unsigned char*> dataQueue {100}
dataQueue.pop(output);
}
return output;
}
bool DataFeed::isDataEmpty()
{
return dataQueue.empty();
}
// Somewhere else in the code
saveData_->saveAsBinary("specifiedPath", *dataFeed);
Комментарии:
1. 1) Какой смысл начинать новый поток, а затем присоединяться к нему? 2) Интересно, насколько велики буферы? Возможно, вы тратите слишком много времени на получение буферов? Это больше похоже на миллион буферов с 5 байтами или на 5 буферов с миллионом байтов?
2. чтобы расширить 1,
thread t1{ [](){ ...}}; t1.join();
добавьте накладные расходы на создание и присоединение к потоку, но отсутствие параллелизма в вашем коде3. Я согласен с @user253751: Запуск и объединение потоков является обширным. Вместо этого я бы подумал о том, чтобы начать поток с самого начала и использовать a
std::condition_variable
для запуска активации. Таким образом, поток будет спать до тех пор, пока в нем не возникнет необходимости. Я уже делал «сброс файлов в фоновом режиме» таким образом. Я не могу назвать вам фактическую скорость передачи данных. В моем случае это было просто достаточно быстро. Следовательно, я не стал анализировать дальше…4. Чтобы объяснить дальше: предположим, что поток отсоединен, чтобы он мог выполнять задачу в фоновом режиме. Я могу прочитать информацию о размере буфера с аппаратного обеспечения, и она сообщает, что одно изображение будет занимать 5242880 байт. То, что я сохраняю, — это изображения одно за другим. В зависимости от решения пользователя их может быть либо несколько, либо много.
5. предположим, что нить отсоединена , Почему вы хотите отсоединить нить? Отсоединенная нить больше не может быть соединена, что лишает ее возможности разорвать ее контролируемым образом, когда она больше не нужна. Я не знаю о каком-либо преимуществе в производительности отдельного потока по сравнению с присоединяемым потоком (по крайней мере, пока он просто запущен).