Successfully reported this slideshow.
Your SlideShare is downloading. ×

Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad

Check these out next

1 of 67 Ad

Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)

Download to read offline

В эпоху распределённых архитектур и микросервисов как никогда актуальными становятся вопросы — как эффективно сериализовать и передать данные. Большинство решает данный вопрос просто — используют стандартный, универсальный и всем понятный формат JSON. Другие же, ориентируясь на производительность, ищут в интернете бенчмарки и выбирают protobuf или msgpack.

Мы протестировали разные реализации статически (thrift, protocol buffers) и динамически (json, msgpack) типизированных протоколов для python; сравнили их производительность в разных сценариях, возможности, внутреннее устройство, удобство разработки.

Я расскажу о результатах нашего исследования, особенностях "приготовления" библиотек и выявленных подводных камнях.

В эпоху распределённых архитектур и микросервисов как никогда актуальными становятся вопросы — как эффективно сериализовать и передать данные. Большинство решает данный вопрос просто — используют стандартный, универсальный и всем понятный формат JSON. Другие же, ориентируясь на производительность, ищут в интернете бенчмарки и выбирают protobuf или msgpack.

Мы протестировали разные реализации статически (thrift, protocol buffers) и динамически (json, msgpack) типизированных протоколов для python; сравнили их производительность в разных сценариях, возможности, внутреннее устройство, удобство разработки.

Я расскажу о результатах нашего исследования, особенностях "приготовления" библиотек и выявленных подводных камнях.

Advertisement
Advertisement

More Related Content

Slideshows for you (20)

Viewers also liked (20)

Advertisement

Similar to Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs) (20)

More from Ontico (20)

Advertisement

Recently uploaded (20)

Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)

  1. 1. Сравнение форматов и библиотек сериализации Антон Рыжов, Qrator Labs
  2. 2. Задача Сериализовать данные: ● Без потерь ● Компактно ● Быстро ● Удобно
  3. 3. JSON ✔ Привычно ✔ Удобно ✔ Человекочитаемо [   {     "very": "simple"   } ]
  4. 4. JSON ✔ Привычно ✔ Удобно ✔ Человекочитаемо ✗ Не компактно [   {     "very": "simple"   },   {     "very": "big"   } ]
  5. 5. JSON — компактность 7              1 byte (1:1)→
  6. 6. JSON — компактность 7              1 byte (1:1)→ 65535          5 bytes (5:2)→ 1000 000 000   10 bytes (10:4)→
  7. 7. JSON — компактность 3 / 2   1.5 (3 byte)→
  8. 8. JSON — компактность 3 / 2   1.5 (3 byte)→ 1 / 3   0.3333333333333333 (18 bytes)→
  9. 9. JSON — компактность Hello   "Hello" (+2 bytes)→
  10. 10. JSON — компактность Hello   "Hello" (+2 bytes)→      "u0420u0418u0422" (×3)РИТ →
  11. 11. JSON — компактность Hello   "Hello" (+2 bytes)→      "u0420u0418u0422" (×3)РИТ →      " " ( )РИТ → РИТ опция
  12. 12. JSON — компактность [   {"userId": 1, "userName": "John Smith"},   {"userId": 2, "userName": "Jane Dow"} ]
  13. 13. JSON — компактность [   {"userId": 1, "userName": "John Smith"},   {"userId": 2, "userName": "Jane Dow"} ]
  14. 14. JSON — компактность [   "keys": ["userId", "userName"],   "values": [     [1, "John Smith"],     [2, "Jane Dow"]   ] ]
  15. 15. JSON — целостность dict(1: "foo")   { "1": "foo" }→
  16. 16. JSON — целостность dict(1: "foo")   { "1": "foo" }→ object = { "type_id": 5 } types = { "5": "Type name" }
  17. 17. JSON — целостность Python   JSON:→ { 1: "foo", "1": "bar" }   ?→ PHP   JSON:→ Array(1=> "foo", "1"=> "bar")   ?→
  18. 18. JSON — целостность Python   JSON:→ { 1: "foo", "1": "bar" }   {"1": "bar", "1": "foo"}→ PHP   JSON:→ Array(1=> "foo", "1"=> "bar")   {"1": "bar"}→
  19. 19. JSON — целостность Python   JSON:→ { 1: "foo", "1": "bar" }   {"1": "bar", "1": "foo"}→ PHP   → PHP: Array(1=> "foo", "1"=> "bar")   → Array(1=> "bar")
  20. 20. JSON — binary {"message": "0KDQmNCiKys="}  +30%
  21. 21. JSON — binary {"message": "0KDQmNCiKys="}  +30% {"message_bin": "0KDQmNCiKys="} {"message": { "type": "bin", "value": "0KDQmNCiKys="}}
  22. 22. Альтернативы Схема данных Binary Ключи map BSON ✗ ✓ str Msgpack ✗ ✓ any Google Protobuf ✓ ✓ ✗ Apache Thrift ✓ ✓ any Apache Avro ✓ ✓ str
  23. 23. Зачем схема? ✔Описывает данные
  24. 24. Зачем схема? ✔Описывает данные ✔Уменьшает дублирование
  25. 25. Зачем схема? ✔Описывает данные ✔Уменьшает дублирование ✔Валидирует данные
  26. 26. Зачем схема? ✔Описывает данные ✔Уменьшает дублирование ✔Валидирует данные ✔Приводит типы
  27. 27. Зачем схема? ✔Описывает данные ✔Уменьшает дублирование ✔Валидирует данные ✔Приводит типы ✗ Надо писать
  28. 28. Зачем схема? ✔Описывает данные ✔Уменьшает дублирование ✔Валидирует данные ✔Приводит типы ✗ Надо писать ✗ … а иногда ещё и компилировать
  29. 29. Protobuf ✔ Старое проверенное решение ✔ Разработан Google ✔ Хорошие результаты в тестах в интернете ✔ Хорошая документация
  30. 30. Protobuf ✔ Старое проверенное решение ✔ Разработан Google ✔ Хорошие результаты в тестах в интернете ✔ Хорошая документация ✗ Не всё можно описать – Список списков, map
  31. 31. Protobuf — схема message Point {   required int32 x = 1;   required int32 y = 2; } message PointsList {   repeated Point points = 1; }
  32. 32. Thrift ● Более новый формат ● Разработал Facebook, отдал в Apache ● Документация — справочник типов и BNF ● Есть “Thrift: The Missing Guide” ● RPC-клиент/сервер
  33. 33. Thrift — схема struct PointsList {     1: required list< list<i32> > points, }
  34. 34. Apache Avro ● Ещё более новый формат ● Разработан для Apache Hadoop ● Документация на схему — подробная ● Кодогенерации нет
  35. 35. Avro — схема {     "namespace": "test.avro",     "type": "array",     "items": {         "type": "array",         "items": "int"     } }
  36. 36. Размер integer: «0»; 1-, 2-, 4-byte Msgpack Avro Protobuf JSON Thrift BSON* 0 2 4 6 8 10 12
  37. 37. Размер float: «0», 2.5, 1/3, 1e9/3 Avro Protobuf Msgpack Thrift BSON* JSON 0 2 4 6 8 10 12 14 16 18 20
  38. 38. Размер string: "", "Z"×10, "Я"×10 Msgpack Avro Protobuf JSON Thrift BSON* 0 5 10 15 20 25 30 35
  39. 39. Размер string: "Z"×1000, "Я"×1000 Msgpack Avro Protobuf Thrift BSON* JSON 0 500 1000 1500 2000 2500
  40. 40. Размер 0, 10 bytes Avro Msgpack Protobuf Thrift JSON BSON* 0 5 10 15 20 25
  41. 41. Размер 1000 bytes Avro Msgpack Protobuf Thrift BSON* JSON 0 200 400 600 800 1000 1200 1400 1600
  42. 42. Размер array [0], [10] Avro Msgpack Protobuf JSON Thrift BSON* 0 5 10 15 20 25
  43. 43. Размер map [0], [10] Msgpack Avro Protobuf* JSON BSON Thrift 0 2 4 6 8 10 12 14 16 18 20
  44. 44. Размер struct vs map Msgpack Avro Protobuf* BSON JSON Thrift 0 20 40 60 80 100 120 140 160 180 200
  45. 45. Топ по размеру 1.Apache Avro 2.Msgpack 3.Google Protobuf 4.Apache Thrift 5.JSON 6.BSON
  46. 46. Методика бенчмарка Характерные объекты — строки, байты, словари разных размеров, массивы Замер времени на сериализацию и десериализацию каждой библиотекой в python2 и python3 Сравнение данных до и после Железо: Intel(R) Xeon(R) CPU E5-2683 v4 @ 2.10GHz 64 Gb RAM
  47. 47. Без схемы Поддержка Установка Реализация Генерация кода uJSON 2, 3 pip C-ext ✗ BSON 2, 3 pip Python ✗ Msgpack 2, 3 pip C-ext ✗
  48. 48. Без схемы — затраченное время msgpack ujson json bson encode py2.7 decode py2.7 encode py3.5 decode py3.5
  49. 49. Protobuf Поддержка Установка Реализация Генерация кода protobuf 2, 2to3 make + pip Python ✓ cprotobuf 3 protobuf + pip C-ext ✓ protobuf3 3 protobuf + pip Python ✓
  50. 50. Protobuf — пример кода protobuf, cprotobuf data = test_pb2.PointsList(     points=[         test_pb2.Point(x=1, y=2),         test_pb2.Point(x=3, y=4),     ] ).SerializeToString() pl = test_pb2.PointsList() pl.ParseFromString(data) print(pl.points[0].x)
  51. 51. Protobuf — пример для protobuf3 pl = test_pb2.PointsList() po = test_pb2.Point() po.x = 1; po.y = 2 pl.points.append(po) data = pl.encode_to_bytes() pl = test_pb2.PointsList() pl.parse_from_bytes(data) print(pl.points[0].x)
  52. 52. Protobuf — затраченное время cprotobuf* google_proto protobuf3* encode py2.7 decode py2.7 encode py3.5 decode py3.5
  53. 53. Thrift Поддержка Установка Реализация Генерация кода (apache) thrift 2 make + pip Python ✓ (facebook) Thrift 2, 3 ☠nightmare☠ Python ✓ thriftpy 2, 3 pip Cython ✗ thriftrw 2, 3 pip Cython ✗
  54. 54. (Apache) thrift — пример кода data = serialize(     test_ttypes.PointsList([(1, 2)]) ) points = deserialize(     test_ttypes.PointsList(),     points_list, ).points print(points[0][0])
  55. 55. (facebook)Thrift, thriftpy, thriftrw Совместим с (Apache) thrift по API
  56. 56. Thrift — затраченное время thriftrw fb_thrift** apache_thrift* thriftpy+cython* thriftpy* Py2.7 Py3.5
  57. 57. Thrift — затраченное время thriftrw fb_thrift** apache_thrift* thriftpy+cython* thriftpy* encode py2.7 decode py2.7 encode py3.5 decode py3.5
  58. 58. Avro Поддержка Установка Реализация Генерация кода (apache) avro 2, 3 2 pip 3 src Python ✗ fastavro 2, 3 pip Cython ✗ pyavroc 2, 3 shell + make libavro + wrapper ✗
  59. 59. (Apache) avro — пример упаковки schema = avro.schema.parse(open('points_list.avsc',  'r').read()) io_stream = io.BytesIO() avro.io.DatumWriter(schema).write(     [(1, 2), (3, 4)],     avro.io.BinaryEncoder(io_stream), ) data = io_stream.getvalue()
  60. 60. (Apache) avro — пример распаковки schema = avro.schema.parse(open('points_list.avsc',  'r').read()) io_stream = io.BytesIO(data) points = avro.io.DatumReader(schema).read(     avro.io.BinaryDecoder(io_stream), ) print(points[0][0])
  61. 61. fastavro — пример упаковки schema = json.loads(open('points_list.avsc', 'r').read()) io_stream = io.BytesIO() fastavro.schemaless_writer(     io_stream,     schema,     [(1, 2), (3, 4)], ) return io_stream.getvalue()
  62. 62. fastavro — пример распаковки schema = json.loads(open('points_list.avsc', 'r').read()) io_stream = io.BytesIO(points_list) points = fastavro.schemaless_reader(     io_stream,     schema, ) print(points[0][0])
  63. 63. pyavroc — пример кода schema = open('specs/points_list.avsc', 'r').read() points_writer = _pyavroc.AvroSerializer(schema) data = points_writer.serialize(     [(1, 2), (3, 4)], ) points_reader = _pyavroc.AvroDeserializer(schema) points = points_reader.deserialize(data) print(points[0][0])
  64. 64. Avro — затраченное время pyavroc* fastavro avro encode py2.7 decode py2.7 encode py3.5 decode py3.5
  65. 65. Топ — затраченное время pyavroc* msgpack cprotobuf* thriftrw ujson fastavro thriftpy+cython* Py2.7 Py3.5
  66. 66. Общие рекомендации ● Следить за новыми разработками ● Рассматривать альтернативы ● Референсная библиотека — не всегда самая лучшая ● Альтернативные — бывают ещё хуже ● Не верить бенчмаркам в интернете (В том числе этому) ● Кодогенерация только мешает
  67. 67. Всё ar@qrator.net https://github.com/QratorLabs/ritfest2016

×