Комментарии 68
Кроме того, без этой команды вы ставите сервера в неравные условия — мне кажется, у вас network stack ограничивает производительность в половине примеров.
Потолок — 10к сообщений в секунду, каждое сообщение по 10 байт. Обидно, нет?
Представьте, что мне нужно сделать batch update для 10 млн значений в хеш-таблицу, и я хочу, чтобы это не требовало часа времени.
Как мне это проще всего сделать?
Что вы вкладываете здесь в слово «максимально»? Посчитайте сами: пусть сеть — 1 ГБит. Сколько запросов размером 10 байт нужно отправить в секунду, чтобы «максимально утилизировать сеть»?
Тарантул — отличный инструмент для большого числа параллельных потоков. Но для групповых операций в нём простого метода, как я понимаю, нет — «пишите lua-скрипт под ваши нужды».
2. Вы будете смеяться, но для Тарантула не нужен такой метод. Он полностью асинхронен. Вы просто в сокет кидаете все операции, сколько хотите, и потом получаете в сокет ответ. Кинете сразу 100 операций — улетит все 100 в одном пакете и потом прилетит ответ в одном пакете. Вы не должны говорить Тарантулу — «вот тут группа начинается», «а вот тут группа заканчивается». Он сам все разрулит и сделает максимально эффективно :)
Сейчас попробую.
>2. Вы будете смеяться, но для Тарантула не нужен такой метод. Он полностью асинхронен. Вы просто в сокет кидаете все операции, сколько хотите, и потом получаете в сокет ответ. Кинете сразу 100 операций — улетит все 100 в одном пакете и потом прилетит ответ в одном пакете. Вы не должны говорить Тарантулу — «вот тут группа начинается», «а вот тут группа заканчивается».
>Он сам все разрулит и сделает максимально эффективно :)
Но вообще, хотелось бы, чтобы это вы не мне в треде по секрету говорили, а это было бы видно сразу как существенное преимущество библиотеки.
А во-вторых, это, увы, никак не снимает претензию к тестированию других библиотек, которые так не умеют — вместо ваших красивых графиков вы могли померить всего два параметра:
а) скорость работы для batch-режима
б) задержка сети до вашего сервера (3к пингов в секунду).
Всё остальное на практике обычно укладывается в формулу
QPS = min(latency * sync_clients, max_throughput).
Как я понимаю, неожиданностей не произошло.
Наша цель была провести максимально объективное тестирование. Возможно, что мы что-то не учли. Мы не претендуем на абсолютную истину. Если у вас есть идеи как ускорить любого из конкурентов Тарантула (по другому настроить, переписать клиентскую либу, написать поверх либы другую правильную либу и тд), то милости просим, покажите. Код теста, повторюсь, открыт. Можете на его основе делать.
Про ваши рекомендации как нам надо было менять наши красивые графики, я не совсем понял. Можете разжевать?
Вы загружаете на сервер данные батчами или по одному значению за один раз?
Как я вижу, ваш код может загрузить батч. Но делает ли он это?
>Вы не должны говорить Тарантулу — «вот тут группа начинается», «а вот тут группа заканчивается».
>Он сам все разрулит и сделает максимально эффективно :)
А tnt_flush это для гарантии отправки последнего сетевого пакета?
>Про ваши рекомендации как нам надо было менять наши красивые графики, я не совсем понял. Можете разжевать?
Ну, я по поводу того, что графики рисуют две линии, плавно переходящие одна в другую. Одна y=kx до насыщения, вторая почти горизонтальная (уровень насыщения).
Наиболее интересны для меня как раз параметры этих линий, и объяснение именно таких значений этих параметров.
Например, я не понимаю, почему у вас на одном потоке всего около 3к запросов в секунду на всех тестируемых базах данных.
Получается, вы не используете возможность групповой загрузки и чтения данных?
rvncerr, почему вы групповую загрузку не хотите протестировать?
Статья называется «Сравнение Tarantool с конкурентами в Microsoft Azure», такое название и первый абзац подразумевают широту изложения.
Тестировать можно по-разному: синхронно, асинхронно, синхронно-асинхронно, с батчингом и без него, с хранилками.
Но все и сразу — нет. Это будет месиво информации, которое бросят читать на полпути.
Я уже делал тест с батчингом (правда, асинхронный) и демонстрировал его результаты на хайлоаде.
Тут я захотел сделать тест без батчинга — по этой причине. Кратко — я взял типовой, по моему мнению, профиль нагрузки и сделал тест под нему.
Как-то так: https://gyazo.com/624e16eda973e742e4cb02059d629d6f
Попробую объяснить, почему, на мой взгляд теряется объективность:
Есть ли юз-кейсы, где redis лучше, чем tarantool?
Если читать ваш пост, то нет, tarantool всегда лучше всех. А на деле — есть. Я показал один такой юз-кейс.
Но загрузка и выгрузка данных тоже весьма распространены.
Вы согласны, что рассмотрение явлений с разных сторон увеличивает объективность исследования?
Поэтому, если вы уменьшите требования к синхронности в ваших тестах, то redis обгонит tarantool в некоторой части этих тестов.
Я был бы доволен, если бы вы смогли упомянуть этот момент в статье, а ещё лучше, если бы вы смогли добавить график теста с групповыми операциями.
См. подробности ниже в https://habrahabr.ru/company/mailru/blog/281841/#comment_8859953
(это я для новых читателей, вы-то в курсе).
20k RPS из клиента в tarantool, 120k из redis.
Вы как будто не читаете другие комменты.
Все бенчмарки и их результаты: https://gist.github.com/buriy/329bdac8f42f2c0c0e678bcbfe26ee0e
Мой конфиг: https://gist.github.com/buriy/c9383845754ff552c83d81ba9f60fbed
Запуск профайлера для bench.py: https://dl.dropboxusercontent.com/u/1703221/batch.prof (я использую runsnakerun чтобы их смотреть)
Запуск профайлера для mbench.py 20: https://dl.dropboxusercontent.com/u/1703221/mbatch.prof
Добавил контакты в профиль хабра, пишите в скайп или телеграм: https://habrahabr.ru/users/buriy/
Он совершенно не всегда может быть органически встроен в структуру проекта.
Придется писать дополнительный код, который эти пачки формирует.
То есть в теории, конечно, попробовать можно протестировать, но а практике не факт что этот подход будет легко применим, ИМХО.
То есть нам важно не «сколько из СУБД можно выжать в принципе» (сферический конь в вакууме), а сколько можно выжать на типовой бизнесовой задаче.
+ Делая пачку, мы увеличиваем latency для первых запросов в ней. (!)
Почему вы ограничиваетесь только проектами, имеющие однотипную нагрузку?
Что мне делать, если мне в один день нужно в БД всё быстро положить, потом день — считать, на третий день — выгрузить?
«Вы не сможете быстро положить ваши гигабайты данных в нашу БД, не сможете быстро их выгрузить, но зато мы быстро с ними работаем, пока данные находятся внутри» — бывает такая проблема у некоторых облачных вычислительных центров.
У меня пока вопрос только по быстрой загрузке данных — счёт и выгрузка вроде бы в порядке.
(Собственно, счёт и не может быть медленным, если скорость обмена память-процессор порядка 30 ГБ/с на десктопных Haswell — сеть гораздо медленнее)
Улучшите загрузку данных в клиентских библиотеках — я с удовольствием слезу с redis, к которому у меня тоже есть определённые претензии, и перелезу на tarantool для подходящей части моих задач.
Потому что я всегда пишу тесты под задачу. Сегодня выбрал такую.
Батчинг — интересная тема, но для совсем другого теста.
В целом этот тест больше для «масс-маркета», чем тест с батчингом.
Основная же идея — сравнивать равное.
Но, на самом деле, я понимаю вашу проблему. Вы хотите бесшовную миграцию. И идеально было бы, если бы Тарантул полностью поддерживал интерфейс редиса и мог бы реплицироваться из него. Мы работаем над этим в том числе.
Нет, спасибо, я не хочу бесшовную миграцию — слишком разные базы данных, вряд ли кто-то будет держать сразу обе.
Я хочу просто лёгкую и удобную загрузку данных в базу данных. Желательно, без гринлетов.
Вполне подойдёт такое:
with conn.pipeline() as p:
for i in xrange(100000):
p.insert((i, value))
Но я согласен и на менее специализированное p.insert_many((i, value)) — это всё же более частая задача для меня, имеющая отдельное значение.
Я не хочу вместо этого переходить на python 3 или писать лапшу, как в https://habrahabr.ru/company/mailru/blog/281841/#comment_8859211
Но готов рассмотреть данный вариант в случае отсутствия более приличных.
Как минимум, есть ситуация начальной загрузки базы данных в случае падения сервера.
На самом деле, вероятно, всё дело именно в особенностях питоновской библиотеки. Если бы она не ждала ответа сервера, всё было бы намного быстрее.
Могу и сам передать, конечно. https://telegram.me/yuri_baburov (это юзернейм)
Оффициально — в питоновском драйвере такой возможности нет, но неоффициально, для примера, можно привести кусок кода из тестов:
from tarantool import Connection
from tarantool.request import RequestInsert
from tarantool.response import Response
c = Connection('localhost', 3301)
c.connect()
request1 = RequestInsert(c, 512, [1, "baobab"])
request2 = RequestInsert(c, 512, [2, "obbaba"])
s = c._socket
try:
s.send(bytes(request1) + bytes(request2))
except OSError as e:
print ' => ', 'Failed to send request'
response1 = Response(c, c._read_response())
response2 = Response(c, c._read_response())
print response1.__str__()
print response2.__str__()
Оффициально батчинг (пайплайнинг) поддерживается в драйвере для C.
Как минимум, есть ситуация начальной загрузки базы данных в случае падения сервера.
Вот об этом, пожалуйста, поподробнее.
>>Как минимум, есть ситуация начальной загрузки базы данных в случае падения сервера.
>Вот об этом, пожалуйста, поподробнее.
Это круто, если сервер никогда не падает. В redis с этим бывают проблемы, поэтому я всегда об этом думаю заранее.
Также ещё два момента перечислены в комментарии ниже ( https://habrahabr.ru/company/mailru/blog/281841/#comment_8859149 ), но первый, про delete и select — это, возможно, особенности питоновского драйвера, а второй момент — что сервер отжирает память и никому не отдаёт — это даже в чём-то плюс для больших серверов и постоянных нагрузок, но, увы, минус для переменных нагрузок. Хотя, может, это как-то и регулируется в опциях.
буду ждать появления батчинга/пайплайнинга в драйвере для Python
Было-бы прекрасно если бы вы отписались/апнули тикет https://github.com/tarantool/tarantool-python/issues/55
Это круто, если сервер никогда не падает. В redis с этим бывают проблемы, поэтому я всегда об этом думаю заранее.
Для этого нужно использовать репликацию и snapshot/xlog (аналоги aof/rdb для редиса). Или я не совсем понял вашу проблему.
но первый, про delete и select — это, возможно, особенности питоновского драйвера
Select — не особенности питоновского драйвера, а ограничение на уровне Тарантула. 2 Гб это максимум пакета, который отправляется по сети. Но есть у меня небольшое впечатление, что это можно/проще обрабатывать прямо на борту Тарантула (но всё, конечно, зависит от задачки).
Delete — оборачивается, проще всего, в хранимку на Lua.
что сервер отжирает память и никому не отдаёт
Это, конечно, так, но касается только памяти под данные.
Тест показывает, что вы не правы, или я не умею правильно запускать ваши «асинхронные запросы»:
https://gist.github.com/buriy/329bdac8f42f2c0c0e678bcbfe26ee0e
$ python batch.py
7 bytes: 2.5 sec, 20263.7 RPS, 0.1 MB/s
1009 bytes: 2.4 sec, 20474.2 RPS, 20.7 MB/s
10009 bytes: 2.9 sec, 17380.0 RPS, 174.0 MB/s
20009 bytes: 3.4 sec, 14531.8 RPS, 290.8 MB/s
50009 bytes: 4.9 sec, 10230.7 RPS, 511.6 MB/s
100011 bytes: 7.1 sec, 7059.3 RPS, 706.0 MB/s
200011 bytes: 12.2 sec, 4110.2 RPS, 822.1 MB/s
300011 bytes: 31.4 sec, 1590.9 RPS, 477.3 MB/s
Аналогично с gtarantool.
У batch.py всегда загрузка около 80-90% CPU, как вы догадываетесь, всё дело в socket.send и socket.recv:
https://gyazo.com/5d2206dea2a93be28e06073f2f9a2ed9
P.S. И ещё два замечания:
1) нет простого способа получить только часть полей: delete всегда возвращает удалённое значение, а select вообще ломается при попытке получить больше 2 гб данных — это актуально для манипуляции данными большого размера.
2) сервер не возвращает память обратно ОС.
Можно посмотреть кейсы для gevent: https://habrahabr.ru/company/mailru/blog/254727/
Всё равно не могу добиться больше 50к RPS от tarantool.
https://gist.github.com/buriy/329bdac8f42f2c0c0e678bcbfe26ee0e
Что я теперь-то делаю не так? :)
Подберите оптимальное кол-во гринлетов, а если питон утилизировал 1 ядро cpu на 100%, то делайте fork и грузите тарантул больше.
Еще вы сравниваете insert в tarantool и insert в redis, под капотом это немного различные вещи.
Запись на диск или в память. Ваш тест не ждет когда redis синканет все данные на диск.
Сравните разницу на select-ах в gtarantool и redis.
Ещё и fork делать? Нет уж, я лучше подожду батчинга/пайплайнинга в драйвере для Python, ветка здесь: https://habrahabr.ru/company/mailru/blog/281841/#comment_8859627
>Еще вы сравниваете insert в tarantool и insert в redis, под капотом это немного различные вещи.
>Запись на диск или в память. Ваш тест не ждет когда redis синканет все данные на диск.
Нет, проблема явно не в этом:
$ python mbatch.py 100
7 bytes: 0.9 sec, 57176.5 RPS, 0.4 MB/s
Вряд ли тут дело в том, что 0.4 MB не смогли записаться на SSD диск за одну секунду.
Ещё и fork делать?
А как вы собираетесь весь процесор на python занять без fork?
redis вас тут тоже не спасет.
> Нет, проблема явно не в этом:
отключите запись на диск в tarantool, и запустите свой бенчмарк для сравнения.
Внутри gtarantool запросы группируются в пачки, несколько запросов в отдельном гринлете отправляются через один вызов soket.send. В отдельном гринлете из сокета вычитываются несколько ответов за один soket.recv.
Отключён. Вообще, как я понимаю, sophia основана на leveldb, а он 150к writes/second без проблем выдерживает.
>А как вы собираетесь весь процесор на python занять без fork?
>redis вас тут тоже не спасет.
Это да, но redis в свой потолок одного ядра без гринлетов утыкается на 120k RPS — около 1.1 MB/s, а не на 20к RPS (или на 50к RPS с извращениями и гринлетами).
Пусть у вас 24 ядра, все грузят данные. За какое время вы забьёте 24 GB мелкими данными при таком сценарии? Пусть оверхед от многопоточности будет 50%.
Ответ: полчаса у Redis, и 3 часа у tarantool (1.2 часа с гринлетами).
Вообще, не так уж и долго, конечно, кроме того, настолько мелкие данные попадаются не часто — 100-байтовые значения более вероятны, чем 10-байтовые, а на них скорость будет в 10 раз выше.
В общем, случай редкий.
Тем не менее, я знаю, что случай не единственный, batching нужен ещё много где, и вижу, что с батчингом скорость библиотеки можно улучшить раз в 10. Буду ждать, а может и сам как-нибудь патч напишу, когда надо будет. Там, в общем-то, ничего сложного, дольше обсуждаем и велосипеды изобретаем.
Во первых — Sophia не основана на LevelDB. Если интересно, то вы можете почитать здесь и здесь
Во вторых — тут имеют ввиду отключить запись WAL и не использовать engine='sophia', для спейса, который вы бенчмаркаете:
box.cfg{
wal_mode='none'
}
box.schema.create_space('test', { engine = 'memtx' })
PS можете показать ваш конфиг тарантула?
Ну, я просто чьи-то слова повторил из комментов к прошлым обсуждениям, может, что-то переврал — но ощущение осталось, что там-то уж точно тормозить не должно.
>PS можете показать ваш конфиг тарантула
Дефолтный из поставки debian для 1.6, example.lua, минимальные исправления.
https://gist.github.com/buriy/c9383845754ff552c83d81ba9f60fbed
Ну и что, ведь есть файловый кеш.
cProfile указывает на socket.recv() как основную причину торможения. Батчинг как раз это улучшил бы.
Посмотрите сами: https://dl.dropboxusercontent.com/u/1703221/batch.prof и https://dl.dropboxusercontent.com/u/1703221/mbatch.prof (гринлеты cProfile учитывает как-то плохо, мне кажется, нужно игнорировать верхние 4 строчки, а дальше вроде бы более-менее правдоподобно)
Сам tarantool спокойно вытягивает 400k RPS при параллельной загрузке без WAL, и 250к RPS с WAL.
У redis 120к — это тоже потолок скорости одного соединения из питона.
Но если вы утверждаете, что проблема с диском, тогда уж сравнивайте с LevelDB или LMDB, а не MySQL:
http://symas.com/mdb/ondisk/ и http://symas.com/mdb/inmem/scaling.html
Кстати, сразу вопросы:
1. Когда Тарантул упирается в 20К, то как выглядит top на сервере с тарантулом?
2. Клиентский код запускается на том же сервере, что и Тарантул или на другом?
75-85% от одного ядра у питоновского процесса, 30% от другого ядра у тарантула (что тоже немного странно, конечно). У mbatch 95% CPU core на маленьких размерах данных.
>2. Клиентский код запускается на том же сервере, что и Тарантул или на другом?
На том же сервере, но не на HT-ядрах (вручную выставлено с помощью taskset).
( В роли сервера — обычный i4790K с 24 Гб памяти и ubuntu, работает без троттлинга на скорости 4 ГГц — это чтобы исключить медленность сервера. кстати, интересно было бы потестировать на серверах с большим числом ядер — там обычно всего около 2 ГГц — как бы там ещё в два раза потолок на CPU не уменьшался. )
https://habrahabr.ru/company/mailru/blog/272669/
https://habrahabr.ru/company/mailru/blog/252065/
https://habrahabr.ru/post/254533/
Взаимодействие с сетью часто является узким местом, это правда. Но какие-то СУБД работают с сетью эффективней других. Тест и это тоже показывает.
Хочу «разогнать» VoltDB и перечертить графики, но пока это лучшее, что удалось на таком тесте.
– а почему? А что будет, если протестировать?
Наверно потому что продукт отечественный и пользуются им не только в нашей стране.
Про такое всегда интересно читать статьи от их создателей.
Как насчёт того чтобы к Lua добавить ещё php7, чтобы не переучиваться?
Сравнение Tarantool с конкурентами в Microsoft Azure