MessagePack Nedir?Serialize/Deserialize Yöntemleri Neden Önemlidir?

Bir koşucu hayal edin...
Ayakkabısı eski püskü, sürekli koşmaktan yıpranmış ve koşarken ayağını acıtan taşlar yüzünden düşen ama yılmadan yoluna devam etmeye çalışan bir koşucu. Belki üstündeki forması çok iyi, hiç terletmiyor hatta koşarken çok rahat fakat üstündeki bu formanın performansına herhangi bir katkısı ne yazık ki yok.
Şimdi de bu koşucumuzu takım arkadaşlarıyla birlikte bir bayrak yarışının son koşucusu olduğunu hayal edelim. Her ne kadar ondan önce koşan takım arkadaşları çok hızlı koşmuş olsa da bitiş çizgisine takımı götürecek olan bu koşucudur. Bu koşucu yeterince iyi koşmazsa takım kaybedebilir.
- Serialize/Deserialize Nedir?
Kısaca bahsedecek olursak serialize ya da serialization, bir datayı kolayca ulaşılabilir hala getirmek ya da bir datayı platform bağımsız hale getirmektir(json,xml,binary).
Bu durumda deserialize ise: Ulaşılabilir hale gelmiş datayı tekrardan hangi dilde yazıyorsak o dildeki objeye çevirmektir.
- Peki Neden Önemli?
Bir yazılım projesini yukarıda bahsettiğim gibi bayrak yarışı gibi örneklendirecek olursak:
Projemizdeki servislerin her biri bayrak taşıyan koşucu misali gayet iyi şekilde çalışıyor olsun. Veri tabanı bağlantıları kusursuz. Cache mekanizmalarımız mükemmel bir şekilde işliyor olsun. Sonunda oluşturduğumuz veriyi client tarafına aktaracağımız zaman bir serialize işlemine tabi tutmamız gerekecek. Eğer buradaki serialize işlemi yavaş olursa response süresini uzatacak ve bu da performansı etkileyecek. Hatta bilgilerimizi redis gibi cache de yada NoSql veritabanlarından birinde tutuyorsak,serialize yönteminize göre performansınız daha çok etkilenmektedir.
- Peki Serialize/Deserialize Yöntemlerinden Hangisi Neden Seçilmeli?
Aslında bu sorunun yanıtı tamamen projenin gereksinimleri ve verinizin büyüklüğüne göre değişir.
Örneğin: Küçük bir veriyi serialize edip, bir dosyaya yazdığınızı ve bu dosyayı müşteriye mail olarak ileten bir uygulamanız olsun. Buradaki veri küçük olduğundan ve dosyaya yazdığınız verinin anlamlı bir veri olmasını istediğinizden dolayı Json kullanmak mantıklı olacaktır.
Fakat aynı örneğin tersini düşünelim verimiz çok büyük fakat uygulamamız bu sefer serialize edip redise atacak. Bu sefer redise attığımız verinin anlamlı bir halde olmasına gerek yok. Çünkü redisden çekerken zaten bu veriyi deserialize edeceğimizden dolayı anlamlı bir objeye dönmüş olacaktır. Bu durumda performansı düşünerek en hızlı serialize hangi kütüphane yapıyorsa o seçilebilir.
Gelin birlikte messagepack, protopuf, byte, json serialize yöntemlerini benchmark yapacak olan programı yapalım.
Bunun için terminalden dotnet new console -n benchmark_test komutuyla yeni bir console uygulaması yaratalım.
Uygulamamızı oluşturduktan sonra gerekli olan paketleri yükleyelim.
- dotnet add package BenchmarkDotnet
- dotnet add package MessagePack
- dotnet add package Newtonsoft.Json
- dotnet add package protobuf-netİlgili nuget paketlerini yükledikten sonra serialize işlemleri için örnek datalara ihtiyacımız var. Bunun için ilgili linkten bir tane büyük boyutlu bir json oluşturup projemize dahil edelim.
Oluşturduğumuz jsonları deserialize etmemiz için jsonların modeline ihtiyacımız var. Bunun için Model adında bir class oluşturuyoruz.
İsterseniz json verinizi .net tarafındaki classlara çeviren online bir tool olan json2csharp’ı kullanabilirsiniz.
- Serializable : Byte
serialize/deserializeişlemlerimiz için gerekli olan attribute. - MessagePackObject: MessagePack
serialize/deserializeişlemlerimiz için gerekli olanattribute.
MessagePackserialize/deserializeişlemleri için bütünpropertylerineKey attribute’nun verilmesi gerekiyor. Eğer kullanılan baseattributeMessagePack(true)şeklinde kullanırsaKeyattributelerine gerek kalmaz.
- ProtoContract: Protobuf
serialize/deserializeişlemlerimiz için gerekli olanattribute.
Protobuf’ın modelinizdeki propertylerin hangilerini
serialize/deserializeetmesini istiyorsak,ProtoMemberattribute’nu vermemiz gerekiyor.
Modeli oluşturduktan sonra Benchmark işlemini gerçekleştirecek olan classımızı oluşturarak devam edelim. Bunun için BigDataSerializerBenchmark adında bir class açıyoruz.
— [SimpleJob(RunStrategy.Monitoring, targetCount: 100)]: Bu
classa bir iş atamış oluyoruz. O da class içerisinde belirttiğimiz methodları 100 er kez çağıracak ve bunun benchmarkını monitör etmesini sağlayacak.— LoadDataset: Bu methodumuzun
GlobalSetupattributealmasındaki amaç: Benchmark işlemi başlamadan önce gerekli ayarların yapılmasını sağlamak. Örneğimizdebig_data.jsonadındaki dosyayıdesearilizeedip modelliyoruz. Böylece diğer methodlarda ilgili modelserialize/deserilizeişlemlerine tutulabilmesini sağlıyoruz.— [Benchmark]: Bu
attributesayesinde ilgili methodların benchmarka dahil olup olmadığını söylemiş oluyoruz.
Benchmark classımızı hazırladığımıza göre şimdi sonuçları gösterme işlemine geçebiliriz. Bunun için Program.cs dosyamıza gidiyoruz.
Artık projeyi çalıştırıp sonuçların nasıl olduğuna bakabiliriz.
NOT:
BenchmarkDotNetkütüphanesi belirttiğimizclassınbenchmarkını çıkartması için projemizinRealesemodunda çalışmasını beklemektedir.
Bunun için dotnet run -c Release komutunu kullanarak projeyi çalıştırıyoruz.

Benchmark sonucu bize gösteriyor ki MessagePack diğer serialize yöntemlerine göre çok çok daha hızlı olurken, Protobuf ile oluşturulan data diğer serialize yöntemlerine göre çok çok daha az boyutta.
Tabi yukarıda da söylediğim gibi hangi serialize yöntemini kullanacağınız size ve tabi projenizin ihtiyacına göre değişmektedir.
Yaptığımız bu projeye buradan ulaşabilirsiniz.
- Peki Bence Neden MessagePack?
Çalıştığım projede yaptığımız bir apide saniyede atılan istek sayısı oldukça fazla, response süremiz ise çok uzundu. Bu isteklerin sonucundan dönen veride ciddi anlamda büyüktü. Bundan dolayı bu api de performans sorunları yaşamaya başlamıştık. Benchmark yaptığımızda en çok serialize/deserialize işlemlerinde zaman kaybettiğimizi gördük.
Verilerimizin tamamını redisden çekiyorduk. Haliyle redise yazarken veya redisden veriyi alırken serialize/deserialize işlemlerine tabi tutuyorduk. Başlarda serialize/deserialize yöntemi olarak json kullanmıştık. Fakat verimiz çok büyüktü serialize/deserialize işlemlerinde ciddi performans kaybı yaşıyorduk.
Sonrasında serialize/deserialize yönteminibyte olarak değiştirmeye karar verdik. Json’a göre byte’a çevirmemiz fark yaratmıştı. Fakat dönen verimiz daha da büyümeye başlayınca performans anlamında hala sıkıntılarımızın olduğunu gözlemledik.
Bunun üzerine serialize/deserialize yöntemleri hakkında araştırma yapmaya başladım. Birçok kaynak messagepack den bahsediyordu. Hem serialize/deserialize işlemlerindeki hızı, hem de serialize işlemleri sonrasında çıkan verinin boyutu ciddi anlamda küçültüyordu. Bunun üzerine messagepack’i denemeye karar verdik. Sonuç şaşırtıcıydı. Başlarda sadece bu işlemler için ortalama 1000ms bulurken, messagepackde bu süre ortalama 19ms bulmuştu. Gerçekten gözle görülür bir fark vardı.
Okuduğunuz için teşekkür ederim.
Sağlıcakla kalın…
