Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Аналог writev для записи в файл нескольких буферов


Автор: phprus 7.10.2011, 21:07
Доброго времени суток!

Хочу оптимизировать запись, в файл журнала, данных, которые находятся в нескольких буферах.

В Linux версии это реализуется через открытие файла в режиме ( O_CREAT | O_WRONLY | O_APPEND ), подготовки вектора буферов struct iovec и записи его в файл при помощи функции writev.
В Windows версии сейчас используется открытие файла при помощи "::_open(file_name.c_str(), ( _O_CREAT | _O_WRONLY | _O_APPEND | _O_TEXT | _O_SEQUENTIAL ), (_S_IREAD | _S_IWRITE))", но из-за отсутствия функции writev приходится собирать данные в один буфер и записывать его одним вызовом _write.
Так как данных для записи много, то излишние копирования и операции распределения памяти занимают достаточную долю времени, чтобы на них стоило обратить внимание. Использование нескольких write подряд недопустимо по причине того, что функция логирования должна быть потокобезопасной, а такие гарантии дает только вызов writev или _write.


Подскажите пожалуйста, можно ли реализовать в Windows дозапись в конец файла блоков данных из нескольких буферов, те по сути реализовать некоторый аналог writev из POSIX?

Автор: 12usver12 7.10.2011, 23:29
Цитата

Использование нескольких write подряд недопустимо по причине того, что функция логирования должна быть потокобезопасной

мне кажется вы сильно усложняете все , используйте синхронизацию - например самый простой вариант через критическую секцию 
Код

EnterCriticalSection(
MyWriteLog(...);
LeaveCriticalSection(

или используйте memory mapped files

Автор: phprus 8.10.2011, 09:30
Цитата(12usver12 @  8.10.2011,  02:29 Найти цитируемый пост)
мне кажется вы сильно усложняете все , используйте синхронизацию - например самый простой вариант через критическую секцию 

Возможно. Дело в том, что POSIX системы гарантируют атомарность write() и writev(), а так как остальной код итак потокобезопасен, то синхронизации не нужны, достаточно подготовить цепочку буферов и передать ее в writev. Windows-код через _write изначально был прямым переносом POSIX кода (и судя по исходникам CRT, _write тоже атомарна).


Цитата(12usver12 @  8.10.2011,  02:29 Найти цитируемый пост)
или используйте memory mapped files 

Подскажите пожалуйста, как можно гарантированно дописывать данные в конец файла через memory mapped files или через WinAPI? Желательно так-же обеспечить возможность тем-же кодом писать на стандартный поток ошибок консольного приложения.

Автор: boostcoder 15.11.2011, 23:19
phprus, ты ведь активно используешь asio. там ведь есть асинхронный файловый ввод-вывод: http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio/reference/windows__stream_handle.html. по аналогии с вводом-выводом на сокетах, используй write()/async_write() и передавай ее BufferSequence.

или что?

Автор: vol4ek 16.11.2011, 00:31
можно и API конечно. WriteFile() и SetFilePointer() на самый крайний случай. Черевато проблемами при чтении.

Автор: phprus 16.11.2011, 13:21
boostcoder, 
Использую, есть, но для него BufferSequence должны содержать указатели, которые будут валидны до вызова completion handler, а я и хотел избавиться в том числе от лишних вызовов распределений памяти.

Так как асинхронность мне в этой части не обязательна, а скорее даже вредна (если включен дебаг лог, то приложение должно падать записав максимум событий smile , а именно при включенном дебаг-логе подсистема записи начинала мозлить глаза при профайлинге ), то итоговое решение стало компромиссным. От копирования сообщений в промежуточный буфер в Windows я конечно не избавился, но буфера стали фиксированной длины и часть из них thread local, что позволило решить проблему с постоянными операциями выделения памяти и в итоге (+ еще некоторые изменения, не связанные с данной темой) раз в 5-10 ускорили весь процесс записи логов.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)