Jump to content

String Birlestirme Isleminde Dikkat Edilmesi Gerek


wmismail

Recommended Posts

String birlestirme işleminde dikkat edilmesi gerekenler

Tüm yazilimci arkadaşlara selamlar,

Bu yazimda string birlestirirken dikkat etmeniz gereken performansi etkileyen çok önemli bir konuya deginecegim.

Gelistirdigimiz uygulamalarda string tipini kullanmaktayiz, ve çogu zaman kurdugumuz algoritmalarda string degiskenlerini birbirine ekleriz.

Örnek vermek gerekirse ;

Bir server uygulamasinin client uygulamamiza network üzerinden bir metin dosyasi gönderdigini varsayalim.

Asagidaki kodu inceleyelim;

TcpClient tclA=new TcpClient();

tclA.Connect("localhost",80);

NetworkStream nstA=new NetworkStream(tclA);

StreamReader strA=new StreamReader(nstA);

StreamWriter stwA=new StreamWriter(nstA);

string strIncomingData="";

while (nstA.DataAvailable)

{

strIncomingData+=strA.ReadLine();

}

Network üzerinden gelen bilgi “strIncomingData+=strA.ReadLine()” komutu ile depolaniyor.

Ufak boyutlu dosyalarda bu işlem çok saglikli çalisacaktir.

Peki büyük boyutlu dosyalarda neden problem çikartir?

Sebebi CLR’nin string tipini hafizanin HEAP alaninda saklamasi ve bu tipin yeni değerinin atanmasi işleminde herseferinde HEAP bölgesinde yeni bir adres açmasi ve eski adresi tutmasidir.

1000000598_StackHeap.jpg

Evet her "strIncomingData+=strA.ReadLine()" komutunda bellegin heap alaninda yeni bir adres açilir ve bir önceki heap alani birakilir.

Bu ufak döngülerde veya ufak çapli dosyalarda problem yaratmayacak fakat örnegimizdeki gibi bir dosya transfer programinda performans problemleri yaratacaktir.

Peki nasıl olacakta HEAP'i doldurmayacagiz? .NET framework'ü bize stringbuider sinifini çözüm olarak sunmaktadir.

StringBuilder sinifi System.Text isimalaninda bulunmaktadir.

Asagidaki kod örnegini çalistirdiginizda size 2 yöntemden birini seçmenizi isteyecektir.

1 girdiginizde size ilk anlattigim standart yöntem ile 100.000 defa strA degiskenine herseferinde A harfini ekleyecektir.

Tabi bu arada işlemin baslangiç ve bitis saati ekrana yazilacaktir.

2 yi seçtiginizde ise ayni işlemi StringBuilder sinifini kullanarak yapacaktir.Bu sayede her atamada heap alaninda yeni bir alan açilmayacaktir.

using System;

using System.Text;

namespace StringConcentrationTip

{

class Class1

{

[sTAThread] static void Main(string[] args)

{

Console.WriteLine("1- Yöntem 1 ile 100.000 defa string birlestir.");

Console.WriteLine("2- Yöntem 2 ile 100.000 defa string birlestir.");

if (Console.ReadLine().ToString()=="1")

{

Console.WriteLine("--işlem yapiliyor--");

Console.WriteLine("Baslangiç: " + DateTime.Now.ToString());

string strA="";

for (int intA=0;intA<100000;intA++)

strA+="A";

Console.WriteLine("Bitis: " + DateTime.Now.ToString());

Console.WriteLine("--işlem bitti--");

}

else

{

Console.WriteLine("--işlem yapiliyor--");

Console.WriteLine("Baslangiç: " + DateTime.Now.ToString());

StringBuilder stbA=new StringBuilder();

for (int intA=0;intA<100000;intA++)

stbA.Append("A");

Console.WriteLine("Bitis: " + DateTime.Now.ToString());

Console.WriteLine("--işlem bitti--");

}

}

}

}

Çok fark var degilmi?

(Bu arada heap alaninda açilip birakilan kullanilmayan adreslere ne olacak diye soranlar için ; Garbage Collector belirsiz bir zamanda heap'i temizleyecektir.)

Süper... o zaman bütün string işlemlerimizde stringbuilder'i kullanalim?

Evet ben de ilk denedigim zaman farki görüp heryerde bu sinifi kullanmaya karar vermistim.Fakat yazilim bu , karsimiza çesitli algoritmalar çikabiliyor.

Iyi de stringbuilder'i övdün övdün simdi neden böyle diyorsun diye söylendiginizi duyabiliyorum :dribble:

Asagidaki örnegi inceleyelim...

Console.WriteLine(" + kullanilarak işlem yapiliyor");

Console.WriteLine("Baslangiç: " + DateTime.Now.ToString());

string strA="";

for (int intA=0;intA<10000000;intA++)

strA="A"+"A"+"A"+"A"+"A"+"A"+"A"+"A"+"A"+"A";

Console.WriteLine("Bitis: " + DateTime.Now.ToString());

Console.WriteLine("-------------------------------");

Console.WriteLine(" Concat kullanilarak işlem yapiliyor");

Console.WriteLine("Baslangiç: " + DateTime.Now.ToString());

strA="";

for (int intA=0;intA<10000000;intA++)

strA =string.Concat("A"+"A"+"A"+"A"+"A"+"A"+"A"+"A"+"A"+"A");

Console.WriteLine("Bitis: " + DateTime.Now.ToString());

Console.WriteLine("-------------------------------");

Console.WriteLine(" stringbuilder kullanilarak işlem yapiliyor");

Console.WriteLine("Baslangiç: " + DateTime.Now.ToString());

strA="";

for (int intA=0;intA<10000000;intA++)

{

StringBuilder stbA=new StringBuilder();

stbA.Append("A");

stbA.Append("A");

stbA.Append("A");

stbA.Append("A");

stbA.Append("A");

stbA.Append("A");

stbA.Append("A");

stbA.Append("A");

stbA.Append("A");

stbA.Append("A");

}

Console.WriteLine("Bitis: " + DateTime.Now.ToString());

Console.WriteLine("-------------------------------");

Bu örnekte 3 yöntem kullanilarak string concentration işlemi yapılmaktadir.

1.yöntem standart olan + operatörü ile

2.yöntem string sinifinin concat metodunu kullanarak

3.yöntem ise stringbuilder sinifini kullanarak.

Örnegi çalistirdiginizda ilk örnegin aksine 1.yöntem en hizlisi olacaktir.

Hele stringbuilder'in zamanina baktiginizda diger 2 yöntemden çok daha fazla zaman aldigini göreceksiniz.Dikkat ederseniz bu örnekte döngünün her safhasinda string degiskenine yeni bir değer ataniyor,eski değeri korunmuyor.

Artik kurdugunuz algoritmaya göre hangi yöntemi kullanacaginiza karar verebilirsiniz.

Umarim yararlı olmustur.Bir sonraki makalede görüşmek üzere.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...