
Отвелекусь немного на сами данные. Сейчас отношения примитивно и неоптимально со всех точек зрения. Пока я предполагаю что весь state
(и persistent и transient) будет валятся в таких структурах. Хочется проверить насколько это все реально, соответственно хочу померить уже известную мне dbmonster модель. Захуярю-ка я ее в “базу”.
В datomic (или RDF-alike) модель запихать монстра оказалось даже быстрее чем в объекты конкретных классов: вот весь код создания базы:
const
DatabaseName = A(1)
Elapsed = A(2)
Waiting = A(3)
SQL = A(4)
Queries = A(5)
proc genQuery(db: DB): E =
result = getId()
db.add(result, Elapsed, random(1500))
db.add(result, Waiting, random(2) == 0)
var query: string
case random(10)
of 0: query = "vacuum"
of 1..2: query = "<IDLE> in transaction"
else: query = "SELECT blah FROM something"
db.add(result, SQL, query)
proc genDatabase(db: DB, name: string): E =
result = getId()
db.add(result, DatabaseName, name)
for i in 0..random(10):
db.add(result, Queries, db.genQuery())
proc getData*(): Db =
result = newDB([sizeof E, sizeof A, -1], [Order(0x123)])
for i in 1..ROWS:
discard result.genDatabase("cluster" & $i)
discard result.genDatabase("cluster" & $i & " slave")
Запускаем, и видим ожидаемую жопу: 1.8ms
на генерацию для 200 монстробаз. Это нативно. Напомню что оригинал генерировал данные за 0.36ms
нативно. Интересно, что уменьшая количество данных в 2 раза, время построения уменьшается линейно до 0.9ms, что говорит о том что неэффктивность где-то в сериализации тупла, а не в уебищной структуре данных (можно было ожидать что тормозит вставка с сортировкой, но походу нет).
Пробую V8. Оригинал – 1ms
. “База данных” – полная сракотень 18.9ms
. С другой стороны, на V8 уменьшив объем данных в 10 раз получаю ускорение в 20 раз, до 0.8ms. Что нам это говорит? Видимо то что emscripten и движки JS пока далеки от генерации чего-то похожего на нативный код. Думаю что memcpy
реализован циклом по массиву HEAP… Или чота типа того. Safari как всегда впереди всех - 14.7ms но тоже не торт. Возможно корень зла в emscripten и webassembly отожгет.
Ладно, хер с ним переживать - все это можно оптимизировать в разы. Продолжу с сутью и давайте попробуем выбрать все запросы где Waiting == true
. Для этого добавлю AVE индекс: var monster = newDB([sizeof E, sizeof A, -1], [Order(0x123), Order(0x231)])
Ха-ха-Ха ебать, и вот она - пизда! 10ms на итерацию в нативном коде. Ну конечно, идентификаторы триплов я генерировал последовательно, и они (триплы) добавлялись в конец, а с индексом понеслась пизда по кочкам, все таки структура данных (тупо массив) - откровенное гавно, но это меня не остановит.
var q = newQuery()
q.pred(monster, variable("?e"), constant(Waiting), constant(true))
q.select("?e")
q.prepare
q.execute
ОК, соснул, построились кривые итераторы не из того места… Починил, включая поддержку 32 бит. Осталось поправить багу (iter.up/iter.open должен перематывать итератор в начало), но бага мешает толко для “плохих” планов (так то нехуй ничо перематывать).
А вот с запросами двигло работет побыстрее. Поиск монстробаз где Waiting == true
– 5.5ms
на V8:
q.pred(monster, variable("?q"), constant(Waiting), constant(true))
q.pred(monster, variable("?db"), constant(Queries), variable("?q"))
q.pred(monster, variable("?db"), constant(DatabaseName), variable("?name"))
q.select("?name")
q.prepare
q.execute
На сегодня с программированием завязал, надо подумать что со всем этим делать дальше. Код под тегом day-170104
.