C программа, застрявшая на бесперебойном ожидании при выполнении диска ввод-вывод на Snow Leopard Mac OS X

Одна строка фона: я - разработчик Redis, базы данных NoSQL. Одной из новых опций, которые я реализую, является Виртуальная память, потому что Redis берет все данные в памяти. Благодаря VM Redis может передать редко используемые объекты из памяти диску, существует много причин, почему это работает намного лучше, чем разрешение ОС сделать работу для нас свопинг (объекты советов создаются из многих маленьких объектов, выделенных в не непрерывные места при сериализации к диску Redis они занимают в 10 раз меньше места по сравнению со страницами памяти, где они живут, и т.д).

Теперь у меня есть альфа-реализация, это работает отлично над Linux, но не так хорошо на Snow Leopard Mac OS X. Время от времени, в то время как Redis пытается переместить страницу из памяти в диск, процесс советов вводит бесперебойное состояние ожидания в течение многих минут. Я не мог отладить это, но это происходит любой в вызове к fseeko() или fwrite(). После минут наконец возвращается вызов, и советы продолжает работать без проблем вообще: никакой катастрофический отказ.

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

Но существует интересная деталь о файле подкачки, это - цель операции записи. Это - большой файл созданное открытие (на 26 гигабайтов) файла с fopen() и затем увеличенное использование ftruncate(). Наконец файл unlink()редактор так, чтобы Redis продолжил брать ссылку на него, но мы уверены, что то, когда процесс Redis выйдет из ОС, действительно освободит файл подкачки.

Хорошо это - все, но я здесь для дальнейшей детали. И BTW, можно даже найти фактический код в мерзавце Redis, но это не тривиально для понимания за пять минут, учитывая, это - довольно сложная система.

Большое спасибо за любую справку.

16
задан user 6 July 2014 в 00:41
поделиться

5 ответов

Насколько я понимаю, HFS + очень плохо поддерживает разреженные файлы. Так что, возможно, ваша запись запускает расширение файла, которое инициализирует / материализует большую часть файла.

Например, я знаю, что при использовании mmap нового большого пустого файла и последующей записи в несколько случайных мест на диске с HFS + получается очень большой файл. Это довольно раздражает, поскольку mmap и разреженные файлы - чрезвычайно удобный способ работы с данными, и практически любая другая платформа / файловая система справляется с этим изящно.

Записывается ли файл подкачки линейно? Это означает, что мы либо заменяем существующий блок, либо записываем новый блок в конце и увеличиваем указатель свободного места? Если это так, возможно, выполнение более частых небольших вызовов ftruncate для расширения файла приведет к более коротким паузам.

Кстати, мне любопытно, почему Redis VM не использует mmap, а затем просто перемещает блоки, пытаясь сконцентрировать горячие блоки на горячих страницах.

11
ответ дан 30 November 2019 в 23:09
поделиться

antirez, я не уверен, что мне сильно поможет, поскольку мой опыт работы с Apple ограничен Apple] [, но я попробую.

Прежде всего, вопрос. Я бы подумал, что для виртуальной памяти скорость работы будет более важной мерой, чем дисковое пространство (особенно для БД NoSQL, где все дело в скорости, иначе вы бы использовали SQL, не так ли?). Но, если ваш файл подкачки имеет размер 26 ГБ, возможно, нет: -)

Некоторые вещи, которые стоит попробовать (если возможно).

  1. Попытайтесь фактически изолировать проблему от поиска или записи. Мне трудно поверить, что поиск может длиться так долго, поскольку, в худшем случае, это должно быть изменение указателя буфера. Тем не менее, я не писал OSX, поэтому не могу быть уверен.
  2. Попробуйте изменить размер файла подкачки, чтобы узнать, не в этом ли проблема.
  3. Вы когда-нибудь динамически расширяли файл подкачки (в отличие от предварительного выделения)? Если вы это сделаете, это может быть причиной проблемы.
  4. Вы всегда пишете как можно ниже в файле? Может случиться так, что создание файла 26G может фактически не заполнить его данными, но, если вы создаете его, а затем записываете в последний байт, ОС может потребоваться обнулить байты до этого (отложить инициализацию, если таковая имеется).
  5. Что произойдет, если вы просто заранее выделите весь файл (записываете в каждый байт) и не разорвите его связь? Другими словами, оставляйте файл там между запусками вашей программы (создавая его, если он еще не существует). Затем в коде запуска Redis просто инициализируйте файл (указатели и т. Д.). Это поможет избавиться от проблем, подобных тем, которые описаны в пункте 4 выше.
  6. Спросите также на различных сайтах BSD. Я не уверен, насколько Apple изменилась под прикрытием, но OSX - это просто BSD на самом низком уровне (Pax утки для прикрытия).
  7. Также подумайте о том, чтобы спросить на сайтах Apple (если вы еще этого не сделали).

Что ж, это мой небольшой вклад, надеюсь, он поможет. Удачи тебе с твоим проектом.

1
ответ дан 30 November 2019 в 23:09
поделиться

Вы отключили кеширование файлов для своего файла? т.е. fcntl (fd, F_GLOBAL_NOCACHE, 1)

0
ответ дан 30 November 2019 в 23:09
поделиться

Пробовали ли вы отладку с помощью DTrace и / или Instruments (экспериментальный интерфейс dtrace от Apple)?

Изучение Leopard с помощью DTrace

Отладка Chrome в OS X

0
ответ дан 30 November 2019 в 23:09
поделиться

Как сказал Линус однажды в списке рассылки Git'а:

"Я понимаю, что людям с OS X трудно это принять, но OS X файловые системы, как правило, являются полным и абсолютным дерьмом - даже больше, чем Окна"

-1
ответ дан 30 November 2019 в 23:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: