Tembel başlatma nedir ve neden faydalıdır?


83

Nesnelerin tembel başlatılması nedir? Bunu nasıl yaparsınız ve avantajları nelerdir?

Yanıtlar:


105

Lazy Initialization, (potansiyel olarak pahalı) nesne oluşturmayı gerçekten ihtiyacınız olana kadar ertelediğiniz bir performans optimizasyonudur.

İyi bir örnek, önceden bir veritabanı bağlantısı oluşturmak değil, yalnızca veritabanından veri almanız gerekmeden hemen önce oluşturmaktır.

Bunu yapmanın temel nedeni, (genellikle) hiç ihtiyacınız yoksa nesneyi tamamen oluşturmaktan kaçınabilmenizdir.


39
Söylemeye gerek yok, ama her ihtimale karşı kaçırmış olması durumunda: Bunun bir optimizasyon olmasının nedeni, genellikle yaratımı yapmanıza gerek olmadığını fark etmeniz ve bilgisayar zaten meşgulken bazı işleri yapmaktan tasarruf edebilmenizdir. daha az meşgul olduğu bir zamana kadar.
Joel Coehoorn

İyi yorum. Fikrinizi birleştirmek için cevabı değiştirdim.
Bevan

çok iyi (ve farklı) bir kullanım durumu / kullanım nedeni Lazy, aşağıdaki SO sorusunda yayınlanmıştır: stackoverflow.com/a/15894928/4404962 bu öneri, çözmemiz gereken şeyi tam olarak çözdü - Lazytemel prensip olarak kullanarak
lev haikin

51

Diğerlerinin de belirttiği gibi, tembel başlatma, bir bileşen veya nesne kullanılana kadar başlatmayı geciktiriyor. Bir tembel başlatma görebilirsiniz çalışma zamanı uygulaması arasında YAGNI ilkesi - " You ain't gonna need it"

Geç başlatmanın uygulama açısından avantajları, kullanıcıların kullanmayacakları özellikler için başlatma süresini ödemek zorunda kalmamasıdır. Uygulamanızın her bileşenini önceden başlattığınızı varsayalım. Bu, potansiyel olarak uzun bir başlama süresi yaratabilir - uygulamanızın kullanıma hazır olması için kullanıcıların onlarca saniye veya dakika beklemesi gerekir. Asla kullanamayacakları veya hemen kullanamayacakları özelliklerin başlatılmasını bekliyor ve ödüyorlar.

Bunun yerine, bu bileşenleri kullanıma hazırlamayı ertelerseniz, uygulamanız çok daha hızlı başlayacaktır. Kullanıcı, diğer bileşenleri kullanırken yine de başlangıç ​​maliyetini ödemek zorunda kalacak, ancak bu maliyet, programın çalışması boyunca amortismana tabi tutulacak ve başlangıca yoğunlaştırılmayacaktır ve kullanıcı, bu nesnelerin başlatma süresini, oldukları özelliklerle ilişkilendirebilir. kullanarak.


Ne yazık ki sadece +1 verebildim! İyi mantık, BTW.
Rajendra Uppal

1
YAGNI, "buna [özelliğe, koda] ihtiyacınız olmayacak" anlamına gelir. Tembel başlatma, kendi içinde bir özellik olan bir optimizasyondur. Bunun tam tersi şekilde geçerli olduğunu söylemeyi tercih ederim: tembel başlatmaya ihtiyacınız olduğundan emin değilseniz, is, YAGNI kullanmayın.
Flavius

19

Tembel Başlatma, nesne gerçekten ilk kullanılana kadar nesne oluşturmayı erteleme kavramıdır. Düzgün kullanılırsa, önemli performans kazanımları sağlayabilir.

Kişisel olarak, .NET 2.0'da kendi elle çevrilmiş ORM'mi oluştururken Lazy Initialization kullandım. Koleksiyonlarımı veritabanından yüklerken, koleksiyondaki asıl öğeler tembel olarak başlatıldı. Bu, koleksiyonların hızlı bir şekilde oluşturulduğu anlamına geliyordu, ancak her nesne yalnızca ihtiyacım olduğunda yüklendi.

Singleton modeline aşina iseniz, muhtemelen eylemde tembel başlatma da görmüşsünüzdür.

public class SomeClassSingleton
{
    private static SomeClass _instance = null;

    private SomeClassSingleton()
    {
    }

    public static SomeClass GetInstance()
    {
        if(_instance == null)
            _instance = new SomeClassSingleton();

        return _instance;
    }
}

Bu durumda, SomeClass örneği, SomeClassSingleton tüketicisi tarafından ilk ihtiyaç duyulana kadar başlatılmaz.


Hızı biraz daha iyileştirmek için açık özel değişken ayarını 'null' olarak kaldırın;). Her neyse, gereksiz.
nicodemus13

güzel nokta, SomeClassSingleton, SomeClass'a eşit veya daha düşük bir sınıf olmalıdır
Fredrick Gauss

Herhangi birinin eski yanıtları okuyup okumadığını bilmiyorum ama özel statik get örneği yönteminin herkese açık olması gerektiğini varsayıyorum.
Biscuit128

@ Biscuit128 - Onları okuyorum ve evet olmalı. Başkasının hala okuması durumunda onu güncelledim.
Justin Niessner

_instance = new SomeClassSingleton () olmamalı; _instance = new SomeClass (); ? ya da farklı bir bakış açısıyla anlıyorum
ashishdhiman2007

6

Genel bilgi işlem terimleriyle 'tembel değerlendirme', gerçekten ihtiyacınız olana kadar bir şeyin işlemesini ertelemek anlamına gelir. Ana fikir, ihtiyaç duymadığınızda bazen maliyetli işlemlerden kaçınabileceğiniz veya kullanmadan önce değerin değişeceğidir.

Bunun basit bir örneği System.Exception.StackTrace'dir. Bu, bir istisnadaki dize özelliğidir, ancak siz ona erişene kadar aslında oluşturulmaz. Dahili olarak şöyle bir şey yapar:

String StackTrace{
  get{
    if(_stackTrace==null){
      _stackTrace = buildStackTrace();
    }
    return _stackTrace;
  }
}

Bu sizi, birisi onun ne olduğunu görmek isteyene kadar buildStackTrace'i çağırmanın ek yükünden kurtarır.

Özellikler, bu tür davranışları sağlamanın bir yoludur.


2
Doğru, ancak yine de birden çok iş parçacığı arasında bir istisnayı neden paylaşıyor olacağından emin değilim.
Dolphin

3

Burada , örnek kod ile Lazy Initialization hakkında bilgi edinebilirsiniz .

  • Oluşturması pahalı bir nesneye sahip olduğunuzda ve program onu ​​kullanmayabilir. Örneğin, belleğinizde, başlatılması için bir veritabanı bağlantısı gerektiren büyük bir Order nesneleri dizisi içeren bir Orders özelliğine sahip bir Müşteri nesnesine sahip olduğunuzu varsayın. Kullanıcı Siparişleri göstermeyi veya verileri bir hesaplamada kullanmayı asla istemezse, bunu oluşturmak için sistem belleğini veya hesaplama döngülerini kullanmak için hiçbir neden yoktur. Geç başlatma için Orders nesnesini bildirmek üzere Lazy'i kullanarak, nesne kullanılmadığında sistem kaynaklarının boşa harcanmasını önleyebilirsiniz.

  • Oluşturması pahalı olan bir nesneye sahip olduğunuzda ve yaratılmasını diğer pahalı işlemler tamamlanana kadar ertelemek istediğinizde. Örneğin, programınızın başladığında birkaç nesne örneğini yüklediğini, ancak bunlardan yalnızca bazılarının hemen gerekli olduğunu varsayalım. Gerekli olmayan nesnelerin başlatılmasını gerekli nesneler oluşturulana kadar erteleyerek programın başlangıç ​​performansını artırabilirsiniz.


3

Bir nesnenin tembel başlatılması, ilk kullanılana kadar yaratılmasının ertelenmesi anlamına gelir. (Bu konu için, tembel başlatma ve yavaş örnekleme terimleri eş anlamlıdır.) Tembel başlatma, öncelikle performansı artırmak, israflı hesaplamayı önlemek ve program belleği gereksinimlerini azaltmak için kullanılır. En yaygın senaryolar şunlardır:

Oluşturması pahalı bir nesneye sahip olduğunuzda ve program onu ​​kullanmayabilir. Örneğin, belleğinizde, başlatılması için bir veritabanı bağlantısı gerektiren büyük bir Order nesneleri dizisi içeren bir Orders özelliğine sahip bir Müşteri nesnesine sahip olduğunuzu varsayın. Kullanıcı Siparişleri göstermeyi veya verileri bir hesaplamada kullanmayı asla istemezse, bunu oluşturmak için sistem belleğini veya hesaplama döngülerini kullanmak için hiçbir neden yoktur. Geç başlatma için Orders nesnesini bildirmek üzere Lazy'i kullanarak, nesne kullanılmadığında sistem kaynaklarının boşa harcanmasını önleyebilirsiniz.

Oluşturması pahalı olan bir nesneye sahip olduğunuzda ve yaratılmasını diğer pahalı işlemler tamamlanana kadar ertelemek istediğinizde. Örneğin, programınızın başladığında birkaç nesne örneğini yüklediğini, ancak bunlardan yalnızca bazılarının hemen gerekli olduğunu varsayalım. Gerekli olmayan nesnelerin başlatılmasını gerekli nesneler oluşturulana kadar erteleyerek programın başlangıç ​​performansını artırabilirsiniz.

Geç başlatma gerçekleştirmek için kendi kodunuzu yazabilseniz de, bunun yerine Lazy kullanmanızı öneririz. Lazy ve ilgili türleri ayrıca iş parçacığı güvenliğini destekler ve tutarlı bir istisna yayma ilkesi sağlar.


2
//Lazy instantiation delays certain tasks. 
//It typically improves the startup time of a C# application.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LazyLoad
{
    class Program
    {
        static void Main(string[] args)
        {
            Lazy<MyClass> MyLazyClass = new Lazy<MyClass>(); // create lazy class
            Console.WriteLine("IsValueCreated = {0}",MyLazyClass.IsValueCreated); // print value to check if initialization is over

            MyClass sample = MyLazyClass.Value; // real value Creation Time
            Console.WriteLine("Length = {0}", sample.Length); // print array length

            Console.WriteLine("IsValueCreated = {0}", MyLazyClass.IsValueCreated); // print value to check if initialization is over
            Console.ReadLine();
        }
    }

    class MyClass
    {
        int[] array;
        public MyClass()
        {
            array = new int[10];

        }

        public int Length
        {
            get
            {
                return this.array.Length;
            }
        }
    }
}


// out put

// IsValueCreated = False
// Length = 10
// IsValueCreated = True

1

Şimdiye kadar lazy init hakkında anladığım gibi, program tüm verileri bir kez yüklemiyor / istemiyor. Örn. 'Den talep etmeden önce kullanımını bekler. bir SQL sunucusu.

Çok sayıda alt tablonun katıldığı büyük bir tablonun olduğu bir veritabanınız varsa ve "düzenle" ya da "ayrıntıları görüntüle" ye gitmedikçe diğer tablolardan birleştirilen ayrıntılara ihtiyacınız yoksa, Lazy Init. uygulamanın daha hızlı gitmesine ve önce ihtiyaç duyulan ayrıntı verilerini "tembel olarak yüklemesine" yardımcı olur.

SQL veya LINQ'da bu "ayarı", pr veritabanı modelinizde ayarlayabilirsiniz. veri elemanı.

Umarım bu sorunuz için mantıklıdır?

Bir web istemcisi (örneğin bir tarayıcı) aynı şeyi yapar. HTML'den sonra görüntüler "tembel yüklenir" ve doğru kullanıldığında AJAX da bir "tür tembel başlatma" dır.


1

Şimdiye kadar bahsedilen veritabanı örnekleri iyidir, ancak sadece veri erişim katmanıyla sınırlı değildir. Aynı ilkeleri, performansın veya hafızanın sorun olabileceği her duruma uygulayabilirsiniz. İyi bir örnek (.NET olmasa da), kullanıcının uçtan onu (ve ilişkili nesnelerini) fiilen yüklemek için bir pencere isteyene kadar bekleyebileceğiniz Cocoa'dadır. Bu, özellikle daha sonraki bir zamana kadar ihtiyaç duyulmayacak Tercihler pencereleri gibi şeyler hakkında konuşurken, bellek kullanımını azaltmaya ve ilk uygulama yüklemesini hızlandırmaya yardımcı olabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.