Lazy<T>
Kendi kod performansımı artırmak (ve bu konuda biraz daha fazla bilgi edinmek) için özellikleri kullanarak düşünüyor . Buraya ne zaman kullanılacağına dair cevaplar aramaya geldim ama gittiğim her yerde şöyle ifadeler var gibi görünüyor:
Büyük veya kaynak yoğun bir nesnenin oluşturulmasını veya kaynak yoğun bir görevin yürütülmesini ertelemek için, özellikle de programın ömrü boyunca bu tür bir oluşturma veya yürütme gerçekleşmeyebiliyorsa, tembel başlatma kullanın.
adlı MSDN Lazy <T> Sınıf
Biraz kafam karıştı çünkü çizgiyi nereye çizeceğimden emin değilim. Örneğin, doğrusal enterpolasyonu oldukça hızlı bir hesaplama olarak görüyorum, ancak yapmam gerekmiyorsa, tembel başlatma, bunu yapmaktan kaçınmama yardımcı olabilir ve buna değer mi?
Sonunda kendi testimi denemeye karar verdim ve sonuçları burada paylaşacağımı düşündüm. Ne yazık ki bu tür testleri yaparken gerçekten uzman değilim ve bu yüzden iyileştirmeler öneren yorumlar almaktan mutluluk duyuyorum.
Açıklama
Benim durumum için, özellikle Lazy Properties kodumun bir çok enterpolasyon (çoğu kullanılmayan) yapan bir bölümünü geliştirmeye yardımcı olup olmadığını görmek ilgimi çekti ve bu yüzden 3 yaklaşımları karşılaştıran bir test oluşturduk.
Her yaklaşım için 20 test özelliğine (onlara t-özellikleri diyelim) sahip ayrı bir test sınıfı oluşturdum.
- GetInterp Class: Bir t özelliği her alındığında doğrusal enterpolasyonu çalıştırır.
- InitInterp Class: Yapıcıdaki her biri için doğrusal enterpolasyonu çalıştırarak t özelliklerini başlatır. Get sadece bir çift döndürür.
- InitLazy Class: Doğrusal enterpolasyon, özellik ilk alındığında bir kez çalıştırılacak şekilde t özelliklerini Lazy özellikleri olarak ayarlar. Müteakip kazanımlar sadece hesaplanmış bir çifte dönmelidir.
Test sonuçları ms cinsinden ölçülür ve ortalama 50 örnekleme veya 20 özellik elde etme ortalamasıdır. Her test daha sonra 5 kez gerçekleştirildi.
Test 1 Sonuçları: Örnekleme (ortalama 50 örnekleme)
Class 1 2 3 4 5 Avg %
------------------------------------------------------------------------
GetInterp 0.005668 0.005722 0.006704 0.006652 0.005572 0.0060636 6.72
InitInterp 0.08481 0.084908 0.099328 0.098626 0.083774 0.0902892 100.00
InitLazy 0.058436 0.05891 0.068046 0.068108 0.060648 0.0628296 69.59
Test 2 Sonuçları: İlk Getir (ortalama 20 mülk alır)
Class 1 2 3 4 5 Avg %
------------------------------------------------------------------------
GetInterp 0.263 0.268725 0.31373 0.263745 0.279675 0.277775 54.38
InitInterp 0.16316 0.161845 0.18675 0.163535 0.173625 0.169783 33.24
InitLazy 0.46932 0.55299 0.54726 0.47878 0.505635 0.510797 100.00
Test 3 Sonuçları: İkinci Getir (ortalama 20 mülk alır)
Class 1 2 3 4 5 Avg %
------------------------------------------------------------------------
GetInterp 0.08184 0.129325 0.112035 0.097575 0.098695 0.103894 85.30
InitInterp 0.102755 0.128865 0.111335 0.10137 0.106045 0.110074 90.37
InitLazy 0.19603 0.105715 0.107975 0.10034 0.098935 0.121799 100.00
Gözlemler
GetInterp
beklendiği gibi somutlaştırmak en hızlısıdır çünkü hiçbir şey yapmaz. tembel özellikler InitLazy
oluşturmanın InitInterp
getirdiği yükün doğrusal enterpolasyon hesaplamamdan daha hızlı olduğunu düşündürmekten daha hızlıdır. Bununla birlikte, burada biraz kafam karıştı çünkü InitInterp
20 doğrusal enterpolasyon yapmalı (t özelliklerini ayarlamak için), ancak GetInterp
sadece bir doğrusal enterpolasyon yapmak için 0.28 ms sürdüğüne kıyasla (test 1) sadece 0.09 ms sürüyor ilk kez (test 2) ve ikinci kez yapmak için 0.1 msn (test 3).
İlk InitLazy
kez GetInterp
bir mülk edinmekten neredeyse 2 kat daha uzun sürer InitInterp
, en hızlısıdır, çünkü örnekleme sırasında özelliklerini doldurur. (En azından yapması gereken buydu ama neden örnekleme tek bir doğrusal enterpolasyondan çok daha hızlıydı? Bu enterpolasyonları tam olarak ne zaman yapıyor?)
Ne yazık ki testlerimde bazı otomatik kod optimizasyonu var gibi görünüyor. Bu almalı GetInterp
bir özellik o ikinci kez yaptığı gibi ilk kez almak için aynı zamanda, ancak daha hızlı daha fazla 2 kata gösteriyor. Bu optimizasyon aynı zamanda diğer sınıfları da etkiliyor gibi gözüküyor çünkü hepsi test 3 için aynı miktarda zaman alıyor. Ancak, bu tür optimizasyonlar kendi üretim kodumda da önemli bir husus olabilir.
Sonuçlar
Bazı sonuçlar beklendiği gibi olsa da, muhtemelen kod optimizasyonları nedeniyle çok ilginç beklenmedik sonuçlar da vardır. Yapıcıda çok fazla iş yapıyormuş gibi görünen sınıflar için bile, örnekleme sonuçları, çift özellik elde edilmesine kıyasla, hala çok hızlı oluşturulabileceğini gösteriyor. Bu alandaki uzmanlar daha ayrıntılı bir şekilde yorum yapabilir ve araştırabilirken, kişisel hissim, orada ne tür bir optimizasyonun olabileceğini incelemek için bu testi tekrar yapmam gerektiğidir. Ancak, InitInterp
bunun bir yol olabileceğini umuyorum.
get { if (foo == null) foo = new Foo(); return foo; }
. Ve onu kullanmak için olası yerler var ...