|  | 
        
            | 
                    
                        | Kod Optimizasyonu ve "volatile" Anahtar Sözcüğü |  |  
                        | 
	
    
		
            | Gönderiliyor lütfen bekleyin... | 
 |  | 
        
            | Bu yazıda C#'ın önemli 
			ama tam olarak neden kullanıldığı bazı profesyonel programcılar tarafından bile 
			pek fazla bilinmeyen bir anahtar sözcük olan volatile üzerinde duracağız. 
 Bir çok popüler derleyici sizin isteğiniz dışında kodunuzun işleyiş mantığına 
			müdahale edebilmektedir. Bu müdahalenin en bilinen sebeplerinden birisi 
			uygulumanızın kod boyutunu küçültmek yada uygulamanızın çalışma zamanını 
			düşürmektir. Aslında biz bu işlemlerin tamamına birden optimizasyon da 
			diyebiliriz. Zira hemen hemen bütün derleyicilerin optimizasyon işleminin 
			yapılıp yapılmayacağını belirten bir parametresi vardır. C# derleyicisi için bu 
			parametre /optimize yada kısaca /o şeklindedir.
 
 Peki optimizastondan neyi anlamalıyız? Genel olarak iki farklı şekilde 
			optimizasyondan bahsetmek mümkündür. Birincisi daha henüz derleme 
			aşamasındayken programcının gözünden kaçan bazı gereksiz bildirimlerin veya 
			tanımlamaların derleyici tarafından derlenecek koda dahil edilmemesi ile 
			olabilir. Örneğin hiç kullanmadığınız bir değişken için bellekte bir alan 
			tahsis edilmesinin hiç bir gereği yoktur. Bu yüzden hiç bir yerde kullanılmayan 
			değişkenlerin derleyiciniz tarafından derleme modülüne iletilmemesi bir 
			optimizasyon olarak görülmektedir. Bu tip optimizasyon kapsamı içinde ele 
			alınabilecek diğer bir örnek ise aşağıdaki kod parçası ile gösterilmiştir.
 
 Not : Aşağıdaki kodun bilinçsiz yada dalgın bir programcı tarafından yazıldğını 
			varsayıyoruz.
 
 
 
			
				| int
							a = 0; 
 while(a != 0)
 {
 a = 2 ;
 a = 0 ;
 }
 
 
 |  Yukarıdaki kodda akış hiç bir zaman while bloğunun içine gelmeyecektir. Ve 
			üstelik eğer a değişkeni farklı bir iş parçacığı(thread) tarafından while 
			bloğuna girmeden değiştirilip akış while bloğuna girse bile a değişkeni while 
			bloğu içinde tekrar eski sabit değerine atanıyor. Dolayısıyla while bloğunda 
			bulunan kodların çalıştırılabilir uygulama dosyasının boyutunu büyütmekten 
			başka bir işe yaramayacağı açıktır. O halde burda insan üstü bir mekanizmanın 
			devreye girip kodu optimize etmesi gerekir. Bu mekanizma elbetteki derleyicinin 
			optimizasyon işine yarayan parametresidir. Optimizasyon işleminde derleyiciden 
			derleyiciye fark olmasına rağmen yukarıdaki kod parçasının geebileceği en 
			optimum biçim aşağıda gösterildiği gibidir.
 
 
 
			
				| int
							a = 0; 
 while(a != 0)
 {
 
 }
 
 
 |  Diğer bir optimizasyon biçimi ise derleyicinin değişkenlerin elde edilmesinde 
				yada tekrar yazılmasında belleğin yada işlemcinin tercih edilmesi ile 
				ilgilidir. Bu noktada mikroişlemciler ile ilgili kısa bir bilgi vermekte fayda 
				var : Kaynak kodumuz çalıştırılabilir durumdayken aslında makine koduna 
				çevrilmiştir. Bu komutlar daha önceden mikroişlemcilerde elektronik düzeyde 
				programlandıkları için bu komutlar tek tek mikroişlemcide kolaylıkla icra 
				edilir. Mikroişlemciler aynı anda tek bir iş yapabileceği için yapacağı 
				işlemler içinde kullandığı değişkenleri her defasında bellekten almak yerine 
				daha hızlı olması açısından mikroişlemcideki data register dediğimiz 
				kayıtçılarda tutar. Bu register dediğimiz bölümlerin sınırlı sayıda bulunduğunu 
				belirtmek gerekir. Dolayısıyla bellekte bulunan uygulamamızın ihtiyacına göre 
				daha doğrusu icra edilecek bir sonraki makine kodunun çeşidine göre işlemci 
				bellekten ilgili değişkenleri register'larına yükler ve ilgili komutunu 
				çalıştırır. Doğaldır ki bir değerin mikroişlemci tarafından belleğe(ram) 
				yazılması ile mikroişlemcideki register bölgesine yazılması arasında dağlar 
				kadar fark vardır. Bu fark elbette hız faktörüdür. İşte tam bu noktada ikinci 
				tip optimizasyon kuralını tanımlayabiliriz. Derleyici öyle bloklara 
				rastlayabilir ki, bu bloklar içinde bulunan bir değişkenin değerini her 
				defasında bellekten okuyacağına bu değişkenin değerini bir defaya mahsus olmak 
				üzere mikroişlemcinin ilgili register bölgesine bölgesine kaydeder ve sonraki 
				okumalarda işlemci bellek yerine bu register bölgesini kullanır. Böylece 
				kodunuzun çalışma süresinde önemli sayılabilecek bir azalma görülür. Elbetteki 
				bu optimizasyon işleminin yüzlerce kez tekrarlandığını varsayarak bu sonuca 
				varıyoruz.
 
 Yukarıda değişken okuma ile ilgili söylediklerimin aynısı bir değişkenin 
				değerini değiştirmek için de geçerli olduğunu belirtmeliyim. Yani siz 
				programınızın 10. satırında bir değişkenin değerini bir değerden başka bir 
				değer çektiğiniz halde derleyici bu işlemi 15.satırda yapabilir. Bu durumda 15. 
				satıra kadar o değişkenin kullanılmadığı yorumunu yapabiliriz. Bu şekilde 
				mikroişlemcinin belleğe yazma işlemi geciktirilerek belli ölçüde optimizasyon 
				sağlanır. Tabi bu optimizasyonun ölçüsü tamamen mikroişlemcinin o anki durumuna 
				bağlıdır.
 
 Buraya kadar herşey normal. Bir de madolyonun öteki yüzüne bakalım. Bildiğiniz 
				üzere uygulamalar genellikle çoklu iş parçacıklarından(multi thread) ve 
				proseslerden oluşur. Her bir proses diğer bir proses teki değişkene işletim 
				sisteminin izin verdiği ölçüde erişip üzerinde işlemler yapabilir. Aynı şekilde 
				bir iş parçacığıda diğer bir iş parçacığında bulunan değişkene erişip üzerinde 
				çeşitli işlemler yapabilir. Peki bunun bizim optimizasyon kurllarımızla 
				bağlantısı ne? Şöyle ki : derleyici bir değişkenin değerinin farklı bir iş 
				parçacağı tarafından yada farklı bir proses tarafından işleneceği üzerinde 
				durmaz. Bu tamamen işletim sisteminin yönetimindedir. Hal böyleyken bizim 
				yukarıda bahsettiğimiz ikinci optimizasyon tipi bazı durumlarda yarar 
				getireceğiniz zarar getirebilir. Zira optimizasyon adına bir değişkenin 
				değerini her defasında bellekten okuma yerine mikroişlemcideki ilgili register 
				dan okurken o anda farklı bir iş parçacağı yada farklı bir proses hatta ve 
				hatta işletim sistemi sizin erişmeye çalıştığınız değişkenin değerini sizin 
				uygulamanızın mantığına göre değiştirebilir. Bu durumda siz o değişkenin son 
				halini kullanmamış olursunuz. Dolayısıyla programınızda farklı thread lar yada 
					prosesler arasında paylaşılan veya işletim sistemi tarafından değiştirilmesi 
					muhtemel olan değişkenlerinizi optimizasyon kuralına tabi tutmamanız gerekir. 
				Peki bunu nasıl başaracağız?
 
 volatile anahtar 
				sözcüğü burada imdadımıza yetişiyor. Bir değişkeni volatile anahtar sözcüğü ile 
				bildirdiğiniz takdirde derleyicinizin optimizasyon ile ilgili parametresini 
				açık tutsanız bile ilgili değişken yukarıda bahsi geçen tehlikeli optimizasyon 
				kurallarına tabi tutulmayacaktır. Yani volatile ile bildirilen değişkenlere 
				programın akışı sırasında her ihtiyaç duyulduğunda değişkenin gerçek yeri olan 
				belleğe başvurulur. Aynı şekilde bir değişkene yeni bir değer yazılacağı zaman 
				bu yazma işlemi hiç geciktirilmeden bellekteki yerine yazılır. Böylece volatile 
				ile bildirilen değişkenler farklı iş parçacıkları yada prosesler tarafından 
				ortak kullanılıyor olsada programın akışı içerisinde her zaman son versiyonu 
				elde edilecektir. Çünkü bu değişkenlerin değeri her defasında bellekten 
				çekilir. Her ne kadar optimizasyondan taviz verme zorunda kalsak ta böylece 
				uygulamalarımızda çıkabilecek olası bugların(böcek) önüne geçmiş oluruz.
 
 volatile, C# dilindeki 
				anahtar sözcüklerden biridir. Üye değişken bildirimi ile birlikte kullanılır. 
				volatile anahtar sözcüğü yalnızca aşağıdaki değişken tipleri ile birlikte 
				kullanılabilir.
 
 
 
			volatile anahtar 
				sözcüğünün kullanımına bazı örnekler verelim :
				Herhangi bir referans 
					tipindeki değişken ile
 
				byte, sbyte, short, 
					ushort, int, uint, char, float yada bool. türünden olan değişkenler ile
 
				byte, sbyte, short, 
					ushort, int, yada uint türünden semboller içeren numaralandırmalar(enums) ile
					
 
				unsafe modda iken 
					herhangi bir gösterici türü ile 
 
 
 
			Microsoft'un resmi 
				dökümanlarında(MSDN) verilen bir örneği buraya taşıyarak ne gibi durumlarda 
				volatile anahtar sözcüğüne ihtiyaç duyacabileceğimizi görelim.
				| public static volatile
							int a; 
 public volatile bool a;
 
 public volatile int* a;
 
 ....
 
 
 |  
 
 
			Yukarıdaki örnek 
				programdaki püf nokta finished isimli değişkenin ana thread ve ana thread 
				içinde başlatılan yeni thread tarafından ortak kullanılan bir değişken 
				olmasıdır. Eğer finished değişkeni volatile olarak bildirilmemiş olsaydı, akış 
				thread2 metoduna gelmiş olmasına rağmen Main metodu içindeki if bloğu 
				çalıştırılmayabilirdi. Çünkü derleyici ana thread içinden finished 
				değişkeninine tampolanmış bir bölgeden(register) erişebilir. Bu durumda 
				finished değişkeninin gerçek değeri true olmasına rağmen ana thread de finished 
				değişkeni halen false olarak ele alınır. Bu yüzden finished değişkeninin her 
				durumda son versiyonunu elde etmek için bu değişken volatile anahtar sözcüğü 
				ile bildirilmiştir.
				| using
							System; using System.Threading;
 
 class
							Test
 {
 public static int result;
 public static volatile bool
							finished;
 
 static 
								void Thread2()
 {
 result = 143;
 finished = true;
 }
 
 static void Main()
 {
 finished = false;
 new
							Thread(new ThreadStart(Thread2)).Start();
 
 for
							(;;)
 {
 if
							(finished)
 {
 Console.WriteLine("result 
							= {0}", result);
 return;
 }
 }
 }
 }
 
 
 |  
 volatile anahtar sözcüğünün kullanımına bir örnek daha verelim. Belli bir anda 
				bir sınıftan sadece bir nesnenin oluşmasını sağlayan 
					Singleton desenini daha önceki bir makalemde ele almıştım. Bu konu ile 
				ilgili bilgi eksikliğiniz varsa ilgili makaleyi okumanızı tavsiye ederim. Bahsi 
				geçen makalede verilen desenin bir uygulaması aşağıda ki gibi yeniden 
				yazılmıştır.
 
 
 
			
				Bu örnekte 
				SingletonDeseni nesnesinin belli bir anda tekil olarak bulunduğunu çok kanallı 
				uygulamalar içinde geçerli kılmak için bu nesne volatile olarak bildirilmiştir. 
				Üstelik bu örnekte farklı bir prosesin müdahalesi olsa bile bu nesneden ancak 
				ve ancak bir adet yaratılacaktır.
					| public
									class SingletonDeseni {
 private 
        static volatile
							SingletonDeseni nesne;
 
 private static Object kanalKontrol 
								= new Object;
 
 private SingletonDeseni()
 {
 
 }
 
 public static
								Singleton Nesne()
 {
 if(nesne 
													== null)
 {
 lock(kanalKontrol)
 {
 if(nesne 
																															== null)
 {
 nesne 
																																			= new SingletonDeseni();
 }
 }
 }
 
 return
								nesne;
 }
 }
 
 
 |  
 Son olarak volatile 
				kelimesinin sözlük anlamı üzerinde durmak istiyorum. İki yıl önce İngilizce'den 
				Türkçe'ye çevrilmiş bir Visual C++ kitabını okuduğumda volatile ile bildirilmiş 
				değişkenlerden oynak(!) değişkenler diye bahsedildiğine şahit oldum. İlk başta 
				bu ilginç kullanım bana birşey ifade etmedi ama hislerimin yardımıyla aslında 
				yazarın volatile dan bahsettiğine karar verdim. Sizde takdir edersiniz ki 
				yukarıda anlattıklarımız ile "oynak" kelimesi arasında pek bir bağ 
				bulunmamaktadır. Kitabın çevirisini yapan yazar muhtemelen bir programcı değil 
				bir çevirmendi. Çünkü eğer iyi bir programcı olsaydı oynak kelimesi yerine daha 
				uygun bir kelime seçilebilirdi. volatile'ın sözlük anlamı "uçucu olan", "buhar 
				olan" anlamına gelmektedir. Ancak ben henüz volatile sözcüğüne kendi 
				mesleğimizle ilgili uygun bir karşılık bulamadım. Bu konuda daha önce 
						cdili ve cdernek
				isimli iki yahoo grubunda çeşitli tartışmalar olmuştur. Bu gruplara üye olarak 
				ilgili tartışmalarda geçen konuşmaları okumanızı öneririm. Eğer sizin de bu 
				konuda önerileriniz varsa bizimle paylaşırsanız seviniriz.
 
 Umarım faydalı bir yazı olmuştur. Herkese iyi çalışmalar...
 
 
 
                Makale:Kod Optimizasyonu ve "volatile" Anahtar Sözcüğü C#, Visual C# ve .NET Sefer Algan
 | 
        
            |  | 
        
            |  | 
        
            | 
                    
                        
                            
                        
                            Eklenen Son 10 
                            Bu Konuda Geçmiş 10 
                        
                            Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
                         
                            Son Eklenen 10 Makale Yükleniyor
                         
                            Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
                         | 
        
            |  |