За счет чего происходит уменьшение размера данных в MessagePack?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
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 достигает сжатия данных через:
- Бинарное кодирование вместо текстового
- Компактное кодирование чисел (2-5 байт вместо 1-10)
- Сжатие строк с префиксом длины
- 1-байтные кодировки булевых значений
- Отсутствие пробелов и форматирования
- Эффективная структура без повтора ключей
Обычно MessagePack дает сжатие на 40-60% по сравнению с JSON, при этом сохраняя быстроту сериализации и десериализации.