Arkadaşlar merhaba,
Bugün bir çoğumuzun bildiği ama çoğu zaman dikkat etmediğimiz bir konuya dikkat çekmek istiyorum.Mutable(değişebilir) ve immutable(değişemez) tipler. Hangi veri tiplerimiz niçin bu özellikte, performansa etkileri ne şekilde bunlar üzerinde yorumlar yapacağız.
Örneklerim java üzerinden olacak. Ufak bir örnekle başlamadan önce String tipinin aslında bir karakterler dizisi olduğunu, bu veri tipinin primitive(ilkel) bir tipi olmadığını hatırlatma gereksinimi duyuyorum.
Bu örneğimizde string bir değişkenimize defalarca concatenating(bağlama) işlemi yapacağız.Iterasyon(tekrarlama) sayısını yüksek tuttum ki fark daha net anlaşılsın. Örnekte 100.000 kez, varolan bir stringin sonuna bir değer ekleme işlemi yapıyoruz. Bu işlem arasında geçen süreyi hesaplıyoruz.
Aynı işlemi bir de StringBuffer sınıfını kullanarak yapalım ve süreyi ölçelim.(İsmi B işlemi olsun)
Durumun aslını özetlemek gerekirse, concatenating(A) işleminde değişkenimiz üzerinde yapılan her işlem aslında yeni bir String değişken instance(örneği) almak anlamına geliyor. Yani klasik örnekle göstermek gerekirse
deneme +="cem";
new String(deneme+"cem");
işlemleri birebir aynı işlemler. Ben 100.000 kez bu işlemi tekrarladığımda her defasında büyüyen karakter dizim için dizinin sığabileceği boyutta bellekte alan aramaya çalışıyorum. Aynı zamanda tek kullanım yaratılıp sonrasında işi biten nesneyi de garbage collector'ın temizlemesine bırakıyorum. Yani ekstra iş yükü ekstra iş yükü. 100.000 kere yeni string yaratıp sonunda 1 tane string kazanıyorum.
Peki B işleminde ne yapıyoruz? StringBuffer sınıfı JDK1.0 ile gelen bir sınıf. Her append işleminde
Bugün bir çoğumuzun bildiği ama çoğu zaman dikkat etmediğimiz bir konuya dikkat çekmek istiyorum.Mutable(değişebilir) ve immutable(değişemez) tipler. Hangi veri tiplerimiz niçin bu özellikte, performansa etkileri ne şekilde bunlar üzerinde yorumlar yapacağız.
Örneklerim java üzerinden olacak. Ufak bir örnekle başlamadan önce String tipinin aslında bir karakterler dizisi olduğunu, bu veri tipinin primitive(ilkel) bir tipi olmadığını hatırlatma gereksinimi duyuyorum.
Bu örneğimizde string bir değişkenimize defalarca concatenating(bağlama) işlemi yapacağız.Iterasyon(tekrarlama) sayısını yüksek tuttum ki fark daha net anlaşılsın. Örnekte 100.000 kez, varolan bir stringin sonuna bir değer ekleme işlemi yapıyoruz. Bu işlem arasında geçen süreyi hesaplıyoruz.
Bu iterasyon için geçen süre yaklaşık 52.000ms. Bu işleme A işlemi ismini verelim.public class Test {public static void main(String[] args) {String deneme=null;long time=System.currentTimeMillis();for (int i = 0; i < 100000; i++) {deneme +=i;}System.out.println(System.currentTimeMillis() - time); // 52860ms}}
Aynı işlemi bir de StringBuffer sınıfını kullanarak yapalım ve süreyi ölçelim.(İsmi B işlemi olsun)
Arada nasıl oluyor da bu kadar büyük bir süre farkı oluyor? Birçoğunuzun String'in immutable bir tip olduğunu söylediğinizi duyar gibiyim. Peki nedir bu kavram, nasıl oluyor da StringBuffer çok daha hızlı bir şekilde bu işi gerçekleştiriyor?public class Test {public static void main(String[] args) {StringBuffer sb = new StringBuffer();long time=System.currentTimeMillis();for (int i = 0; i < 100000; i++) {sb.append(i);}System.out.println(System.currentTimeMillis() - time); // 7ms}}
Durumun aslını özetlemek gerekirse, concatenating(A) işleminde değişkenimiz üzerinde yapılan her işlem aslında yeni bir String değişken instance(örneği) almak anlamına geliyor. Yani klasik örnekle göstermek gerekirse
deneme +="cem";
new String(deneme+"cem");
işlemleri birebir aynı işlemler. Ben 100.000 kez bu işlemi tekrarladığımda her defasında büyüyen karakter dizim için dizinin sığabileceği boyutta bellekte alan aramaya çalışıyorum. Aynı zamanda tek kullanım yaratılıp sonrasında işi biten nesneyi de garbage collector'ın temizlemesine bırakıyorum. Yani ekstra iş yükü ekstra iş yükü. 100.000 kere yeni string yaratıp sonunda 1 tane string kazanıyorum.
Peki B işleminde ne yapıyoruz? StringBuffer sınıfı JDK1.0 ile gelen bir sınıf. Her append işleminde
sb.insert(sb.length(), [eklenecek string])
şeklinde işlem gerçekleştirilir. Özetle burada yapılan yeni bir string alıp değerleri orada tutmak değil, varolan stringin kapasitesi artırılıp sonuna insert edilmesidir. Kapasitenin artırılması JVM tarafından otomatik olarak gerçekleştirilmektedir. Bu işlem asenkron olarak işlemektedir.
Aynı işlemi thread safe olarak gerçekleştiren bir sınıf JDK 1.5 ile gelmiştir. Adı StringBuilder'dır. Dileyen inceleyebilir, senkron olarak çalışır. Senkronizasyon için harcanan süre sebebiyle StringBuffer'dan çok az bir miktar daha yavaştır. Concatenation'dan çok çok daha hızlı olduğunu yine hatırlatmakta fayda var.
Bir sonraki yazıda Java'da immutable-mutable olması açısından primitive veri tipleri, Object'ler ve referans yapıları hakkında bahsedeceğim.
Herkese bol kodlu günler.
alıntı: http://www.mehmetcemyucel.com/2012/01/mutable-immutable-types.html
Hiç yorum yok:
Yorum Gönder