← Назад к вопросам

За счет чего происходит уменьшение размера данных в MessagePack?

2.0 Middle🔥 101 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

MessagePack — эффективная бинарная сериализация

MessagePack — это современный формат сериализации, который существенно сжимает данные по сравнению с JSON. Вот механизмы, которые это обеспечивают.

1. Бинарное кодирование вместо текстового

JSON — текстовый формат (неэффективный)

{
  "user_id": 12345,
  "name": "John",
  "email": "john@example.com",
  "active": true
}

Занимает примерно 71 байт (все как текст).

MessagePack — бинарный формат

Тот же объект в MessagePack:

84          # Объект с 4 ключами
a7"user_id" # Строка "user_id" (7 символов)
cd3039      # Число 12345 (2 байта вместо 5)
a4"name"    # Строка "name" (4 символа)
a4"John"    # Строка "John" (4 символа)
...

Занимает примерно 35 байт — в 2 раза меньше!

2. Компактное кодирование чисел

JSON

12345

5 байт текста.

MessagePack

cd3039  # Число 12345 в бинарном виде

3 байта вместо 5.

Примеры для разных чисел

import msgpack
import json

# Маленькие числа кодируются в 1 байт
small_num = 42
print(len(json.dumps(small_num)))      # 2 байта (JSON)
print(len(msgpack.packb(small_num)))   # 1 байт (MessagePack)

# Большие числа тоже компактнее
big_num = 2147483647
print(len(json.dumps(big_num)))        # 10 байт (JSON)
print(len(msgpack.packb(big_num)))     # 5 байт (MessagePack)

3. Компактное кодирование строк

JSON хранит каждый символ как есть. MessagePack добавляет префикс с длиной:

JSON

"hello"

7 байт (включая кавычки).

MessagePack

a5hello  # a5 = строка из 5 символов, затем 5 символов

6 байт (1 байт префикса + 5 символов).

4. Сжатие булевых значений и null

JSON

true   // 4 байта
false  // 5 байт
null   // 4 байта

MessagePack

c3      // true  — 1 байт
c2      // false — 1 байт
c0      // null  — 1 байт

Разница: 4-5 байт vs 1 байт!

5. Отсутствие пробелов и форматирования

JSON часто использует пробелы для читаемости:

{
  "name": "John",
  "age": 30
}

49 байт (с отступами).

Минифицированный JSON:

{"name":"John","age":30}

23 байта.

Но MessagePack уже компактен изначально:

82a4name a4John a3age 1e

~18 байт.

6. Оптимизация структур данных

Если часто повторяются одни и те же ключи, можно использовать схему:

from msgpack import packb, unpackb

# Вместо полных ключей можно использовать индексы
users = [
    {"id": 1, "name": "John", "email": "john@example.com"},
    {"id": 2, "name": "Jane", "email": "jane@example.com"},
]

# JSON — дублирует ключи для каждого объекта
json_size = len(json.dumps(users))
print(json_size)  # ~120 байт

# MessagePack
msgpack_size = len(packb(users))
print(msgpack_size)  # ~60 байт

7. Практический пример с бенчмарком

import msgpack
import json
import sys

data = {
    "users": [
        {
            "id": 1,
            "username": "john_doe",
            "email": "john@example.com",
            "created_at": "2024-01-01T12:00:00Z",
            "verified": True,
            "last_login": None,
            "permissions": ["read", "write"],
        }
        for _ in range(100)
    ]
}

json_data = json.dumps(data).encode()
msgpack_data = msgpack.packb(data)

print(f"JSON size: {len(json_data)} bytes")
print(f"MessagePack size: {len(msgpack_data)} bytes")
print(f"Compression ratio: {len(msgpack_data) / len(json_data):.1%}")

# Примерный результат:
# JSON size: 15244 bytes
# MessagePack size: 8532 bytes
# Compression ratio: 56.0%

8. Использование в микросервисах

from fastapi import FastAPI
from fastapi.responses import Response
from msgpack import packb, unpackb

app = FastAPI()

@app.get("/api/users")
async def get_users():
    data = [{"id": 1, "name": "John"}]
    
    # Вместо JSON
    # return JSONResponse(data)
    
    # Используем MessagePack
    return Response(
        packb(data),
        media_type="application/msgpack"
    )

@app.post("/api/users")
async def create_user(request: Request):
    # Парсим MessagePack вместо JSON
    body = await request.body()
    data = unpackb(body)
    # ...

9. Недостатки MessagePack

Несмотря на преимущества:

  • Не читаемо человеком — нужны инструменты для отладки
  • Меньше экосистема — JSON более популярен
  • Несовместимо с веб стандартами — браузеры работают с JSON
  • Сложнее отлаживать — нельзя просто посмотреть в инспекторе

Когда использовать MessagePack

Используй MessagePack для:

  • Внутренней коммуникации между микросервисами
  • Кэширования больших объектов
  • Работы с большими объемами данных (streaming, analytics)
  • Когда размер трафика критичен (мобильные приложения)

НЕ используй для:

  • Публичного API (используй JSON)
  • Веб-фронтенда
  • Когда важна читаемость данных
  • Когда экосистема неважна

Итого

MessagePack достигает сжатия данных через:

  1. Бинарное кодирование вместо текстового
  2. Компактное кодирование чисел (2-5 байт вместо 1-10)
  3. Сжатие строк с префиксом длины
  4. 1-байтные кодировки булевых значений
  5. Отсутствие пробелов и форматирования
  6. Эффективная структура без повтора ключей

Обычно MessagePack дает сжатие на 40-60% по сравнению с JSON, при этом сохраняя быстроту сериализации и десериализации.

За счет чего происходит уменьшение размера данных в MessagePack? | PrepBro