Понимание Ruby и OS I / O буферизации - PullRequest
30 голосов
/ 15 июля 2011

Как работает буферизация ввода-вывода в Ruby? Как часто данные сбрасываются в базовый поток при использовании классов IO и File? Как это соотносится с буферизацией ОС? Что нужно сделать, чтобы гарантировать, что данные были записаны на диск, прежде чем уверенно читать их для обработки?

Ответы [ 2 ]

54 голосов
/ 15 июля 2011

Документация 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: закрывает Ruby IO и записывает ожидающие данные в ОС. Обратите внимание, что это не означает fsync(). Документация POSIX по close() говорит, что она НЕ гарантирует, что данные физически записываются в файл. Поэтому для этого нужно использовать явный fsync() вызов.

Вывод: flush и / или close должно быть достаточно для кэширования файла, чтобы его можно было полностью прочитать другим процессом или операцией. Чтобы с полной уверенностью передать файл на физический носитель, вам нужно позвонить IO.fsync.

Другие родственные методы:

  • IO.syswrite: Обойти внутренние буферы Ruby и выполнить прямую ОС write. Если вы используете это, не смешивайте его с IO.read/write.
  • IO.sysread: То же, что и выше, но для чтения.
2 голосов
/ 15 июля 2011

Ruby выполняет внутреннюю буферизацию поверх ОС.Когда вы делаете file.flush, Ruby очищает свой внутренний буфер.Чтобы файл был записан на диск, вам нужно выполнить file.fsync.Но, в конце концов, вы не можете быть уверены, что файл все равно записывается на диск, это зависит от ОС, контроллера жесткого диска и жесткого диска.

...