Я наблюдаю следующее поведение с помощью метода библиотеки C ++ Std std :: ostream :: write ().
Для буферизации данных я использую следующий C ++ API
std::ofstream::rdbuf()->pubsetbuf(char* s, streamsize n)
Это прекрасно работает (проверено с помощью утилиты strace), пока размер данных (размер данных), которые мы записываем в поток файлов, используя
std::ofstream::write (const char* s, datasize n)
Меньше 1023 байта (ниже этого значения записи накапливаются до тех пор, пока буфер не заполнится), но когда размер записываемых данных превышает 1023, буфер не учитывается и данные сбрасываются в файл.
например Если я установлю размер буфера в 10 КБ и запишу около 512 байт за раз, strace покажет, что несколько записей были объединены в одну запись
writev(3, [{"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 9728}, {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 512}], 2) = 10240 ( 10 KB )
writev(3, [{"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 9728}, {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 512}], 2) = 10240
...
но когда я записываю 1024 байта за раз (оставляя буфер фиксированным до 10 КБ), теперь strace показывает мне, что он не использует буфер, и каждый вызов ofstream :: write транслируется для записи системного вызова.
writev(3, [{NULL, 0}, {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 1024}], 2) = 1024 ( 1KB )
writev(3, [{NULL, 0}, {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 1024}], 2) = 1024
...
Есть ли какой-нибудь C ++ API Call или Linux Tuning Parameter, который мне не хватает?
Это деталь реализации libstdc ++, реализованная в строке 650 бит / fstream.tcc. По сути, если запись больше 2 ^ 10, буфер будет пропущен.
Если вы хотите обосновать это решение, я предлагаю вам отправить письмо в список разработки libstdc ++.
Похоже, кто-то, пишущий реализацию stdlib, произвел «оптимизацию», не задумываясь об этом. Таким образом, единственный обходной путь для вас будет избегать C ++ API и использовать стандартную библиотеку C.
Это не единственная субоптимальность в реализации стандартной библиотеки C ++ для GNU / Linux: на моей машине malloc()
на 100 циклов быстрее, чем стандарт void* operator new (size_t size)
…