[О блоге] [наверх] [пред] [2024-12-13 23:46:38+03:00] [081012a8e33bde4945e73916802bc885a8e7d9d4]
Темы: [c][go][keks]

Производительность декодера YAC

Реализации YAC (вскоре KEKS) ещё даже не покрыты тестами (кроме Python
версии), пока ещё всё в процессе и прогрессе. Но я так ни разу и не
мерил производительность чего бы то ни было. Совершенно не знал что
можно было бы ожидать от того что наваял.

Исходные данные взял с коллегой из
https://github.com/getml/reflect-cpp/tree/main/benchmarks, где есть
licenses с кучей вложенных словарей/списков со строчками, и canada, где
куча вложенных списков с float-ами. Так как float-ы никакой реализацией
не поддерживаются, то преобразовали их в начале в список из двух int-ов,
а потом в словарь с двумя короткими ключами.

Сравнивали с MessagePack msgpack-c и github.com/shamaton/msgpack/v2
реализациями. CBOR, судя по тому что говорит Интернет, везде медленнее
(он и куда сложнее!).

В целом, и Си и Go версии работают такого же порядка быстро как и
msgpack. Версия canada с list-ами в Go работает раза в полтора хуже
из-за существенно большей нагрузки на heap и GC, так как мы не можем
заранее создавать slice/map-ы нужного размера, так как YAC/KEKS не
передаёт количество элементов контейнеров, в отличии от MessagePack.
Что, с другой стороны, является плюсом, так как даёт возможность
потокового кодирования. Но кол-во аллокаций у нас почти в два раза
меньше. Версия canada с map-ом или licenses -- почти идентичны, но в два
раза меньше аллокаций. Если в YAC не делать валидацию UTF-8, то он
становится быстрее msgpack. String interning позволяет ещё в разы
сократить аллокации, но двухкратной ценой времени декодирования.

В Си же проверка UTF-8 отнимает примерно треть времени. Если её не
учитывать, то Си реализация примерно раза в два медленнее. И судя по
профилированию кода, всё упирается не в скорость декодирования атомов, а
в то, как оно хранится в памяти, в совершенно иные структуры данных.
Раза в два медленнее это значит YAC занимает 20мс, а MessagePack 10мс.
MessagePack аллоцирует зоны из кучи, тогда как в cyac можно один раз
передать область памяти и не использовать кучу вовсе, что полезно для
встраиваемых систем. Плюс в cyac структуре можно легко вставлять в
середину списка какой-то элемент например.

Изначально я легко мог ожидать и то, что всё будет очень медленно. Ибо о
производительности не задумывался. Но теперь видно, что и Си и Go версии
находятся в такой же весовой категории как и MessagePack, что приятно.

    [оставить комментарий]