Mesaj Kuyrukları — Serileştirme için MessagePack vs JSON
Mesaj kuyruklarında mesajlarımızın nasıl tutulacağı, sistemin verimliliğini ve performansını etkileyen önemli bir parametredir. API'larda kullandığımız JSON, insanlar için okunması ve yazılması kolay bir yöntem. Ancak, mesaj kuyruklarında sistemler veya sistemlerin küçük parçaları arasında iletişimi sağlayan veriler sunuyoruz ve MessagePack’ın binary format oluşu ile gelen kompaktlık ile network verimliliği, daha hızlı serileştirme, deserileştirme getirilerini kullanarak yüksek performans, düşük gecikmenin ve bütçenin kritik olduğu dağıtık sistemlerimizin mesaj kuyruklarında MessagePack kullanmak mükemmel bir seçim olabilir.
MessagePack verileri kompakt bir binary formatta tutar, bu da JSON gibi metin tabanlı formatlara kıyasla daha küçük boyutlar demektir. Binary yapısı nedeniyle daha hızlı serileştirme ve deserileştirme yapılmasını sağlar, metin tabanlı serileştirme yöntemlerine kıyasla binary ile gelen kompaktlık sayesinde network üzerinde boyutları daha az olan paketler ile iletişim kurmayı sağlar bu da hem verimlilik hem de performansa katkı sağlar.
Gözlem
Symbol, Price ve Volume olarak 3 alanı olan bir finansal enstrümanın alanlarını 0, 1, 2 şeklinde keyleyerek (Serileştirilirken 'Symbol' adı yerine ‘0’ olarak tutulacak, bu da serileştirilmiş veri boyutunu azaltacaktır.) bir tanım oluşturdum ve bunun üzerinden 1 adetten 1,000,000 adete kadar veri setleri oluşturarak serileştirme performansını ve veri boyutunu gözlemlemeye çalıştım.
[MessagePackObject]
public record Stock
{
[Key(0)] [JsonPropertyName("0")] public string Symbol { get; init; }
[Key(1)] [JsonPropertyName("1")] public double Price { get; init; }
[Key(2)] [JsonPropertyName("2")] public double Volume { get; init; }
public Stock(string symbol, double price, double volume)
{
Symbol = symbol;
Price = price;
Volume = volume;
}
[SerializationConstructor]
public Stock()
{
}
}
Performansa ne kadar etki ediyor?
Aşağıda 1 adetten 1,000,000 adete kadar olan farklı adette obje barındıran verilerin serileştirme ve deserileştirme benchmark sonuçlarını göreceksiniz, MessagePack ile yapılan serileştirme ve deserileştirme ortalama 411% daha performanslı çalışıyor.
| Method | Mean | Error | StdDev | Median | Gen0 | Gen1 | Gen2 | Allocated |
|------------------------------------------------------ |-----------------:|-----------------:|-----------------:|-----------------:|-----------:|----------:|----------:|------------:|
| MessagePackSerializationDeserialization_Count_1 | 113.6 ns | 0.08 ns | 0.07 ns | 113.6 ns | 0.0216 | - | - | 136 B |
| MessagePackSerializationDeserialization_Count_10 | 838.8 ns | 1.66 ns | 1.39 ns | 838.9 ns | 0.1984 | - | - | 1248 B |
| MessagePackSerializationDeserialization_Count_100 | 7,989.5 ns | 158.02 ns | 375.54 ns | 7,854.9 ns | 1.8768 | 0.0076 | - | 11776 B |
| MessagePackSerializationDeserialization_Count_1000 | 76,766.5 ns | 1,213.33 ns | 1,134.95 ns | 76,330.1 ns | 19.8975 | 3.2959 | - | 125176 B |
| MessagePackSerializationDeserialization_Count_10000 | 917,663.5 ns | 17,815.88 ns | 16,664.99 ns | 910,570.7 ns | 155.2734 | 80.0781 | 2.9297 | 1268194 B |
| MessagePackSerializationDeserialization_Count_100000 | 25,214,373.4 ns | 494,744.89 ns | 740,510.85 ns | 25,320,850.2 ns | 1531.2500 | 687.5000 | 312.5000 | 12788717 B |
| MessagePackSerializationDeserialization_Count_1000000 | 275,701,080.9 ns | 5,461,375.35 ns | 8,819,103.19 ns | 276,414,093.8 ns | 20000.0000 | 9000.0000 | 3000.0000 | 152010116 B |
| JSONSerializationDeserialization_Count_1 | 495.5 ns | 0.36 ns | 0.32 ns | 495.4 ns | 0.0238 | - | - | 152 B |
| JSONSerializationDeserialization_Count_10 | 5,410.7 ns | 107.95 ns | 225.33 ns | 5,262.1 ns | 0.3738 | - | - | 2368 B |
| JSONSerializationDeserialization_Count_100 | 48,960.2 ns | 175.93 ns | 155.96 ns | 48,957.9 ns | 2.4414 | 0.0610 | - | 15649 B |
| JSONSerializationDeserialization_Count_1000 | 484,821.9 ns | 1,608.85 ns | 1,343.46 ns | 484,129.2 ns | 23.4375 | 0.9766 | - | 152529 B |
| JSONSerializationDeserialization_Count_10000 | 6,817,696.4 ns | 126,110.83 ns | 117,964.15 ns | 6,769,114.7 ns | 179.6875 | 93.7500 | 46.8750 | 1694997 B |
| JSONSerializationDeserialization_Count_100000 | 68,462,841.2 ns | 1,162,845.12 ns | 1,428,078.24 ns | 68,705,116.1 ns | 1571.4286 | 571.4286 | 142.8571 | 20672606 B |
| JSONSerializationDeserialization_Count_1000000 | 664,231,691.7 ns | 12,880,939.80 ns | 12,048,839.08 ns | 665,760,375.0 ns | 18000.0000 | 9000.0000 | 4000.0000 | 289836648 B |
Özetle, MessagePack’ın JSON serileştirme ve deserileştirmede her Count
değeri için belirgin derecede daha hızlı olduğunu görüyoruz. Performans farkı küçük veri setlerinde daha belirgin olup, veri seti büyüdükçe fark azalmaktadır, ancak yine de MessagePack genellikle %100–2 kat daha fazla performanslıdır.
Veri boyutuna ne kadar etki ediyor?
Yukarıda bahsettiğim gibi MessagePack binary ile serileştirmesi daha kompakt bir veri sunuyor.
Aşağıda 1 adetten 1,000,000 adete kadar obje barındıran verilerin serileştirme sonrası ne kadar yer tuttuğunu göreceksiniz, MessagePack ile yapılan serileştirme verileri JSON’a göre 37% oranında daha verimli.
+-----------+----------------+----------------+
| Count | MessagePack | JSON |
+-----------+----------------+----------------+
|1 | 26 bytes | 43 bytes |
|10 | 281 bytes | 458 bytes |
|100 | 2893 bytes | 4690 bytes |
|1,000 | 29893 bytes | 47808 bytes |
|10,000 | 308893 bytes | 488719 bytes |
|100,000 | 3188895 bytes | 4985072 bytes |
|1,000,000 | 32888895 bytes | 50854409 bytes |
+-----------+----------------+----------------+
Sonuç olarak, MessagePack ile serileştirme mesaj kuyruklarında kullanıldığında daha hızlı işleme süreleri ve daha düşük veri boyutlarıyla yüksek performanslı ve verimli sistemlerin oluşturulmasına olanak tanır fakat insanların veriyi okuyabilmesini ve verileri manuel düzenleyebilmesini ortadan kaldırmış olursunuz. Zaten düzgün çalışan bir sisteminiz varsa insanlar neden verileri okumaya ve düzenlemeye ihtiyaç duysun ki?
Benchmark kodları: https://gist.github.com/halilkocaoz/a2c2f345fc7f9a3370652d54ebcd11ad
Veri boyutunu gözlemleme kodları: https://gist.github.com/halilkocaoz/70559ae6720001a5052aca50c8c99056