Понимание Ruby и буферизации ввода-вывода ОС
Как буферизация ввода / вывода работает в Ruby? Как часто данные сбрасываются в основной поток при использовании IO
а также File
классы? Как это соотносится с буферизацией ОС? Что нужно сделать, чтобы гарантировать, что данные были записаны на диск, прежде чем уверенно читать их для обработки?
2 ответа
Документация Ruby IO не на 100% ясна о том, как работает эта буферизация, но вот что вы можете извлечь из документации:
- Ruby IO имеет собственный внутренний буфер
- В дополнение к этому базовая операционная система может или не может дополнительно буферизовать данные.
Соответствующие методы для просмотра:
IO.flush
: ФлешиIO
, Я также посмотрел на источник Ruby и вызовIO.flush
также вызывает базовую ОСfflush()
, Этого должно быть достаточно для кэширования файла, но это не гарантирует физических данных на диск.IO.sync=
: Если установленоtrue
внутренняя буферизация Ruby не производится. Все немедленно отправляется в ОС, иfflush()
вызывается для каждой записи.IO.sync
: Возвращает текущую настройку синхронизации (true
или жеfalse
).IO.fsync
: Очищает оба буфера Ruby + вызовыfsync()
в ОС (если она это поддерживает). Это гарантирует полную очистку вплоть до файла физического диска.IO.close
: Закрывает рубинIO
и записывает ожидающие данные в ОС. Обратите внимание, что это не означает,fsync()
, Документация POSIX поclose()
говорит, что это НЕ гарантирует, что данные физически записываются в файл. Так что вам нужно использовать явныйfsync()
призыв к этому.
Заключение: flush
и / или close
должно быть достаточно для кэширования файла, чтобы он мог быть полностью прочитан другим процессом или операцией. Чтобы с полной уверенностью передать файл на физический носитель, необходимо позвонить IO.fsync
,
Другие связанные методы:
IO.syswrite
: Обойти Ruby внутренние буферы и сделать прямую ОСwrite
, Если вы используете это, то не смешивайте его сIO.read/write
,IO.sysread
То же, что и выше, но для чтения.
Ruby выполняет внутреннюю буферизацию поверх ОС. Когда вы делаете file.flush, Ruby очищает свой внутренний буфер. Чтобы обеспечить запись файла на диск, вам нужно выполнить file.fsync. Но, в конце концов, вы не можете быть уверены, что файл все равно записывается на диск, это зависит от ОС, контроллера жесткого диска и жесткого диска.