Объяснение / искомая информация: Windows записывает производительность ввода-вывода с помощью "fsync" (FlushFileBuffers)

Этот вопрос является продолжением предыдущего вопроса, который я опубликовал: производительность Windows fsync (FlushFileBuffers) с большими файлами. Где я нашел возможное решение, но и новые вопросы.

При сравнении различных сценариев для записей fsynced я обнаружил ряд удивительных результатов. Я надеюсь, что кто-то может помочь объяснить или указать мне направление информации, которая объясняет эти результаты.

То, что делает этот эталонный тест, - это запись случайных блоков (страниц размером 4096 байт) в файл последовательно в виде пакетов по 8 страниц (32 Кбайт) с последующей очисткой записей. Он записывает в общей сложности 200000 страниц, что в сумме составляет 800 МБ и 25000 сбросов. Размер файла устанавливается до его окончательной длины перед началом записи.

Он поддерживает всего 4 опции, из которых запускаются все комбинации:

  • Для выполнения "fsync"/FlushFileBuffers операция (FS) после записи партии или нормального сброса (NS).
  • Чтобы записать один байт в последнюю позицию файла перед началом записи (LB) или оставить файл пустым (E).
  • Использовать обычные буферизованные записи (B) или небуферизованные / записи (WT) (используя FILE_FLAG_NO_BUFFERING и FILE_FLAG_WRITE_THROUGH).
  • Для записи непосредственно в файловый поток, т.е. через дескриптор файла (F) или косвенной записи в файл с использованием карты памяти (MM).

В таблице ниже обобщены мои выводы о моей системе (64-битный ноутбук Win 7 с медленным диском шпинделя) для всех комбинаций этих опций.

Результаты тестов для всех комбинаций опций

Я обнаружил, что производительность буферизованных записей "fsynced" экспоненциально уменьшается с размером файла до невероятно низкой пропускной способности, что делает это невозможным в сочетании с большими файлами. Если в файл был записан последний байт (опция LB), пропускная способность еще ниже, поэтому я опасаюсь, что при случайных, а не последовательных сценариях записи производительность будет еще более существенной.

Удивительно, однако, что при небуферизованном / перезаписываемом вводе / выводе пропускная способность остается постоянной, независимо от размера файла. Первоначально (первые 100-200 МБ) он имеет меньшую пропускную способность, чем буферизованные записи, но после этого средняя пропускная способность быстро догоняет и значительно быстрее завершает запись 800 МБ. Еще более удивительным является то, что если в файл был записан последний байт, пропускная способность возрастает в 2 раза.

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

ОБНОВЛЕНИЕ На основании объяснений Говарда здесь и здесь, я перезапустил тест, не создавая новый файл перед началом записи (т.е. открывая существующий, полностью записанный файл и перезаписывая его). Я обновил код в своем первоначальном вопросе, чтобы отразить изменения, внесенные в этот тест. Результаты частично соответствуют его объяснениям и выводам о Linux. Но есть некоторые заметные исключения. В приведенной ниже таблице представлены результаты, красным цветом выделены значительные изменения, синим цветом выделены места, где изменений не произошло, и это вызывает удивление (то есть не соответствует ожиданиям, если эффекты, упомянутые в объяснении Говарда, были единственными действующими).

Результаты при перезаписи существующего файла

Для буферизованных записей в файл (т. Е. Не с помощью memmap) со сбросом "fsync" производительность теперь изменилась с экспоненциального затухания до постоянного тренда. Однако теперь это занимает гораздо больше времени, чем в предыдущих тестовых сценариях. Пропускная способность постоянная 1,5 МБ / с, где до начала она была около 20 МБ / с, чтобы экспоненциально снижаться до около 1,5 МБ / с. Может показаться, что возможное объяснение состоит в том, что метаданные файла также сбрасываются при каждой очистке, в результате чего полный оборот диска ищет местоположение метаданных.

Для сценариев "сквозной записи" в файл результаты записи последнего байта или нет теперь идентичны, что соответствует ожиданиям Говарда.

Однако записи на карту памяти, за одним заметным исключением, на самом деле не изменились, и это удивительно. Они по-прежнему демонстрируют тот же экспоненциальный спад в производительности записи (начиная примерно с 20 МБ / с, снижаясь до 1,8 МБ / с). Это говорит о том, что другой механизм работает. Единственное заметное исключение - если базовый файл был создан без FILE_FLAG_WRITE_THROUGH и выполняются сбросы "fsync". Этот сценарий теперь показывает постоянную (плохую) производительность с пропускной способностью около 1,6 МБ / с. Поскольку у меня были некоторые сомнения, я повторял этот сценарий несколько раз, каждый раз получая один и тот же результат.

Чтобы выяснить немного больше, я также перезапустил этот тест, используя файл меньшего размера (50000 страниц, объемом 200 МБ), чтобы подтвердить, что производительность fsync (для буферизованного ввода-вывода) действительно зависит от размера файла. Результаты показаны ниже, а те, которые заслуживают особого внимания, выделены красным.

Результаты в меньшем файле

Эти результаты хорошо коррелируют с тем, что было видно для более крупного файла. Заметные изменения заключаются в том, что записи немного более производительны для выделенных, где кажется, что они достигают предела около 7 МБ / с.

Подводя итог как весьма умозрительные выводы, основанные на наблюдениях за моей системой до сих пор:

  • Производительность "fsync" для окон в файлах с буферизованным вводом-выводом (т.е. без флагов FILE_FLAG_WRITE_THROUGH) экспоненциально уменьшается с количеством байтов, уже записанных в файл. Причина, по-видимому, заключается в необходимости каждый раз сбрасывать метаданные файла, что вызывает поиск диска в начале файла.
  • Производительность "fsync" в Windows при записи в файл с отображением в памяти также показывает экспоненциально снижающуюся производительность. В настоящее время у меня нет объяснения точного механизма (механизмов), вызывающего это.

Учитывая эту наблюдаемую производительность, по крайней мере для моего случая использования, эти два варианта ввода / вывода не будут представлять собой возможные решения.

Согласно предложению Грега, я перезапущу тест с отключенным кэшированием на дисках Windows, а также буду запускать код производительности, предоставленный Говардом, чтобы исключить вероятность того, что результаты будут искажены из-за моих собственных ошибок.

ОБНОВЛЕНИЕ 2 Я закончил тесты и в настоящее время собираю результаты. Чтобы не писать "полную историю", я заменю текущее содержание этого вопроса кратким изложением результатов, выводов и некоторыми выводами. Ответы Говарда на этот вопрос, а также возможность запуска своего кода для тестирования c рядом с.NET-кодом оказались наиболее полезными. Результаты этих приложений достаточно хорошо коррелируют. Ответ Rlb помог мне лучше понять, что такое "разумные цифры", связанные с дисками. Благодарю.

Часть вопроса остается без ответа. Особенно связано с наблюдаемым снижением (и зависящим от размера файла) производительности при записи в карту памяти. Это может быть связано с поиском / сбросом метаданных, но мне пока не ясно, почему / как.

2 ответа

Вы видите экспоненциальное снижение скорости на синхронизирующих запусках, потому что это не чисто последовательные рабочие нагрузки, как вы полагаете. Поскольку вы начинаете с нового файла каждый раз, ваши записи увеличивают его, и метаданные должны быть обновлены в файловой системе. Это требует многократных поисков, и по мере роста файла поиск с конца файла до метаданных занимает все больше и больше времени. Я также отправил это на ваш другой вопрос по ошибке, полный ответ там: /questions/5827825/proizvoditelnost-windows-fsync-flushfilebuffers-s-bolshimi-fajlami/5827827#5827827

Попробуйте отключить кеширование диска и репост?

В противном случае эти метрики бессмысленны (Fsync и write through могут фактически не попасть на диск). Windows по умолчанию включает кэширование диска и контроллера.

Greg

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