Close

27.10.2015

Disk IO Perfomance, hi load

«in-memory» — это сейчас звучит часто и со всех сторон.
Но что, если с диском НАДО работать в вашем ПО ? Какие либы использовать? Какие движки? Быстрее какого предела не подняться в принципе ? Какие основные проблемы здесь имеет программист?

Я попробую приподнять звесу и поделиться своим опытом.

Производительность IPC

Сначала надо начать с самой ОС и ее ввода-вывода. И даже с оверхеда на системный вызов.
Внутри самого компа (box) используются IPC методы для ввода-вывода, чаще всего они проходят, не затрагивая дисковый ввод-вывод.

IPC — inter process communication; ru «методы межпроцессного обмена»

Тут сразу приведу странные факты о влиянии железа. Два теста: первый проходил в старые времена, второй — гораздо свежее.

Оба они показывают задержки по работе с IPC.  И !

Как была базовая линия задержки (в целом) 64-200 мкс, так и осталась!

Пропускная способность возросла, но задержка, считай, никак не поменялась за эти годы. Уже ядра другие, ОС развивались, железо лучше, а вот так — и это заставляет задуматься(было от 64-200, или 300, стало 40-60 — что очень не существенно).

Что характерно, в тестах 96 года задержка на системный вызов — до 3-х мкс, а это по сравнению с 64 или 512 сильно меньше. Понятно, что эта разница как раз скрыта в работе ядра ОС, а это переключения контекстов в том числе, работа планировщиков… Планировщики — отдельный разговор.

Пропускная же способность сильно возросла! Но слабый рост по задержке уже тогда, а сейчас тем более, создает главную и большую проблему. При рабте с диском умножай задержку на 100, 1000, 10000 и это зависит от загрузки диска, его очереди, размера и скорости кеша, числа головок, и даже хваленый SSD требует большой коэффициент для домножения. Batch mode помогает, но где вы его реально сами-то используете?

Как только нужен random access, сразу эта задержка бьёт по пальцам. В наше время с этим стали бороться словосочетанием «in-memory» или методами memory mapping, как это делает  LMDB, например. В итоге, работа с диском сильно страдает.

 Обсуждение тестов

Обсуждений здесь не будет.

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

Прочих тестов полно и можно почитать. Там все разжевано. Да, не очень ясны причины получаемых цифр, можно спорить о методах тестирования — мне сейчас на это наплевать.

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

Advanced IO

Я рекомендую всем ИТ-специалистам хотябы прочитать этот раздел -Linux Programming.  Ссылка: https://www.safaribooksonline.com/library/view/linux-system-programming/9781449341527/ch04.html

Эти методы надо знать и понимать:

  • Scatter/gather I/O
  • Epoll
  • Memory-mapped I/O
  • File advice
  •  Asynchronous I/O

Но их использование и даже изучение на уровне C API — тяжелая задача. Пользоваться этим в таком виде будете, когда будете писать движок БД, например. Кроме того, возможности эти очень низкого уровня.

Планировщик ввода-вывода на уровне приложения тут, как бы, напрашивается методика работы со структурами блоков данных и т.д.

Чтобы проблема встала перед вашими глазами, четче приведу пример задержки доступа при random access (случйном порядке доступа) к диску.

Хорошей скоростью считается результат, достигаемый движками Sophia и  RocksDB. Чистый результат всего 120-200~ чтений в секунду и  5-8 мс задержка на одну операцию. Это очень близко к аппаратному seek time диска.

Данные результаты замерялись на таком железе:

cpu Intel(R) Xeon(R) CPU E5-2609 0 @ 2.40GHz cpu
ram 96Gb
storage SATA hard disk drive WD4000FYYZ-01UL1B0 4Tb
file system XFS
Тест
number of operations 2 billion
operations set, iterate, get
key order random
key size 16 bytes
value size 32 bytes
data compression off

Чтобы достигать реальных результатов, наверное, не стоит начинать с Advanced IO — уже есть эффективные движки для IO, которые я хочу рассмотреть.

LevelDB и клоны

Мы использовали LevelDB и его «клоны» (RocksDB, HyperLevelDB) в своих проектах.

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

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

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

TC — Tokyo Cabinet

Эта матрешка собирается так:

HDB (K|V HASH)  <<<< BTREE (K/V ordered tree)  <<<<< TABLE with columns and query)

Самым элементарным считается Hash. Работает и правда очень быстро, хорошая штука.

BTree — подвижный, но можно лучше. Можете использовать. Разрешаю 😉 , только следите за скоростью все время.

Table — вообще не пользуйтесь, даже если он соблазняет. Провал в скорости огромен (хотя при разработке не заметен), тормоза есть, считайте, что его нет в TC.

В доп. преимущества скажу, что есть еще TC Dystopia и префиксные деревья с запросами, которые можо использовать для эффективных индексов, тегирования, поиска…

Есть биндинги к языкам, я пользовался lua биндингом. Если длаете продукт с этой штукой, то учтите, что собирать ее на машине придется каждый раз gcc надо, либу собрать, make install  для либы, для биндинга, поставить либы с зависимостями, само оно нигде с полпинка не стоит и apt-get не поможет вам.

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

BDB — Berkeley DB

BDB я использовал из Python биндинга для индексирования большой кучи xml связанными ссылками.

Когда я вместо него попробовал TC,  понял,  что TC быстрее, а BDB — тормоз (в том варианте как было у меня).

Однако, BDB умеет мимикрировать под API SQLITE http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#berkeleydb-backend под который есть ORM, а сам он умеет хорошо скелится (scale) по машинам… Вам это может очень в жизни пригодится 😉

WiredTiger

сайт

Создатели движка гордятся включением его в проект MongoDB.

Его правомерно сравнивать как с key-value движками, так и  с, например, InnoDB или Percona MySQL(MariaDB).

Как так ?  Да потому что там накручено абстракций из коробоки.

Вот, к примеру, о схеме данных http://source.wiredtiger.com/2.6.1/schema.html

Я так и не стал этим пользоваться — сложно и у меня мало времени, если так, то уж лучше разобраться с InnoDB, там и API дружелюбнее.

Но, если у Вас времени хватает, лучше разобраться ней, ведь она стоит  в одном ряду с InnoDB и XtraDB, а это говорит о многом.

Его производительность кроется в методике LSMTrees, хорошо расписанной, кстати, как раз у них (хотя она общеизвестна)  ссылка https://github.com/wiredtiger/wiredtiger/wiki/LSMTrees

В оригиналде LSMTree описан тут http://www.cs.umb.edu/~poneil/lsmtree.pdf

Sophia

Встраиваемая K/V хранилка http://sphia.org/index.html с транзакциями!

Но  Append-Only MVCC.

Надо посмотреть графики, чтобы определить случай, когда она вам нужна.

Коротко: стабильно малая задержка 1) при вставке 2) при итерировании (обход значений)

Концептуально

Хранилиша локальные мы имеем. Движки для использования ресурсов ОС — тоже.

Можно выбрать планировщик IO, тип файловой системы тоже.

Но все равно не получается в 21 веке использовать все это правильно и вот почему:

Представьте как бы вы действовали, если бы вам нужно было сделать «Instagramm»?

В команде yandex для хранения картинок тоже используют не тупо ФС и кучу мелких файликов.

Задача, в которой надо много хранить мелких кусочков данных, которые могут быть востребованы в любом порядке не известно когда, не решается ни «быстрыми file API», ни кешированиями (т.к. не понятно, когда картинка будет нужна — нет предсказания, нет смысла все держать в кеше).

Тут ограничителем встает disk seek. Кусочки данных лежат в разных местах диска, все что можно сделать «вычитать файл картинки целиком за один seek», тогда  скорось не будет превышать  disk seek per second — а это очень мало чтений в секунду. Тут бесполезно знать, сколько памяти у компа, какие у него процы, и даже скорость ввода-вывода по сети мало влияет. Лучше «размылить» запросы к большому числу несильных машин, у которых по несколько дисков.

Представьте: картинка стала популярной! Беда — все ее запрашивают и вычитывают (если мы решили не кешировать) — диск дохнет, просто сгорает.

Надо периодически делать немного реплик каждого файла на живые диски и проверять, не стали ли пропадать реплики каких-то файлов вместе с мертвыми дисками.

Надо кешировать популярные файлы на какое-то время в памяти, чтобы не делать для них seek каждый раз.

Представьте: а если нет реплик этой картинки в сети?  А она популярная, то сеть ограничит скорость отдачи. Решения два:

  • проводить супер сеть — а это очень избыточно, т.к. мала вероятность пупулярности файла, (не реально)
  • реплицировать картинку на 100500 компов — очень дорого, значит надо реплицировать только популярные картинки динамически намного компов,  делать много реплик.

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

Для  построения хранилищ есть компоненты, но даже развернуть подобное — большая работа.

handlersocket

Когда я впервые это увидел, я подумал: «Ну наконец-то догадались». Еще в институте я бловался с InnoDB и удивлялся получаемым скоростям.

Но удивило меня не сама эта поделка, а способ ее работы по сети — напоминает шизу, почему так??? Остается сказать только: «Хрен сним, главное, что оно работает»

Ссылка на хабр http://habrahabr.ru/post/239637/

Ссылка на percona https://www.percona.com/doc/percona-server/5.5/performance/handlersocket.html

Остается только пожелать, чтобы была вменяемая версия embedded, и она есть.

haildb

Встраиваемый InnoDB, правда, слишком сишный(они все уж очень  сишные)

Ссылка http://www.haildb.com/tag/embedded-innodb/

Читать лучше тут http://www.haildb.com/doc/latex/refman.pdf

Расстраивает, что биндингов, считай, нет.  Для питона есть, но не Hail, а просто InnoDB https://github.com/vpelletier/python-innodb

Стоит отметить странность-«нет оберток высокого прикладного уровня для InnoDB с простым API key-value, tree, table» — тема для диплома ?

Было бы неплохо иметь для питона, java, с репликами эксперимент поставить…

tarantool , nodejs, libuv

С точки зрения работы с данными tarantool можно считать хорошей штукой или даже платформой.  http://tarantool.org/

Он использует внутри ассинхронщину sophia db для работы с диском и свою надстройку над ней. Там есть пакеты работы с файлами, все многопоточно, асинхронно и без блокирования. tarantool использует lua, а точнее luajit. Тот самый-самый, быстрый скиптовый.

Есть сборки подобного рода на JS, например, nodejs. К ним написано много пакетов и биндингов. Про это можно почитать отдельно.

Мое мнение: использование таких динамических платформ — это стрельба по ногам. Допустимо использование для  отдельных задач, но писать на такой платформе большую систему на lua или JS я бы не рекомендовал.

http://libuv.org/

Множество асинхронных неблокирующихся hi load систем строятся поверх одной и той же либы libuv (это системы Luvit, Julia, pyuv  и ДРУГИЕ https://github.com/libuv/libuv/wiki/Projects-that-use-libuv)

nodejs тоже работает поверх нее. Упрощенно и по сути Nodejs- это libuv, к которой приделали JS.

Биндинги к ней есть, наверное, для всех основных языков.

Сегодня libuv развивается, как библиотека-платформа для создания нагруженных вводом-выводом компонентов или звеньев программных систем.

«на этом  мы остановимся», но Ваш путь только начинется 😉 

 

One Comment on “Disk IO Perfomance, hi load

Михаил Павлов
14.04.2016 в 23:31

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *