Yoğunlaştırma ve Sıkıştırma: Özel İkili Dosya Formatımız

Geçtiğimiz yıl ROBLOX'a getirdiğimiz performans iyileştirmelerini ve görüntüleme özelliklerini düşünün. Bunlar arasında hafif parçalar, hızlı kümeler, verimli çarpışma algılama ve dinamik aydınlatma yer alıyor. Bu iyileştirmeler, yapımcıların bir zamanlar karşılaştığı parça sayısı, fizik simülasyonu ve estetik esneklik sınırlarını ortadan kaldırdı ve bir dünya dolusu olasılığın kapılarını açtı. Ayrıca, yapımcılar sınırları her zamankinden daha da ileriye taşıdıkça yeni sınırlar da ortaya çıktı. Bu makalede, ROBLOX mekanlarının dosya boyutunu yaklaşık 100 kat, yükleme/kaydetme süresini ise 5-10 kat nasıl azalttığımızı açıklayacağız.
Tüy kadar hafif parçaları düşünün. Artık yalnızca belirli şekil ve malzemelerle sınırlı olmayan, tüm ROBLOX parçalarına uygulanan bu özellik, on binlerce tuğladan oluşan bir ROBLOX mekanı oluşturmanıza ve bunu hem masaüstü hem de mobil cihazlarda çalıştırmanıza olanak tanır. Ancak, on binlerce parçadan oluşan bir mekan, çok büyük bir dosya boyutuna neden olabilir. Bu makale boyunca referans vereceğimiz test mekanımız 50.000 parçadan oluşuyor ve tam 230 megabayt ağırlığında. Bu, oluşturucuları birçok yönden etkileyecek kadar büyük bir boyut: işleme, kaydetme/yükleme, yayınlama, sunucudan mekan yükleme ve daha fazlası.
Kullanıcı deneyimini iyileştirmek ve henüz duyurulmamış bir projenin geliştirilmesini desteklemek amacıyla, ROBLOX yapılarının dosya boyutunu ele almanın zamanının geldiğine karar verdik. Bu amaçla, yakında ROBLOX verilerini XML yerine ikili formatta kaydeden yeni bir dosya formatını test etmeye başlayacağız. Değişiklik şeffaf olacak, ancak zamanla yapımcıların bekleme süresini azaltacaktır. ROBLOX verilerini kaydetmenin yeni yöntemini yavaş yavaş uygulamaya koyacağız. İlk olarak ROBLOX Studio'daki "Tek Başına Oynat" ve "Sunucuyu Başlat" oturumları için oluşturulan geçici dosyalarla başlayıp, sonunda Kişisel Yapım Sunucusu depolama alanına, yer yüklemelerine ve yerel kaydetmelere geçeceğiz.

Eskiyi atın
Dosya boyutu önemlidir. Dosyayı yerel olarak kaydetme ve yükleme süresini, ayrıca ROBLOX.com'a yayınlama ve buradan içerik yükleme süresini etkiler. Ayrıca, ROBLOX.com'a yayınlanabilecek içeriklerde dosya boyutu kısıtlaması vardır (geliştiriciler, oyun yüklendikten sonra ek parçalar oluşturan komut dosyaları yazarak bu sorunu aşmanın yollarını bulmuşlardır).
ROBLOX, uzun süredir yer verilerini XML formatında kaydetmektedir. Bu, her nesnenin özellikleri ve her özelliğin bir değeri olduğu, her şeyin güzel bir veri ağacında birbirine uyan, sezgisel, hiyerarşiye dayalı bir formattır. Ancak, öncelikle bellek tarafından okunabilir verileri bir dizeye dönüştürmek zaman aldığı (örneğin, kaydetme sırasında) ve önemli ölçüde yineleme olduğu için sonsuz ölçeklenemez. Neredeyse aynı olan iki parça, tamamen ayrı XML parçaları olarak depolanır. XML olarak kaydedildiğinde, 50.000 parçadan oluşan ve dosya boyutu 230 megabayt olan test mekanımızın kaydedilmesi 23 saniye, yüklenmesi ise 37 saniye sürer. İnsan tarafından okunabilir olması (hata ayıklama amaçları için yararlı) ve ileriye/geriye dönük uyumlu olması (ROBLOX Studio ile ROBLOX Player'ın sürümlerinin her zaman aynı olmadığı ortamlarda yararlı) gibi avantajları olsa da, bu format artık bize yetmiyor.
XML ayrıştırıcımızı iyileştirmeyi düşündük, ancak bunun faydalarının sınırlı olacağını biliyorduk. ROBLOX verilerini kaydettiğimiz formatı baştan aşağı yenileyerek büyük bir adım atmaya karar verdik.
Yeniye geçiş
ROBLOX yaratımlarını ikili formatta kaydetmek suretiyle, özelliklere yapılan gereksiz referansları ortadan kaldırıyoruz. Bu tek başına dosya boyutunda 10 katlık bir azalmaya neden oluyor.
Metin ağırlıklı XML formatına alternatiflerden biri de ikili formattır. İkisi arasında keskin farklar vardır.
- İkili format insan tarafından okunamaz. Ancak, ikili veriler bellek içi temsiline çok benzer, yani bellekteki bir nesneyi alıp onu bir bayt akışı olarak yazmak (ve tersi) bizim için kolaydır.
- Her biri 30'a yakın özelliği ve değerlerini içeren nesnelerden oluşan bir hiyerarşi yerine, ROBLOX verileri tekrarlamayı azaltmak için gruplar halinde depolanır (yani, her özellik için, o yerdeki tüm nesnelerin değerini kaydederiz). Bu, gelecekte bir parça özelliğini kaldırmamız durumunda ortaya çıkabilecek, kullanımdan kaldırılmış verilerin yüklenmesini atlamayı da kolaylaştırır. Yine de ileri ve geri uyumluluk avantajından yararlanmaya devam ederiz.
Bir ROBLOX yaratımını ikili formatta kaydederek, özelliklere yapılan gereksiz referansları (kullanıcılar tarafından eklenemeyen/kaldırılamayan ve genellikle statik olan) ortadan kaldırır ve dosya boyutlarını yaklaşık 10 kat azaltırız. Ancak bu, sihirli bir düğmeye basmak kadar basit değildir; özellik değerlerini (tamsayılar) hem hızlı hem de sıkıştırılabilir bir şekilde kaydetmek için özel bir yöntem geliştirdik.
Hız ve sıkıştırma için özellik değerlerini dönüştürme
İlk olarak, özellik değeri tamsayılarını dört bayta bölüyoruz. Her baytın maksimum değeri 2^8-1 (veya 255) dir. Yedi, şöyle görünür:
0 | 0 | 0 | 7 |
Ve 258 değeri şöyle görünür:
0 | 0 | 1 | 2 |
Kodumuz, her bir değeri satır bazında değil, sütun bazında depolar. ROBLOX'taki çoğu özellik değeri küçük olduğundan, sonunda birçok sıfırın üst üste yığılmasıyla sonuçlanır. Bu tür bir tekrarlama, sıkıştırma için harikadır.
Örneğin, dosyaya şu tamsayıları yazmak istediğimizi varsayalım: 1, 5, 4, 258. Basit bir yaklaşım, baytları şu şekilde arka arkaya yazardı:
0 | 0 | 0 | 1 | 0 | 0 | 0 | 5 | 0 | 0 | 0 | 4 | 0 | 0 | 1 | 2 |
Ancak sütuna göre yeniden sıralamamızda, bunlar şu şekilde yazılır:
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 5 | 4 | 2 |
Çok sayıda sıfır tekrarlandığı için bu, çok daha verimli bir şekilde sıkıştırır.
Negatif sayılar bu tekniği zorlaştırır. Çok yaygın olmasalar da, örneğin bir GUI öğesinin konumunu ayarlamak için negatif bir sayı kullanıldığında ROBLOX verilerinde ortaya çıkabilirler. İşareti tersine çevirmek için ikinin tamamlayıcısı olarak bilinen matematiksel işlemi uyguladıktan sonra (2^32 + (-7)), negatif yedi şu şekilde görünür:
255 | 255 | 255 | 249 |
Sıfır olmayan tüm bu sayılar, hedefimiz olan yüksek oranda sıkıştırılabilir bir sıfırlardan oluşan bayt akışını engeller. Negatif tamsayıları küçük pozitif tamsayılara dönüştürmek için ikinci bir yöntem geliştirdik. Bir değer 0'dan büyük veya 0'a eşit olduğunda, onu şu formülden geçiriyoruz:
2 x nBir sayı 0'dan küçük olduğunda, onu şu şekilde ele alıyoruz:
2 x |n| - 1Bu, 7 değerinin 14 (2 x 7) olarak temsil edildiği anlamına gelir. -7 değeri ise 13 (2 x |7| - 1) olarak temsil edilir. Bu sayıları üst üste koyduğumuzda, sıfırlar birikir ve son derece sıkıştırılabilir bir dosya elde ederiz.
0 | 0 | 0 | 14 |
0 | 0 | 0 | 13 |
Tüm bu dönüştürme ve hesaplamalar çok az maliyetle gerçekleşir. Bu nedenle, tamamen bir sıkıştırma algoritmasına güvenmek yerine bu işi ön uçta halletmek çok daha verimlidir.
Özellik değerlerinin tamsayılarını baytlara ayırdıktan sonra, verileri otomatik olarak LZ4 sıkıştırma algoritmasından geçiriyoruz. Bu, ikili verileri çok düşük bir maliyetle hızlı bir şekilde sıkıştıran kayıpsız bir algoritmadır. Bu, dosya boyutunu daha da azaltır. Önceden, dosya depolama sürecinin bu aşamasında sıkıştırma yapılmıyordu; sıkıştırma, bir içerik HTTP üzerinden ROBLOX.com'a aktarıldığında Gzip'in otomatik sıkıştırma özelliği aracılığıyla gerçekleşiyordu.
Yeni formatın test edilmesi
İkili dosya formatı ve LZ4 sıkıştırması ile 230 megabaytlık ROBLOX yeri 1 megabaytın altına düşer. Gzip sıkıştırmasından sonra dosya yaklaşık 100 kilobayt olur. İşte şirket içinde yaptığımız birkaç testin sonuçları:
Test 1
50.000 parça, 150.000 ManualWeld eklemi ve 8 milyon vokselden oluşan bir test alanı oluşturduk.
XML | İkili | |
Boyut | 230 mb | 600 kb |
Boyut (Gzip sonrası) | 3,9 mb | 93 kb |
Yükleme süresi | 27 saniye | 3,7 saniye |
Kaydetme süresi | 20 saniye | 0,5 saniye |
Test 2
40.000 parçadan oluşan gerçek bir ROBLOX seviyesi olan Welcome to the Neighborhood of ROBLOXia'yı test ettik. Seviye çok fazla eklem içermiyor, bu da test alanına kıyasla sayılardaki farkı açıklıyor. Birçok cesur yapımcı, dosya boyutunu küçültmek için komut dosyası yoluyla seviyelerinden eklemleri kaldırmış, ancak bunun bedeli olarak fiziksel simülasyonu kaybetmiştir. Bu, onların işini kolaylaştıracaktır.
XML | İkili | |
Boyut | 112 mb | 1 mb |
Boyut (Gzip sonrası) | 3,5 mb | 700 kb |
Yükleme süresi | 15 saniye | 2 saniye |
Kaydetme süresi | 9 saniye | 0,2 saniye |
Not: Yükleme/kaydetme süreleri sunucudan alınmıştır; Studio'da kaydetme süresi aynıdır, ancak Studio'da yükleme süresi biraz daha uzundur çünkü geri al/yeniden yap işlevlerini yürüten bir sistem kurmak için bazı ek işlemler gerçekleştirilir.

Her iki testte de, dosya boyutunda 100 kat azalma ve yükleme/kaydetme süresinde 5-10 kat azalma gibi iyileştirmeler elde edildi. Bu makalenin başında belirtildiği gibi, ikili dosya formatını yavaş yavaş kullanıma sunacağız. İlk olarak, ROBLOX Studio üzerinden "Tek Başına Oynat" veya "Sunucuyu Başlat" seçeneklerini kullanarak bir oyun oturumu başlattığınızda oluşturulan geçici dosyalarla başlayacağız. Bunun verilerinizi bozmayacağından emin olmak için gerekli özeni gösterdik, ancak herhangi bir garip davranış fark ederseniz (örneğin, parçalarınız olması gerektiği gibi görünmüyor veya daha az olası olmakla birlikte bir dosyayı açamıyorsanız) geri bildirimde bulunmanızı rica ederiz.
Sonunda, Personal Build Server ve yerel kayıtlar için verileri ikili formatta depolamaya başlayacağız. O zaman, daha büyük bir fayda görmeye başlamalısınız. Umudumuz, daha sorunsuz bir oluşturma, kaydetme ve yayınlama sürecine kolayca alışmanız ve ROBLOX deneyiminin kalitesinde ince ama önemli bir artışın keyfini çıkarmanızdır.


