Garbage Collector’ ınstandart yaklaşımla çalışma sistemi tüm Managed kod uygulamageliştiricilerinde bildiği üzere şu şekildedir :
Obje instance’ ının belleğin stack bölgesi üzerinde herhangi birreferensının olmaması objenin Garbage Collector’ ın hedefi halinegeldiği ; başka bir ifade biçimiyle “çöp” durumuna geldiğini ifadeetmektedir. Garbage Collector Stack üzerinde referansını bulamadığıobjeleri mümkün olan en kısa ve en mantıklı zaman süreci içerisinde –kibu noktada altını çizerek belirtmemiz gerekirki Garbage Collector’ ınbir çöpü ne zaman toplayacağı kesinlikle ama kesinlikle belli değildir-toplamaktadır.
Garbage Collector’ ın (yazımızın bundan sonraki kısmında GarbageCollector yerine GC olarak ifade edilecektir) bu sistemi göz önündebulundurulduğunda bellek bakımından kısıtlı olarak tasarlanmış mobilcihazlarda geliştirdiğimiz uygulamalarda cihaz performansınıarttırabilmemiz açısından gerçekleştirebileceğimiz en mantıklı işlemartık ihtiyacımızın olmadığı objeleri çöp ; yani GC’ nin hedefi halinegetirmek ve gerektiği durumlarda bu objeleri tekrar oluşturmaktır.
Konunun kafamızda daha rahat canlanabilmesi açısındanörneklendirmemiz gerekirse 10000 adet DataRow’ un bulunduğu birDataTable objesi düşünelim. Bu obje hepimizinde tahmin edebileceğiüzere mobil cihazımızın “kısıtlı” belleği üzerinde ciddi bir yerkapyalacaktır. Muhtemel yaşanacak bir problem ise bu objenin bellektebulunduğu süreçte cihaz işlemlerinin yavaşlaması , çalıştırılmasıgereken uygulamaların hafıza yetersizliğinden çalıştırılamamasıdır.Peki uygulama süreci içerisinde bu objeye ihtiyaç duyuyor ve mobilcihaz üzerindeki bellek yönetimine birazda olsa katkıda bulunmakistiyorsak nasıl bir yöntem izleyebiliriz ?
Muhtemel cevap tahmin edebileceğimiz üzere şu olacaktır :
Uygulama süreci içerisinde bu objenin kullanıldığı arayüzler deaktifolduğu durumda bu obje çöp durumuna getirilebilir ; ihtiyaç olduğu herdurumda tekrar tekrar oluşturulabilir.
Bu noktada karşımıza daha farklı bir problem daha çıkmaktadır :
Ya bu objenin oluşturulma süreci saniyeler hatta dakikalar sürüyorise ? Böyle bir uygulama sürecinin her ne kadar performansı arttırdığıifade edilsede uygulama süreci içerisinde geçecek olan zaman başka birproblem doğurmaktadır.
Şöyle bir yapı olsada en azından belirli noktalarda tüm bu problemlere yanıt getirebilse ;
Objemiz kullanılmadığı durumlarda senaryoda bahsedildiği üzere GC’nin hedefi haline ; yani Çöp durumuna getirilse, tekrar geridönüldüğünde ise “eğer objemiz hala bellek üzerinden toplanmamış ise”tekrar geri getirilebilse ve “objenin tekrar oluşturulması için geçensüreç minimuma indirilse” çok daha mantıklı ve kullanılabilirliğiyüksek olmazmıydı ?
İşte bu noktada karşımıza .Net Compact Framework içerisinde bulunan WeakReference (Zayıf Referans) sınıfı çıkmaktadır !
WeakReference adından da anlaşılabileceği üzere birşeyleri –kimuhtemel cevap bellek üzerinde oluşturulmuş olan objeleri- refere etmeküzere geliştirilmiş .Net Compact Framework Base Library içerisindebulunan özellikle mobil cihazlar için çok faydalı olabilecek birsınıftır.
Çalışma mekanizması şu şekilde ifade edilmektedir :
Yazımızın başında da ifade ettiğimiz üzere GC bellek üzerindereferansı bulunmayan objeleri çöp olarak algılamakta ve toplamaktadır.Objenin çöp haline getirilmesi ile ilgili şekilde minik bir örnekverilmektedir :
Şekildende anlaşılabileceği üzere obje referansı null’ a eşitlenerekGC’ nin hedefi haline geliyor. Bu noktada yazımızın bundan sonrakikısmında WeakRefence ile karşılaştırabilmek açısından objenin Stacküzerinde bulunan referansından Strong Reference olarak bahsedilecektir.
Yazımıza kaldığımız yerden devam etmemiz gerekirse WeakReference’ ınçalışma yapısı gereği bellek üzerinde bulunan bir obje her ne kadarStrong Reference’ a sahip olmasa fakat WeakReference objesi tarafındanrefere edilse bile GC tarafından halen çöp olarak algılanmaktadır !Evet yanlış okumadınız, GC objeye referans eden başka bir obje bulsabile –ki bu noktada gözden kaçmaması gereken önemli noktalardanbirtanesi bu referansın Weak yani Zayıf bir referansın olmasıdır-objeye çöp muamelesi yapmaktadır.
Konunun daha rahat anlaşılabilmesi açısından anlaşılır bir örnekuygulama geliştirmeye geçmeden önce WeakReference sınıfını kendiMetaData’ sı üzerinden hızlı bir şekilde tanıyalım.
Şekilden de anlaşılabileceği üzere WeakReference sınıfı kalabalık bir member listesine sahip değildir.
Refere etmeyi düşündüğünüz objeyi atayabileceğiniz iki yapıcı metotve üç adet konu ile ilgili yararlanabileceğimiz property sisteminçalışması için fazlasıyla yeterli olmaktadır.
Bu noktada konunun daha rahat kavranabilmesi açısından reel birsenaryoyu kullanarak örnek bir mobil uygulaması geliştirmek çok dahamantıklı olacaktır.
Senaryo gereği hazırlayacak olduğumuz basit bir sınıfın StrongReferansını null’ a eşitlemeden önce WeakReference objesi üzerineatayacağız. Bir sonraki adımda ise ekrana farklı bir form belirli birsürenin geçmesini bekleyip bu süre sonunda ekrana getirdiğimiz formukapatacağız. Form kapandıktan hemen sonra kendi objemizin WeakReferenceobjesi üzerinden yok edilip edilmediğini kontrol edip yok edilmemiş iseStrong Reference’ a tekrar atayarak yaşam sürecine devam etmesinisağlayacağız.
Dikkat edilmesi gereken bir diğer nokta ise örneğimiz Visual Studio2008 Orcas BETA 2 sürümü üzerinde .Net Compact Framework 3.5 kullanarakWindows Mobile 6.0 işletim sistemi yüklü Mobil cihazlar içingeliştirilecektir.
Hiç vakit kaybetmeden örnek uygulamayı geliştirebilmek adına bir Mobil Uygulama projesi açıyoruz.
Projemizin adına ise UsingWeakReference değerini veriyoruz.
Bir sonraki adımda ise uygulama içerisine GC’ nin hedefi olabilmesi açısından örnek bir sınıf oluşturuyoruz.
Bir sonraki aşamada WeakReference yapısını inceleyebileceğimiz örneğin kod bloğunu uygulamanın yüklenme anına ekliyoruz.
Konunun daha rahat anlaşılabilmesi açısından satır numaralı üzerinden referanslar vererek makalemize devam edeceğiz.
Şekil üzerinden de anlaşılabileceği üzere 21-22 numaralı satırlardabir önceki adımda örneğin uygulanabilmesi açısından geliştirmişolduğumuz basit sınıfın instance’ ını alarak işe başlıyoruz.
25. satırda ise WeakReference instance’ ımızı oluşturuyoruz. Bunoktada WeakReference objesi oluşturulma aşamasında bizden refereedecek olduğu objenin kim olacağını istemektedir.
so ismindeki referansı WeakReference objesine vererek uygulamamıza devam ediyoruz.
28 satırda so referansını null’ a eşitliyoruz. Başka bir açıdanbakıdığında bir önceki aşamada oluşturulan SampleObject instance’ ınınormal şartlarda “çöp” durumuna getiriyoruz.
GC’ nin standart yaklaşımla göstermesi gereken davranış bu objeyi enuygun zaman süreci içerisinde bellek üzerinden temizlemesi olacaktır.
Ve işte şov bu noktada başlıyor ; uygulama süreci içerisinde belirlibir sürenin geçebilmesi bakımından proje içerisine eklediğimiz birform’ un instance’ ını ekrana “ShowDialog” metodu üzerindengetiriyoruz. Başka bir deyişle bu form kapanmadan uygulamanın anaekranının süreci kesinlikle devam etmeyecektir.
Açılan form üzerinden ne kadar vakit kaybedilirse, ana ekran’ a geridönüldüğünde objenin yok olma ihtimali doğru orantılı olarakartacaktır. Dolayısıyla form’ u ne kadar hızlı kapatırsak geridönüldüğünde objeye erişme ihtimali o kadar artacaktır.
Geri dönüldüğünde ise objenin hala toplanıp toplanmadığınıWeakReference instance’ ımızın IsAlive property’ si üzerindengörüntüleyeceğiz.
Değerin true gelmesi durumunda şekildeki kod bloğu üzerinden objeyi tekrardan hayata geçirebiliriz :
Hiç vakit kaybetmeden uygulamamızı çalıştıralım :
Uygun emülatörü seçtikten sonra Deploy’ a tıklıyoruz.
Ve işte uygulama ekranı karşımızda. Uygulama ana ekran’ ı yeniaçılan form ile gölgelenmektedir. Yeni açılan form üzerindeki button’ atıklayarak form’ u kapatıyoruz ve ana ekran’ a dönerek objenin yokedilip edilmediğini kontrol ediyoruz.
Upps ! Objemiz yok edilmiş ; başka bir açıdan bakıldığında GC’ nin objeyi toplamadan önceki sürecine erişemedik.
Yeni açılan form içerisine şekildeki kod’ u ekleyerek açılıp kapanma işlemi esnasında geçen süreyi minimum’ a indiriyoruz.
Başka bir yaklaşımla form açıldığı anda kapatılmakta, dolayısıylaana ekran’ a daha hızlı dönülmekte ve objenin yok edilme süreciniminimuma indirmekteyiz.
Uygulamayı bu şekilde tekrar çalıştırıyoruz :
İşte mutlu son ! Objemiz hala yaşıyor, Mesaj kutusunu kapatarak tekrar kaldığı yerden devam etmesini sağlıyoruz !
İşte objemizin referansı null’ a eşitlenmeden önceki son hali !
Bu makalemizde WeakReference kullanarak performanslı mobil cihazuygulamalarının nasıl geliştirileceği konusunda anlaşılır bir örnekgeliştirdik. Başka bir makalede daha görüşmek üzere.