Обновить

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

не хватает сравнения с simdjson-go. Думаю simdjson будет быстрее и нет необходимости с приседаниями писать самому декодер

Почему нет необходимости писать самому декодер?
Вот что примерно получается у SIMD: https://gist.github.com/ernado/3d2e256128dd173537825e6e845b87fc

SIMD в 10 раз медленней на таком json:

goos: linux
goarch: amd64
pkg: bench
cpu: AMD Ryzen 9 5950X 16-Core Processor            
BenchmarkOTEL/Decode/jx-32               2385859               517.8 ns/op       965.61 MB/s           0 B/op          0 allocs/op
BenchmarkOTEL/Decode/simdjson-32                 3970692               318.7 ns/op        87.86 MB/s          96 B/op          2 allocs/op
PASS
ok      bench   3.327s

Да и то нет возможности написать аналогичный код, который сырой json в Body и значения атрибутов (values в Resource и Attributes) сохраняет.

да ошибся, там действительно нету unmarshal в структуру. Если будет время попробуйте пожалуйста https://github.com/bytedance/sonic

Если вот такую структуру использовать:

type OTEL struct {
	Timestamp      int64 `json:"Timestamp,string"`
	Attributes     map[string]json.RawMessage
	Resource       map[string]json.RawMessage
	TraceID        TraceID
	SpanID         SpanID
	SeverityNumber byte
	Body           json.RawMessage
}

То получается 386.27 MB/s и 11 allocs/op. Мб можно как-то эффективнее, но я пока не придумал.
Целиком структуры для соника тут: https://gist.github.com/ernado/b8d576d3b20b73b452483e09297b9997

Скорее всего это разница из-за map[string]json.RawMessage vs кастомный Map из статьи.

Но если заменить на

type OTEL struct {
	Timestamp      int64 `json:"Timestamp,string"`
	Attributes     json.RawMessage
	Resource       json.RawMessage
	TraceID        TraceID
	SpanID         SpanID
	SeverityNumber byte
	Body           json.RawMessage
}

То получается 561.37 MB/s.

Хочу поделиться, Решали задачу подобного плана, и одно время стоял joniter. Это самый быстрый пакет который нашли, но в итоге ушли в пользу самописного ручного «прохода»

В задаче было 4 типа сообщений с заранее известной формой, и они могли еще объединятся в «массивы». Скорость сообщений на входе в пиках 200-250к rps (примерно около 800мбит утилизировали в пиках)

Схема примерно такая получилась

Посмотреть первый байт, если там [, значит прилетел массив и он улетает на функцию которая посимвольно пролетает по всей строке и делит }, и возвращает обратно в поток для дальнейшего разбора

Если нет, значит измеряем количество байт и кидаем в один из 4 потоков на обработку (каждый тип сообщения имел разный размер)

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

Делали из размышлений: «а почему бы и нет» из разряда мозги прогреть, поэтому ожиданий никаких не было. В итоге joniter обогнали в 4 раза, а отрыв при большом потоке оказался еще больше

Мораль этой истории такова: joniter крутой пакет, но можно быстрее если сообщения стандартизированы

PS: метод преподготовки (деления массива на отдельные чанки и разделения типов сообщений) было изначально реализовано для joniter. Т.е мы точно выжали все что могли..

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

А в чем суть вашей задачи? Локально на хосте лежит много файлов и их надо распарсить? Чтобы что? Аггрегировать, загрузить в базу?

Как вариант, задача — парсить много приходящих логов в секунду из кафки перед загрузкой в ClickHouse.

В этом случае, можно не бороться за высочайшую производительность. Всё равно ведь, в Clickhouse упретесь или в сеть

Возможно упремся, но зато меньше ресурсов потратим на json :)

Там же еще и экономия энергии рядом итд. "Всё что может быть сделано лучше..." (перефразировка Форда)

Мышление как у админа локалхоста с гигабитной сетью.

Если можно сделать быстро и не тратить ресурсы, то почему бы и не сделать?

А освободившиеся ядра потратить на другую полезную работу или сэкономить денег.

А зачем там middleware? Почему нельзя складывать тупо тот джейсон, что приходит из Кафки, и прикрутить materialized views для того представления, которое нужно бизнесу, или кому там?

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

Публикации