Aptos Framework’e iki güçlü yenilik getiriyoruz: Ordered Maps ve Big Ordered Maps. Bu yeni anahtar-değer koleksiyonları, Move dilinin gücünü ve esnekliğini genişletiyor — gerçek zamanlı DeFi sistemlerinden, yüksek işlem kapasiteli zincir içi indeksleme ve analitiğe kadar geniş bir yelpazedeki zincir içi kullanım durumlarına verimli ve öngörülebilir performans getiriyor.
Bu veri yapılarının performansını daha da artırmak — ve geliştiriciler için yeni optimizasyon stratejilerinin önünü açmak — amacıyla, aynı zamanda yeni Move tabanlı fonksiyonlar da sunuyoruz: mem::swap, vector::move_range, cmp::compare ve bcs::constant_serialized_size
. Bu eklemelerle birlikte Aptos’taki Move, hızlı, güvenli ve ölçeklenebilir zincir içi uygulamalar geliştiren geliştiricilerin tercih ettiği platform olarak daha da güçlendi. Bu yenilikler bir araya geldiğinde, Aptos üzerindeki Move’u hızlı, güvenli ve ölçeklenebilir zincir içi uygulamalar geliştirmek isteyen geliştiriciler için tercih edilen platform olarak daha da güçlendiriyor.
Ordered Map
OrderedMap
, tamamı bağlı olduğu parent resource (ebeveyn/ana kaynak) içerisinde saklanan bir yapıdır. Şu anda sıralı bir vektör olarak uygulanmıştır. Resource boyutlarının sınırlı olması ve optimize edilmiş vektör işlemlerinden (örneğin memcpy
) faydalanması sayesinde yüksek performans sunar — yaklaşık olarak O(log(n)) karmaşıklığına ulaşır, hem de oldukça basit bir uygulamayla.
Yaptığımız performans testlerinde, OrderedMap
’i alternatif bir yapı olan (SimpleMap
) ile karşılaştırdık. Farklı boyutlardaki haritalar üzerinde bir insert
ve bir remove
işleminin ne kadar sürede gerçekleştiğini (mikrosaniye cinsinden) ölçtük.
Eşdeğer işlevsellik ve geliştirilmiş performans sayesinde, OrderedMap
, SimpleMap
’in yerini tamamen alır ve onu geçer. Ancak, SimpleMap
sabit ve önceden tanımlanmış bir yapıya sahip olduğu için onu doğrudan yerine koymak mümkün olmadı. Bu nedenle, OrderedMap
, gelecekte yapılacak iyileştirme ve genişletmelere imkân tanımak adına, Move 2’nin yeni bir özelliği olan enum yapısını kullanır.
Big Ordered Map
BigOrderedMap
, anahtar-değer eşlemesi yapan ve keyfi büyüklüğe ulaşabilen bir haritadır; içeriğini birden fazla (boyutu sınırlı) resource arasında saklar. Şu anki uygulaması, B+ ağacı (B+ tree) yapısıdır çünkü bu yapı, zincir içi saklama düzenine en uygun olanıdır — burada maliyetin büyük kısmı saklama öğelerine veri yükleme ve yazmadan kaynaklanır ve kısmi okuma/yazma yapılmaz.
Bu uygulamanın çok yönlü ve geniş kullanım alanlarına uygun olmasını sağlayan birkaç özelliği vardır:
-
Az sayıda öğe içerdiğinde, tüm verileri onu içeren resource içinde saklar ve bu sayede OrderedMap ile karşılaştırılabilir bir performans sunar; daha fazla öğe eklendikçe dinamik olarak birden fazla resource’a genişler.
-
Çakışmaları azaltır: Anahtar alanının farklı kısımlarına yapılan değişiklikler genellikle paralel gerçekleşir ve paralellik ile yapı boyutu arasında ayarlama yapmayı sağlayan esneklikler sunar.
-
Tüm işlemler, ne kadar süreceği ve ne kadar işlem & I/O gas tüketeceği konusunda garantili üst sınırlar taşır; bu da onu çeşitli kullanım senaryoları için güvenli hale getirir.
– Tek dikkat edilmesi gereken nokta, iade edilebilir saklama ücretidir. Varsayılan olarak, haritanın yeni resource’lara büyümesini gerektiren bir işlem, bu alanlar için saklama ücreti ödemek zorundadır. Ancak uygulama, bu ücretlerin önceden ödenmesini ve öğeler eklenip çıkarıldıkça bu saklama alanlarının yeniden kullanılmasını sağlayacak bir seçenek sunar. Bu sayede, uygulamalar tamamen öngörülebilir bir gas maliyeti elde edebilir. -
Eğer anahtar/değer çifti, haritanın yapılandırıldığı boyut sınırları içindeyse, ekleme işlemleri hiçbir zaman öngörülemeyen şekilde başarısız olmaz, çünkü harita kaynak boyut sınırlarını dahili olarak anlar ve yönetir.
Bu yapı, mevcut uygulaması çeşitli sınırlamalara sahip olan SmartTable
ile karşılaştırıldığında oldukça farklıdır:
-
Çakışmalar, performansı keyfi şekilde düşürebilir.
-
Resource sınırlarını anlamaz veya yönetmez, bu nedenle bazı anahtarların haritaya eklenemediği durumlara yol açabilir.
-
Herhangi iki değişiklik işlemi birbirleriyle çakışır, bu da onu kullanan her iş yükünü tamamen sıralı hale getirir.
İşlevsel eşitlik, geliştirilmiş performans ve daha iyi davranış biçimi sayesinde, BigOrderedMap
, SmartTable
’ın yerini tamamen alır ve onu geride bırakır.
Performans açısından iki şeyi ölçtük: Büyük ölçekli kullanımda performansı nasıl, küçük ölçekli kullanımda performansı nasıl…
Büyük Ölçekli Performans
En dikkat çekici olanı: performansı büyük ölçekte test ettik ve SmartTable
ile kıyasladık — yani önceki hash tabanlı, sınırsız anahtar-değer haritası uygulamasıyla. Testte her iki yapıya da 1 milyon anahtar ekledik ve sıralı işlem performansını ölçtük. Elde ettiğimiz sonuçlar şöyle:
Bu test, anahtar/değer çiftleri küçük olduğunda, BigOrderedMap
’in daha verimli bir saklama yapısına sahip olduğunu gösteriyor; çünkü SmartTable
, anahtar ve değere ek olarak ayrıca bir hash değeri de saklar. Ayrıca, daha fazla öğeyi tek bir “bucket” içinde tutarak saklama maliyetini optimize ettiğimizde, 1 milyon anahtar üzerinde bile daha yüksek performans gösteriyor. Bucket boyutunu küçülttüğümüzde SmartTable
daha rekabetçi hale geliyor, ancak bu kez saklama maliyeti ciddi şekilde artıyor.
Not: Karşılaştırma adil olması için tek iş parçacığı (single thread) üzerinde yapılmıştır; çünkü SmartTable
paralel çalışmaz. Öte yandan BigOrderedMap
paralel çalışabilir ve daha fazla iş parçacığında çalıştırıldığında çok daha yüksek işlem kapasitesi sunar.
Küçük Ölçekli Performans
Ayrıca, verilerin tek bir resource içine sığıp sığmayacağının bilinmediği durumlarda, sadece OrderedMap
yerine BigOrderedMap
kullanmanın getireceği ek yükü görmek için küçük ölçekli kullanımda da performans ölçtük.
Burada, farklı boyutlardaki bir haritaya tek bir ekleme + silme işlemi için geçen mikrosaniyeyi ölçüyoruz.
Sonuçlar şunu gösteriyor: Harita, her şeyi tek bir resource içinde tutacak şekilde yapılandırıldığında, ek yük 2 katın altında kalıyor. Paralellik için optimize edilmiş bir yapılandırmada ise, tekil işlemlerin ek yükü hâlâ makul kalıyor (yaklaşık 2–3 katı). Ancak her durumda, veri kümesi büyüdükçe ölçeklenebilirlik son derece güçlü.
Alternatifler
Genel olarak, sıralı olmayan (unordered) haritalar, sıralı olanlara göre daha yüksek performans sağlayabilir; çünkü daha fazla serbestliğe sahiptirler. Ancak:
-
İşlemlerin sonradan tanımlanabildiği durumlarda, çakışmalarda öngörülebilir performans sunan hash tabanlı bir yapı kurmak oldukça karmaşıktır.
-
Yapılan değerlendirmelerin de gösterdiği üzere, karşılaştırma (comparison) işlemleri
—hashing’e kıyasla— ve memcopy işlemlerinin verimliliği sayesinde, performans oldukça karşılaştırılabilir düzeylere ulaşabiliyor. Bu da sıralı olmayan ayrı versiyonlara olan ihtiyacı azaltıyor.
Kullanım
Bu yapıları kullanmaya başlamak istiyorsanız, kullanım kılavuzuna veya kod belgelerine göz atabilirsiniz (ordered_map.move ve big_ordered_map.move dosyaları).
Yerel Fonksiyonlar
Değer manipülasyonu için, işlevselliği ve performansı artıran bir dizi yeni yerel (native) fonksiyon ekledik:
-
mem::swap
– İki değiştirilebilir referansın içeriğini takas eder. Bu sayede,copy+drop
yeteneği olmayan struct ve enum’ların alanlarını, tüm yapıları yıkıp yeniden oluşturmadan değiştirmek mümkün olur — bu da değiştirilebilir koleksiyonların oluşturulmasını kolaylaştırır. -
vector::move_range
– Belirli bir pozisyonda, bir vektörden diğerine bir dizi öğeyi verimli şekilde taşır, kalan öğelerin sırasını korur. -
cmp::compare
– Aynı türdeki iki Move değeri arasında karşılaştırma yapar. Bu, yukarıda bahsedilen Ordered Map’ler, sıralama, ikili arama araçları, öncelik kuyrukları gibi genel koleksiyonlar ve yardımcı işlevlerin oluşturulmasını mümkün kılar — ki bu daha önce mümkün değildi. -
bcs::constant_serialized_size
– Eğer bir türün, BCS formatında bilinen sabit (her zaman aynı, örnekten bağımsız) bir serileştirilmiş boyutu varsa, bu bilgiye erişilmesini sağlar. Bu da, bu türler için veri yapıları içinde özel optimizasyonların önünü açar.
Vektör Performans İyileştirmeleri
Vektörler üzerinde yapılan birçok yaygın işlem (örneğin: insert
, remove
, append
, trim
) vektörün bir kısmının kaydırılmasını gerektirir. Şu anda yalnızca bireysel öğeler vector::swap
ile değiştirilebiliyor ve bu nedenle tüm bu işlemler Move içerisinde, öğeleri tek tek takas ederek uygulanıyor.
Çoğu programlama dilinde bu tür işlemler, (çalıştıkları donanım için optimize edilmiş) son derece verimli memcopy
fonksiyonları aracılığıyla gerçekleştirilir. Örneğin Rust’ta, Vec
işlemleri, bu tür taşıma işlemlerini etkin bir şekilde gerçekleştirmek için ptr::copy_nonoverlapping
fonksiyonunu kullanır. Biz de burada şu yeni yerel fonksiyonu sunuyoruz: fun range_move<T>(from: &mut vector<T>, removal_position: u64, length: u64, to: &mut vector<T>, insert_position: u64);
Bu fonksiyon, belirli bir pozisyonda bir vektörden diğerine bir dizi öğeyi taşır ve kalan öğelerin sırasını korur. Bu tek bir metod, yukarıda bahsi geçen dört işlemi (ve daha fazlasını) genelleyerek kapsar.
Performans (ve buna bağlı olarak gas maliyeti) iyileştirmeleri şunlardır:
Bugün Denemeye Başlayın
Ordered Maps, Big Ordered Maps ve yeni yerel fonksiyonların tanıtılmasıyla birlikte, Aptos Framework, performans, ölçeklenebilirlik ve geliştirici deneyimi alanlarında ilerlemeye devam ediyor.
Bu yeni koleksiyonlar, hem küçük ölçekli hem de büyük ölçekli uygulamalar için öngörülebilir performans, verimli gas kullanımı ve esneklik sunar — destekleyici temel yapılar (primitives) ise, yüksek performanslı veri yapılarınızı kendiniz oluşturmayı her zamankinden kolay hale getirir. İster bir DeFi protokolü, ister bir indeksleyici, ister veri yoğunluklu akıllı kontratlar geliştiriyor olun, bu araçlar size daha az yükle, daha fazla kontrolle, daha fazlasını yapma gücü sağlar.