gRPC -- отличный протокол передачи данных. Но он подходит далеко не для всех сценариев работы. Тут статья не про достоинства JSON а про то, как сделать его реально быстрым, простым и удобным
Всё абсолютно верно, вы очень точно сформулировали суть! Идея как раз в том, чтобы сместить фокус с „давайте разберем всё и как можно быстрее“ на „давайте сделаем ровно столько работы, сколько нужно для конкретного шага в потоке“. Спасибо за отличные выводы! Честно, я точнее не сформулировал бы. Конечно, есть технические нюансы, но тем не менее.
easyjson -- это решение совсем для других задач. Оно не умеет основные вещи, которые я использую. это оно не умеет в стрим, оно не умеет в rawjson (реальный), и скорость значительно меньше + реально неудобно использовать. Само решение более зрелое и как замена универсальному стандартному решению одно из лучших. В свое время на крупных проектах с удовольствием сам использовал. Но не этот случай.
вопрос очень хороший. Я по сути не нашел среди баз подходящую. Одни из проверенных, как-то подходящих -- SQLLite, но тут нюанс, sql-overhead. По скорости она не может соревноваться. Как и по простоте. Я сделал решение для проекта, где нет ограничений по структуре данных, со схемой -- нативно работаем с индексами, документы отдаем как есть (as-is). т.е. напрямую запрос -> индексы -> json -> ответ. Даже система может не знать что внутри документа. Все это решается при подготовке данных в базу. т.е. полагаемся не на логику приложения, а на логику информации. При любом изменении меняем просто подготовку информации и если нужно индексы. все.
Насчёт «удобнее и быстрее» с protobuf -- это действительно стоит мерить на конкретных бенчмарках, спорить здесь не буду. В рамках конкретно моего проекта тянуть protobuf с генерацией схем, кодогенерацией и т. д. было бы избыточным усложнением.
Почему не Redis или Riak? Как минимум потому, что это уже совсем другой класс решения. В моём случае задача -- embedded-хранилище, где данные и индексы работают непосредственно в памяти процесса или через mmap. Поэтому здесь я в первую очередь пытаюсь минимизировать накладные расходы самого storage layer, а не сетевого взаимодействия с отдельным сервисом.
Это не значит, что Redis/Riak или protobuf плохие решения. Просто у них другие trade-off и другая область применения.
Я давно заглядываюсь на С++, даже имел опыт работы на нем, в том числе как база для больших проектов. Поэтому приятно видеть единомышленников. Но поскольку я больше работаю с Go, сделал такой эксперимент. И действительно, как и вы, обнаружил, что гибкость такого рода решений находится на таком уровне... Правда очень сложно налаживать систему и много времени уходит на доведение.
В репозитории очень много информации, и я с удовольствием вам ее предоставлю по бенчмаркам,
напишите, какие библиотеки вам бы хотелось увидеть, я подготовлю и напишу ответ. По поводу других, надо пробовать. И я признателен всем, кто дает мне фидбек.
UPD. До этого я пробовал и json2 и Jsoniter. json2 практически на ровне с стандартным. Jsoniter намного лучше, зависит от сценариев, но от нас отстает. Единственные кто может потягаться – simd типа sonic. Но у них есть свои большие недостатки и в ключевых сценариях благодаря многопоточности (и не только) у них мало шансов
*Тест последовательной десериализации сложной структуры с глубокой вложенностью, ~3 млн записей. Данные содержат экранированные строки, null-значения и неизвестные поля.
| Библиотека | Время (ns/op) | Пропускная способность | Память (B/op) | Аллокации (allocs/op) |
можете проверить. попытался сделать с SIMD на ваш процессор. На виртуалке скорость нет смысла тестировать. simdjson-go вообще arm не поддерживает, поэтому цифры там невалидные будут.
Совершенно верно. Но мы имеем то что имеем. Форматы не всегда мы выбираем. Это хорошо когда продукт не зависит от внешнего бизнеса. А внешнему бизнесу важнее другие вещи.
gRPC -- отличный протокол передачи данных. Но он подходит далеко не для всех сценариев работы. Тут статья не про достоинства JSON а про то, как сделать его реально быстрым, простым и удобным
не совсем понятен вопрос. речь про сетевые протоколы или про передачу данных?
Всё абсолютно верно, вы очень точно сформулировали суть! Идея как раз в том, чтобы сместить фокус с „давайте разберем всё и как можно быстрее“ на „давайте сделаем ровно столько работы, сколько нужно для конкретного шага в потоке“. Спасибо за отличные выводы!
Честно, я точнее не сформулировал бы. Конечно, есть технические нюансы, но тем не менее.
easyjson -- это решение совсем для других задач. Оно не умеет основные вещи, которые я использую. это оно не умеет в стрим, оно не умеет в rawjson (реальный), и скорость значительно меньше + реально неудобно использовать. Само решение более зрелое и как замена универсальному стандартному решению одно из лучших. В свое время на крупных проектах с удовольствием сам использовал. Но не этот случай.
вопрос очень хороший. Я по сути не нашел среди баз подходящую. Одни из проверенных, как-то подходящих -- SQLLite, но тут нюанс, sql-overhead. По скорости она не может соревноваться. Как и по простоте. Я сделал решение для проекта, где нет ограничений по структуре данных, со схемой -- нативно работаем с индексами, документы отдаем как есть (as-is). т.е. напрямую запрос -> индексы -> json -> ответ. Даже система может не знать что внутри документа. Все это решается при подготовке данных в базу. т.е. полагаемся не на логику приложения, а на логику информации. При любом изменении меняем просто подготовку информации и если нужно индексы. все.
Вот такое было требование.
Насчёт «удобнее и быстрее» с protobuf -- это действительно стоит мерить на конкретных бенчмарках, спорить здесь не буду. В рамках конкретно моего проекта тянуть protobuf с генерацией схем, кодогенерацией и т. д. было бы избыточным усложнением.
Почему не Redis или Riak? Как минимум потому, что это уже совсем другой класс решения. В моём случае задача -- embedded-хранилище, где данные и индексы работают непосредственно в памяти процесса или через mmap. Поэтому здесь я в первую очередь пытаюсь минимизировать накладные расходы самого storage layer, а не сетевого взаимодействия с отдельным сервисом.
Это не значит, что Redis/Riak или protobuf плохие решения. Просто у них другие trade-off и другая область применения.
Я давно заглядываюсь на С++, даже имел опыт работы на нем, в том числе как база для больших проектов. Поэтому приятно видеть единомышленников. Но поскольку я больше работаю с Go, сделал такой эксперимент. И действительно, как и вы, обнаружил, что гибкость такого рода решений находится на таком уровне... Правда очень сложно налаживать систему и много времени уходит на доведение.
Жалко, что не все источники данных в Go
по поводу
Интересует avx1 (aka avx-128) и neon в termuxна гитхабе можете создать таску. я включу в дорожную картукак вариант
go test -bench ./... -benchmemнет, поля могут меняться местами, лишние поля, непечатные символы
тут есть хитрость. Я кормлю их грязным json. а он видимо хорошо работает с чистым. Но это даже не смешно, если честно.
goos: windows goarch: amd64 pkg: github.com/GenshIv/silentjson cpu: AMD Ryzen 9 7950X3D 16-Core Processor
SilentJSON_Solo-32 | 298 | 3998580 ns/op | 3972.91 MB/s | 60544 B/op | 3 allocs/op
SilentJSON-32 | 1885 | 605436 ns/op | 26238.97 MB/s | 20791 B/op | 27 allocs/op
EasyJSON-32 | 21 | 55023176 ns/op | 288.71 MB/s | 66938179 B/op | 700019 allocs/op
go-faster/jx-32 | 63 | 19326083 ns/op | 822.00 MB/s | 15892560 B/op | 2 allocs/op
Standard_V1-32 | 9 | 121855689 ns/op | 130.37 MB/s | 10552349 B/op | 522219 allocs/op
PASS ok github.com/GenshIv/silentjson 8.954s
отдельно json v2 приведу из прошлого теста, бо там нужно включать экспериментальную поддержку
StdJSON_v1-32 3 80785100 ns/op 196.65 MB/s 2163085 B/op 220401 allocs/op
StdJSON_v2-32 3 82894933 ns/op 191.64 MB/s 19606984 B/op 820401 allocs/op
В репозитории очень много информации, и я с удовольствием вам ее предоставлю по бенчмаркам,
напишите, какие библиотеки вам бы хотелось увидеть, я подготовлю и напишу ответ. По поводу других, надо пробовать. И я признателен всем, кто дает мне фидбек.
UPD. До этого я пробовал и json2 и Jsoniter. json2 практически на ровне с стандартным. Jsoniter намного лучше, зависит от сценариев, но от нас отстает. Единственные кто может потягаться – simd типа sonic. Но у них есть свои большие недостатки и в ключевых сценариях благодаря многопоточности (и не только) у них мало шансов
1. BenchmarkNestedComparison
*Тест последовательной десериализации сложной структуры с глубокой вложенностью, ~3 млн записей. Данные содержат экранированные строки, null-значения и неизвестные поля.
| Библиотека | Время (ns/op) | Пропускная способность | Память (B/op) | Аллокации (allocs/op) |
| SilentJSON |
790,308,800| 640.23 MB/s |65,368,888| 6 || Sonic |
1,203,687,900| 420.36 MB/s |886,626,392| 10,612,816 || Jsoniter |
1,490,925,000| 339.37 MB/s |2,045,419,120| 28,434,294 || Simdjson |
1,720,019,800| 294.17 MB/s |5,742,331,784| 21 || Buger/jsonparser |
3,430,657,000| 147.49 MB/s |511,510,464| 26,433,913 || Standard |
4,815,193,900| 105.08 MB/s |162,149,888| 13,343,235 |2. BenchmarkLargeScaleComparison
*Десериализация большого массива, состоящего из 100 000 объектов
| Библиотека | Время (ns/op) | Пропускная способность | Память (B/op) | Аллокации (allocs/op) |
| SilentJSON |
6,113,900| 2598.34 MB/s |19,189,576| 24,472 || SonicParallel |
11,889,000| 1336.19 MB/s |55,370,048| 569,222 || Sonic |
34,034,900| 466.76 MB/s |16,217,376| 10,004 || Protobuf (для сравнения) |
35,280,500| 192.91 MB/s |39,120,520| 1,100,019 || Simdjson_AST |
56,378,700| 281.77 MB/s |180,495,912| 17 || Buger/jsonparser |
107,575,500| 147.67 MB/s |20,807,936| 1,099,990 || Standard |
164,591,500| 96.52 MB/s |3,904,224| 509,997 |как то так
я внес правки в статье в соответствии с данными
Справедливо, я не корректно поставил информацию. Вернее было бы считать не мегобайты, а сколько объектов у нас распарсилось.
BenchmarkLargeScaleComparison/SilentJSON-32 241 5076327 ns/op 3129.43 MB/s 82334 B/op 132 allocs/opBenchmarkLargeScaleComparison/Protobuf-32 36 32726719 ns/op 207.96 MB/s 39120496 B/op 1100019 allocs/opвидим 241 против 36 проходов абсолютно одинаковых наборов. можете сами протестировать на своих данных
можете проверить. попытался сделать с SIMD на ваш процессор. На виртуалке скорость нет смысла тестировать. simdjson-go вообще arm не поддерживает, поэтому цифры там невалидные будут.
UPS немного отладки еще нужно. скоро выложу
Совершенно верно. Но мы имеем то что имеем. Форматы не всегда мы выбираем. Это хорошо когда продукт не зависит от внешнего бизнеса. А внешнему бизнесу важнее другие вещи.