Понимание 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. Но, в конце концов, вы не можете быть уверены, что файл все равно записывается на диск, это зависит от ОС, контроллера жесткого диска и жесткого диска.

Другие вопросы по тегам