LINUX.ORG.RU

кэш, O_DIRECT и sync


1

1

Странные дела творяться...

Написал небольшую программулину, которая открывает файл с O_DIRECT и пишет туда, скажем, 10 Gb. Просто буфер максимального размера выравниваю по странице и в цикле делаю write.

Работает, кэш не засоряет, проверено.

Сравниваем с ней же, но без O_DIRECT, а время меряется time'ом с sync'ом, типа

time sh -c "./iotest ; sync"

Результат -- раза в 2 быстрее.

Пробовал монтировать директорию с опцией sync -- то же самое.

Пробовал даже вместо sync делать umount -- то же самое.

Кто может объяснить?

Да, RAM'а у меня 65 Gb

★★★★★

не знаю точного обьяснения но в мане написано:

     O_DIRECT may be used to minimize or eliminate the cache effects
     of reading and writing.  The system will attempt to avoid caching
     the data you read or write.  If it cannot avoid caching the data, 
     it will minimize the impact the data has on the cache.  Use of this
     flag can drastically reduce performance if not used with care.

lg ★★
()

2 both lg and ananas:

Я проверял, кэш остается чистым.

И вот выдержка из мануала, который соответствует моему ядру:

       O_DIRECT
              Try to minimize cache effects of  the  I/O  to  and
              from  this file.  In general this will degrade per╜
              formance, but it is useful in  special  situations,
              such  as  when  applications  do their own caching.
              File  I/O  is  done  directly  to/from  user  space
              buffers.  The I/O is synchronous, i.e., at the com╜
              pletion of the read(2)  or  write(2)  system  call,
              data   is  guaranteed  to  have  been  transferred.
              Transfer sizes, and the alignment  of  user  buffer
              and  file offset must all be multiples of the logi╜
              cal block size of the file system.
              This flag is supported on  a  number  of  Unix-like
              systems;  support  was  added under Linux in kernel
              version 2.4.10.
              A semantically similar interface for block  devices
              is described in raw(8).

Die-Hard ★★★★★
() автор топика

> Просто буфер максимального размера...

А что значит "максимального размера"? Ежели буфер 10гиг, то на кой нужен цикл?

И еще: что выдает time? Если время затраченное процессом, без учета ядерных задержек (ожидание готовности железа, получение результатов как оно там отработало итп.), то может имеет смысл секундомером померять? 2 раза можно легко увидеть даже при скорости записи 30-40 Мег/сек.

yuriy123
()
Ответ на: комментарий от Die-Hard

это .. с профайлером бы собрал да посмотрел бы скока они болтаются в write(2) сысколах

Возможно что не используя системный кеш ты постоянно получаешь пенальти?

lg ★★
()
Ответ на: комментарий от yuriy123

yuriy123 (12.11.2004 15:38:53):

> А что значит "максимального размера"?

Есть ioctl, возвращающий максимальный размер буфера, допустимого для direct I/O.

> И еще: что выдает time?

Я wall-clock time мерил. Считай, секундомером.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от lg

lg (12.11.2004 15:54:09):

> с профайлером бы собрал да посмотрел бы скока они болтаются в write(2) сысколах

Угу надо попробовать. Но я думаю, что оно там проводит ВСЕ время.

> Возможно что не используя системный кеш ты постоянно получаешь пенальти?

Не понимаю, можно подробнее?

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

> Угу надо попробовать. Но я думаю, что оно там проводит ВСЕ время.

все то это да, но само поведение .. то есть посмотреть не суммарно а по каждому вызову .. мне кажется что будет типа:

один раз пишет бысто, второй раз тупит, или два раза быстро потом один раз тупит

>> Возможно что не используя системный кеш ты постоянно получаешь пенальти?

> Не понимаю, можно подробнее?

не уверен, но может быть что без использования сыстемного кеша не хватает процового кеша при трансфере данных и возникает так называемый miss penalty(когда процу надо обновить блок кеша). Которые конечно же возникают и при кеше но в меньших количествах

lg ★★
()
Ответ на: комментарий от lg

lg (*) (12.11.2004 17:40:42):

> ...может быть что без использования сыстемного кеша не хватает процового кеша при трансфере...

А в чем принципиальная разница между сбросом на SCSI шину системного кэша и сбросом туда же моего буфера (с точки зрения проца)?

То есть, единственная разница -- мой буфер копируется из юзерспейса, а системный кыш в кернеле живет (кастати, а так ли это?). IMHO процессору должно быть наплевать...

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

> А в чем принципиальная разница между сбросом на SCSI шину системного кэша и сбросом туда же моего буфера (с точки зрения проца)?

> То есть, единственная разница -- мой буфер копируется из юзерспейса, а системный кыш в кернеле живет (кастати, а так ли это?). IMHO процессору должно быть наплевать...

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

на самом деле я не знаю как это работает :), так что меня можешь не слушать вообще

эй linux kernel хакеры, подскажите как все это происходит в Linux?

lg ★★
()

при записи с O_DIRECT мы избавляемся от копирования
данных в page_cache, это единственный выигрыш с точки
зрения производительности.

зато каждый вызов write() теперь делает filemap_write_and_wait()
перед и invalidate_inode_pages2() после собственно вывода.

но это не главное. хуже то, что вывод теперь синхронный,
то есть, каждая запись идет сама по себе, без помощи
(фактически) io-scheduler. и каждый раз нужно ждать
завершения записи.

без O_DIRECT requests могли быть merged, переставлены,
и т.д. 

кроме того там было, вроде бы много проблем (с точки
зрения производитеоьности), а у вас, кажется, 2.4.

по поводу кэша процессорного. не забывайте, что без
O_DIRECT вы копируете "горячие" (то есть, уже в кэше)
данные. в тот момент, когда они будут писаться на диск,
они, скорее всего, из кэша утекут, но это и не требуется,
т.к. процессор на них и смотреть не будет - DMA. поэтому
потери на копирование не такие уж большие.

idle ★★★★★
()
Ответ на: комментарий от idle

2idle :

Thanks, уже ближе.

Может, посоветуете, как мне данные из юзерспейса загнать прямиком в файловую систему? Мне всего лишь надо замерить ее производительность, поэтому всякие xscsicontrol не годятся -- они прямо на шину гонят.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от idle

> т.к. процессор на них и смотреть не будет - DMA

a da, tochno! .. miss penalty igraet rol' tol'ko dlya PIO mode, da? ..

PS: translit COCET

lg ★★
()
Ответ на: комментарий от Die-Hard

Die-Hard:

IMHO, записью в файл бессмысленно мерять производительность файловой системы, тем более, если она слабо фрагментирована и использует hints вроде prealloc. Даже ext2 с ее дурацкими битмапами не будет "проваливаться" на выделении блоков, поскольку групповые дескрипторы она резидентно хранит в памяти, ну и ко всему прочему испольует preallocation. Куда интереснее операции с метаданными (например, много нитей бегает по директориям, создает файлы, директории, удаляет) - вот тут ext2 и подобные файловые системы с "плоскими" директориями могут сильно проседать.

В принципе, обычно в дистрибутивы Linux включаются утилиты тестирования производительности (напр, bonnie). Если есть надобность, то можность достать более интересный benchmark вроде SPEC SFS.

Murr ★★
()
Ответ на: комментарий от Murr

Имеется в виду "проседание" ext2 при поиске. При добавлении/удалении возможны разные варианты (как значительно медленнее, так и значительно быстрее).

В принципе, единственный разумный тест ФС - это моделирование интересующей нагрузки.

Murr ★★
()
Ответ на: комментарий от Die-Hard

> Мне всего лишь надо замерить ее производительность,
> поэтому всякие xscsicontrol не годятся -- они прямо
> на шину гонят.

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

мне кажется, единственный _полезный_ способ, это
мерять "real workload", то есть то, что вам действитльно
нужно делать, и, соответственно, оптимизировать.

в качестве первого приближения я не придумал бы
ничего лучшего, чем dd if=/dev/zero + sync, что
вы, собственно, и делали.

кстати, новые версии dd должны иметь флажок для
O_DIRECT i/o.

написал много, в итоге: не знаю, что посоветовать :)

idle ★★★★★
()
Ответ на: комментарий от Murr

Murr:
> В принципе, единственный разумный тест ФС -
> это моделирование интересующей нагрузки.

во, пока писал, пришел Murr и все одной
строкой выразил.

idle ★★★★★
()
Ответ на: комментарий от idle

idle:

>во, пока писал, пришел Murr и все одной строкой выразил.

По моему маленькому опыту, самое забавное в ФС (да и вообще в БД, наверное) - это когда придумываешь новую оптимизацию, а оказывается, что при определенной нагрузке она наоборот только является тормозом. И встает вопрос включать ее или не включать. Если те же B-деревья для описания blockmap ,директорий или preallocation дают оптимизацию для широкого класса нагрузок, то те, что удается придумать - фифти-фифти.

В принципе, наверное, сложно придумать новую технологию доступа, которая при общих схемах загрузки может дать заметный прирост производительности, зато можно достаточно серьезно ковырять отказоустойчивость(в первую очередь mirroring) и масштабируемость (эффективная интеграция с LVM; в свою очередь LVM, поддерживающая эффективный доступ как к локальным, так и удаленным носителям, естественно, с динамической поддержкой удаления и добавления дисков; HSM и др.), что не менее интересно.

Murr ★★
()
Ответ на: комментарий от Murr

Есть еще интересная нерешенная задача эффективной динамической дефрагментации в рамках существующей ФС.

Murr ★★
()

Thanks 2 all.

Конечно, наглость -- спрашивать в форуме столь конкретный вопрос, но, может, что полезное присоветуете,,,

У меня есть конкретное приложение, под которое нужно оптимизировать конфигурацию xvm. Приложение представляет собой штук 30 процессов, каждый из которых интенсивно читает из одного большого файла и пишет в другой большой файл. Имеется 16 SCSI дисков, собранных в один volume с помощью xvm, который отформатирован под XFS. Доступ идет по 4 SCSI шинам, т.е. по 4 диска на шину. Я пытаюсь, играя конфигурацией xvm (и параметрами XFS), добиться максимальной приоизводительности.

Проблема в том, что bottleneck'ом являются как раз дисковые операции, но они начинаются через несколько часов после старта приложения, поэтому тест на реальной задаче длится не меньще суток -- не наиграешься параметрами! Поэтому мне хочется как-то оценить производительность FS при линейной записи большого файла.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Murr

2Murr:

> Если те же B-деревья для описания blockmap ,директорий или preallocation дают оптимизацию для широкого класса нагрузок,

Чисто теоретическо-познавательный вопрос: а почему именно B-деревья так широко используются в FS? У меня создалось впечатление (впрочем, тут я СОВЕРШЕННО не специалист), что в любой FS используется либо "плоская" структура, либо B-деревья. Почему не двоичные деревья, не хэш-таблицы, не комбинации?

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

> Проблема в том, что bottleneck'ом являются как раз дисковые
> операции, но они начинаются через несколько часов после старта
> приложения

а вы уверены, что узким местом является именно запись?
может быть что угодно, read starvation, vm trashing...

попробуйте посмотреть vmstat, когда проблемы начинаются.
посмотрите sysrq+t, где процессы спят. проверьте, не
светятся ли kswapd, pdflush в top'е.

у вас нестандартное ядро, если туда backported fadvise(),
может иногда помочь.

конкретно про xfs ничего не знаю.

idle ★★★★★
()
Ответ на: комментарий от Die-Hard

Die-Hard > Почему не двоичные деревья, не хэш-таблицы, не комбинации?
А кто сказал, что хэш функции вообще не используются.
В vxfs они, например, используются.
Двоичные деревья не самый сахар для реализации на внешних устройствах.
Если использовать стандартные алгоритмы, то придется читать или
писать больше блоков, чем для других типов хранения.
Это же все можно найти у Кнута.
В этом плане B-деревья обычно удивительно удачны и не только
для внешних устройств.

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

Каков таки общий объем записываемых данных?
Сколько времени идет сброс этих данных?
Какими объемами происходит обмен c FS?
Точно ли проблема в выводе, а не в синхронизации и т.п.?
Если файлы разбросаны по дискам и контроллерам, то иногда гигабайты
уходят удивительно быстро.

io ★★
()
Ответ на: комментарий от io

2io (*) (14.11.2004 13:11:47):

Thanks. Действительно, у Кнута все подробно разжевано.

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

> Каков таки общий объем записываемых данных?

Приложение состоит из 15-30 процессов. Каждый процесс занят тем, что циклами читает из одного большого файла и пишет в другой файл. В следующем цикле файлы меняются местами. Общее количество циклов зависит от сложности задачи; от сотен до сотен тысяч. Размер файлов тоже зависит от сложности задачи и составляет от мегабайтов до сотен гигабайт.

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

Вообще говоря, дисков не хватает, то есть мы упираемся в ограниченность ресурсов. Всего у нас 16 дисков по 146 Gb, так что мне нужно оптимизировать эту схему из рассчета одновременного попарного чтения/записи 2x15 файлов по 50 Gb каждый, но чтобы оно не проваливалось на гораздо более мелких и в 2-3 раза более крупных файлах.

> Какими объемами происходит обмен c FS?

Настраиваемый параметр, к сожалению, не независимый. Обычно используется чтение и запись вызовами read/write буферами по 120 Mb

> Точно ли проблема в выводе, а не в синхронизации и т.п.?

idle(14.11.2004 11:55:46):

> а вы уверены, что узким местом является именно запись? может быть что угодно, read starvation, vm trashing...

Разумеется, там не один bottleneck.

Просто я вижу, что называется, органолептически, что основное время приложение шуршит дисками.

> посмотрите sysrq+t, где процессы спят.

А они вообще не спят :0. Артефакт MPI, синхронизация через busy work. Только один такой процесс на процессор.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

Die-Hard:

Если я правильно понял вопрос, то B-деревья дают время поиска имени или экстента за C*log(n) и просты в реализации. Можно ли ассимптотически улучшить оценку?

Murr ★★
()
Ответ на: комментарий от Die-Hard

Die-Hard:

Т.е. есть всего два (нефрагментированных) файла, к которым идет одновременный доступ?

Тут я согласен с idle - можно попробовать поиграть параметрами readahead в зависимости от схемы доступа. direct_IO тут противопоказан, поскольку, как опять же сказал idle, будет сильная синхронность и помеха io-scheduler'у. Если хочется самому контроллировать процесс записи на диск, то лучше временами вызывать sync - это будет ничем не хуже direct_IO.

Murr ★★
()
Ответ на: комментарий от Murr

Murr (14.11.2004 22:24:49):

> Еще глупый вопрос: как объединены диски - в stripe set?

Сейчас они в одной страйпе, сортировано по шинам: 

шина 1 диск 1
шина 2 диск 1
шина 3 диск 1
шина 4 диск 1
шина 1 диск 2
шина 2 диск 2
etc.

Есть бысль организовать все в страйп над 4 другими страйпами, в xvm
мануале намекают, что для параллельного доступа будет лучше. 

Собственно, этим я и хочу поиграть попробовать.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Murr

Murr (14.11.2004 22:15:41):

> Т.е. есть всего два (нефрагментированных) файла, к которым идет одновременный доступ?

Из одного адресного пространства -- да.

Но у меня 30 процессов делают это одновременно.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Murr

Murr (14.11.2004 22:02:37):

> ...B-деревья дают время поиска имени или экстента за C*log(n)...

Ну, они все дают C*log(n), а от хешей можно даже O(1) добиться.

Я полистал Кнута -- в общем, понятно; просто B-деревья -- самое "универсальное".

Кстати, кто-нибудь знает, что означает буква "B"? У меня такое воспоминание, что история возникновения этого термина утеряна.

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

Die-Hard:

>Ну, они все дают C*log(n), а от хешей можно даже O(1) добиться.

Не понял. Как это O(1)? Для любой директории за фиксированное число операций находить любой элемент? Давайте считать для худшего случая.

Murr ★★
()
Ответ на: комментарий от Murr

Лучший случай для деревьев с элементами в листьях, конечно, хуже, чем для хэшей или даже плоских директорий а-ля EXT2, но если усреднить или посчитать худший случай, то деревья смотрятся достаточно оптимально.

Нам, кстати, даже было такое пожелание - желательно, чтобы fs performance была без рывков и проседаний, многим пользователям это не нравится.

>Есть бысль организовать все в страйп над 4 другими страйпами, в xvm >мануале намекают, что для параллельного доступа будет лучше. > >Собственно, этим я и хочу поиграть попробовать.

Забавно, кстати, в нашем случае можно было бы allocation policy задать вполне осмысленно на уровне файловой системы (нужный prealloc, striping, mirroring и др. allocation policies) через webmin или Java апплет.

Лишний раз убеждаюсь в том, что интеграция LVM и файловой системы - вполне здравая идея. :)

Murr ★★
()
Ответ на: комментарий от Murr

Murr (*) (15.11.2004 0:23:29):

> Не понял. Как это O(1)? Для любой директории за фиксированное число операций находить любой элемент?

Ok, "псевдо" O(1) (по аналогии с термином "псевдополиномиальный алгоритм"): если длины имен и допустимая глубина поддиректорий ограничены, а хэш-функция подобрана так, чтобы ранг конфликта тоже был ограничен.

Практическая ценность подобной конструкции, конечно, сомнительна (хотя, для специфических случаев -- кто знает?), но чисто теоретически по числу файлов будет O(1).

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

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

В этом плане очень интересен вопрос о зависимости процессов друг
от друга и их размере.

Вообще-то не ясно зачем нужен буфер в 120Мб. Обычно нормальные
буфера начинаются в 10-150% от дискового кэша. Удар же по записи
в системный кэш не обязан ничего особенного давать даже при
наличии такой памяти. А вот пересечение записи/чтения гарантировано.

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

io ★★
()
Ответ на: комментарий от io

io (15.11.2004 20:29:51):

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

Увы, никак. ПРоцессы, конечно, очень до диска охотчивы, но основная их обязанность, все же, не просто переписать данные из файла в файл, но еще и сделать над ними нетривиальные операции.

> Вообще-то не ясно зачем нужен буфер в 120Мб.

Это -- не совсем буфер. Это -- порция данных, обрабатываемых в оперативной памяти.

Без проблем раздробить чтение/запись на меньшие фрагменты -- только зачем? Все равно мне нужно за один присест обмениваться с диском по 120 Mb (как показали эксперименты).

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

Может имеет смысл сотворить несколько разных файловых систем, может с ними будет идти параллельная работа. ИМХО, при работе с одной ФС в ядре идут сплошные блокировки.

У меня как то получалось, что когда 2 приложения на однопроцессороной системе "дерутся" за винт, причем за разные файлы, то все становится значительно лучше, если этот винт разбить на 2 раздела = 2 файловые системы... Хотя это очень субъективно, ничего не мерил...

Может "засинхронизовать" процессы, чтобы с ФС общался только 1 процесс, а остальные, если им нужно, ждали его. Тогда не будет не будет одновременной записи нескольких буферов/файлов из нескольких процессов и стриппинг должен помогать.

А приложение нельзя остановить в произвольный момент времени и потом стартовать с этого места --- для тестовых замеров? Правда 16 файлов по 50 ГБ еще куда то скопировать надо...

mky ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.