Как стать автором
Обновить

Комментарии 7

Tarantool должен работать быстро. У нас есть грубая оценка — мы должны выдавать 1 Mrps на чтение и запись.

Не очень понятно, на каком оборудовании этот Mrps должен быть достигнут и каков размер данных для request?


Если этот Mrps отдается из кеша, то непонятно, при чем тут Memory ALLocators.

Как правило речь про рабочий десктоп и 1 миллион записей в базе (если я правильно понял про «размер данных»). Понятно, что десктоп десктопу рознь, боевые сервера слегка другие, а многие вообще на ноутах работают. Но это, как я пишу, грубая оценка, для ответа на вопросы типа «могу ли я ради новой фичи потратить еще 50 наносекунд на запрос?». Сразу можно прикинуть, что это порядка 5% деградация в самом простом случае, что — много.

А помимо железа и размера спейсов есть еще море нюансов. Индекс — hash или tree (или rtree)? Индексируемое поле — число, строка, скаляр? Сколько полей в индексе? А сколько индексов? Запросы из lua или по сети (или по сети дергаем lua хранимку)? Записи делаем по одной или большими транзакциями? Сравнение строк бинарное или utf8 case insensitive? И это то, что первое пришло в голову.

Если интересны реальные цифры, то на моем почти десятилетнем десктопе все самое простое из вышеперечисленного в lua выдает около 0.5Mrps на запись и 1Mrps на чтение.

С ноутбуком вообще непонятно про 1 Mrps на чтение. Миллион взятий в секунду из локального кэша? Ну как-то так и должно быть, хоть на derby, хоть на bboltdb.


Миллион операций по записи в секунду — это впечатляет, но все равно непонятно, при чем тут память. Надо стремиться к "Zero memory allocations in hot paths", иначе с "миллионом" будут проблемы, как не выделяй.


Кроме того, миллион реальных операций записи в секунду это может быть около гигабайта в секунду. Терабайтный диск заполнится за 20 минут. Круто, что.

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

Конечно, если есть возможность избежать аллокации — нужно её избежать. Но это всё же можно сделать не всегда. И тут приходит на помощь аллокатор в высоким быстродействием.

Спасибо за статью! Было интересно почитать. Оставлю несколько предложений и вопросов:

1) В коде с примером работы Region в 10 строчке должно быть &fiber()->gc, AnotherItem) (пропущена скобка).

А ещё функция region_alloc_object_xc не представлена в списке сразу после заголовка "Region" (там есть только region_alloc).

2) В описании LSRegion при упоминании LSM-дерева, мне кажется, уместно прикрепить ссылку на статью (только, может быть, стоит упомянуть, что она довольно убойная).

3) В разделе про OBuf, наверное, стоит добавить: "Когда Tarantool отвечает НА запрос по сети" .

4) В разделе про Small alloc слово задублировалось: "и такой БЛОК БЛОК будет результатом".

Не очень понятно, почему Small alloc с мемпулами используется именно для кортежей? Разве под них не нужно выделить один кусок памяти размером с сам этот кортеж?

5) В разделе про Matras тоже слово задублировалось: "в любой момент МОЖНО текущее состояние всех данных в одном Matras МОЖНО моментально".

Думаю, опечатка: "ИПРИ перезаписи какого-нибудь элемента...".

В этом ^^^ же разделе говориться про несколько потоков: "свободно использовать, например, в другом ПОТОКЕ без всяких мьютексов". Приведите, пожалуйста, пример потока, о котором идёт речь. Спрашиваю, потому что у Тарантула ведь один транзакционный поток.

Объясните, пожалуйста, когда может быть полезна ситуация "Для писателя элементы для него уже будут лежать в другом месте, а для читателя — в старом.". Разве это не означает, что у читателя будут старые данные?

Спасибо, поправил опечатки! Кроме:

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

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

А что касается вопросов:

  • Small alloc и кортержи - не понял вопроса. Кортеж - это единица хранения данных, что-то типа одного ряда таблицы. Хранится в памяти он одним кусоком. Кортежи переменного размера, поэтому для них нужен аллоктор общего назначения. Подошел бы malloc, но вместо него мы используем свой small_alloc.

  • В Тарантуле действительно один транзакционный поток, но есть еще несколько вспомогательных потоков. В частности recovery checkpoint (он же snapshot на диске) пишется из треда. Еще один пример relay поток реплики. Когда приходит пустая реплика и присоединяется к кластеру, для неё создается персональный поток, а чтобы заполнить реплику текущими данными - в этот поток также передается read view всех данных.

  • Про читателя и старые данные - все верно, это и нужно. Читатель дожен получить консистентный неизменный read view на какой-то момент времени, писатель будет создавать новое состояние базы данных, а читатель - получается будет работать с неизменным старым.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий