Root > Documents > Programlama > CSharp Performans | AR-GE Grup
Cyber-Warrior.Org \ Doküman \ Programlama > CSharp Performans | AR-GE Grup
Madde
  Yazar : macmillan
  Date : 05.01.2016 13:58:01
 
# CSharp Performans | AR-GE Grup
 
Merhabalar,
C# ile program yazarken aslinda benim gibi birçok kimsenin dikkat etmedigi önemli bir husus var.
Mesela bir kaç adet veri degilde yüz binlere ulasan veri üretebilen bir program yazdiginizi düsünün, eger programdaki kodlari iyice optimizasyon etmezseniz bu programin çiktiyi verme süresi bir hayli uzun olabilir.
Simdi bu optimizasyonun nasil yapilacagini gösterelim.

1 - String Performansi
Örnek bir kod yazalim.
            for (int i = 0; i < 1000000; i++)
            {
              
            }
Bu kod ile döngü 1M kez devam edecektir ve islem 1 sn altinda bitecektir.Ancak eger asagidaki gibi kod yazarsak islem dakikalar boyunca sürecektir.
            string a = "";
            for (int i = 0; i < 1000000; i++)
            {
               a += "a";
            }
Bu islemin bu kadar uzun sürmesinin sebebi sudur;
a degiskenine deger atanmadan önce hafizada yeni bir yer ayrilir ve yeni ayrilan yere a’ nin önceki degeri ile yeni atamis oldugumuz deger kopyalani ve eski yer temizlenir.
Ve bu islem 1M kez tekrarlanir, her seferinde veri büyücegin dolayi döngü ilerledikçe islem yavaslayacaktir.
Aslinda siz 1M lik islem yaptirirken a degiskeni üzerinde 499999500000 kez islem yapiliyor. Çünkü her karakter eklendiginde metin boyutu tek tek büyüyor ve yapilacak islemin süresi bir hayli uzuyor.

Peki biz bu islemin bu kadar uzamamasi için ne yapmamiz gerekiyor;
Bunun için Buffer mantigini kullanacagiz.
Buffer mantigi iki veri arasinda boyutu küçük olan bir araçtir ve bu araçta belirlenen boyut doldugunda içerisindeki veriyi hedef degiskene ekler ve içerigini bosaltir, böylece yukaridaki isleme göre bayagi performansli olur.
Mesela 1 ton Kum ve 1 adet Kamyon oldugunu düsünelim.

Bizim ilk yaptigim islemde Kumu kamyona kürek ile atmaya benzer ancak ikinci yapilan islemde kumu greyder ile kamyona atmak gibidir.
Simdi bunu bir örnekle gösterelim. Öncelikle buffer isminde bir string degiskeni belirleyelim.
            string buffer = "";
yukarida belirlemis oldugumuz degisken belirledigimiz boyuta ulastiginda içerigini a degiskenine ekleyecek ve içerigini bosaltacaktir böylece sürekli sürekli a degiskenine veri eklenmeyip bu islemin çok daha kisa olmasi saglanacaktir.
            string a = "";
            string buffer = "";
            for (int i = 0; i < 1000000; i++)
            {
               buffer += "a";
               if (buffer.Length >= 500)
               {
                    a += buffer;
                    buffer = "";
               }
            }
Yukaridaki yazdigimiz kodu kisaca açiklayalim.
buffer degiskeninin uzunlugunu 500 oldugunda içerigini a degikenine dahil edip sifirlanacaktir, böylece bu islemin süresi baya kisalmis olacak.

Ilk Kod:
            string a = "";
            for (int i = 0; i < 1000000; i++)
            {
               a += "a";
            }

Ikinci Kod:
            string a = "";
            string buffer = "";
            for (int i = 0; i < 1000000; i++)
            {
               buffer += "a";
               if (buffer.Length >= 500)
               {
                    a += buffer;
                    buffer = "";
               }
            }
            a += buffer;
Ilk kod her döngüde bir a degiskenine bir adet karakter ekler.
Ikinci kod 500 döngüde bir a degiskine buffer içerisindeki 500 karakteri ekler.
Ilk kod ile ikinci kodun sonucu ayni olacak fakat Ikinci yazmis oldugumuz kod ilk koddan çok daha hizli tamamlanacaktir. Ilk kodun tamamlanmasi dakikalari alirken Ikinci kodun tamamlanmasi saniyeler sürecektir.

2 - Array Performansi
Kullanilacak Fonskiyonlar: Array.Resize

Bir program yazdigimizi düsünelim ve program Cheat Engine tarzi bir program olsun ve seçtigimiz islemin hafizasindaki degerleri tarayip istedigimiz sonuçlari döndersin ve daha sonra biz bu degerler içerisinde eleme yapabilelim. Ancak program bilinmeyen degerleride tarayabilsin.
Bir adet Hafiza sinifimiz olsun içerisinde Adres ve Deger degiskenini barindirsin daha sonra biz bu sinifi dize olarak kullanacagiz ve buldugumuz adresi ev degeri bu diziye ekleyecegiz.
Bir uygulamanin hafizasinda milyonlarca adres olabilir.
Simdi cw.exe isimli uygulamanin hafizada 20M kadar adres taradigimizi ve bu adreslerder sonucu 1 den büyük olan degerler oldugunu varsayalim ve bu adresleri daha önce belirledigimiz Hafiza isimli dizimize atayalim.
Asagidaki kodlarda örnek olsun diye degiskenlere deger atamadim Adres dizisinin adresleri ve Degerler dizi ise hafizaya ait degerleri içerdigini varsayalim.
             int Bulunan = 20000000;
            Hafiza[] mHafiza = new Hafiza[0];
            int[] Deger = new int[Bulunan];
            string[] Adres = new string[Bulunan];
            for (int i = 0; i < Bulunan; i++)
            {

               if (Deger >= 1)
               {
                    Array.Resize<Hafiza>(ref mHafiza, mHafiza.Length + 1);
                    mHafiza[mHafiza.Length - 1] = new Hafiza();
                    mHafiza[mHafiza.Length - 1].Adres = Adres;
                    mHafiza[mHafiza.Length - 1].Deger = Deger;
               }
            }
yukaridaki yazmis oldugumuz kod ile degeri 1 den büyük olan degerleri dizimize dahil ettik ancak eger degeri 1 den büyük olan diziler arttiktan yukarida string tipinde belirttigim gibi isem süresi bayagi uzuyacak ve hatta saatlerinizi dahi alabilir.
Bu islemin süresini kisaltmamiz için gerekenler az önce string tipinde belirttigim gibi yine bir Buffer kullanmaktir çünkü diziyi her yeniden boyutlandirma yaptigimizda yeni yer açacak ve önceki verileri yeni yere koypalayacak ve bunu her bir deger buldugunda yaptigi için islem süresi bayagi uzayacaktir ancak bunu her veri buldugunda degilde topluca belirttigimiz sayidaki kadar veri buldugunda eklerse islemin süresi bayagi kisalacaktir.
Simdi kodlarimizi tekrar düzenleyelim ve bir tane Buffer isimli bir dizi ekleyelim ve bu dizinin boyutu 1000 oldugunda içerisindeki verileri ana dizimize eklesin.
            int Bulunan = 20000000;
            int BufferUzunluk = 0;
            Hafiza[] mBuffer = new Hafiza[1000];
            Hafiza[] mHafiza = new Hafiza[0];
            int[] Deger = new int[Bulunan];
            string[] Adres = new string[Bulunan];
            for (int i = 0; i < Bulunan; i++)
            {

               if (Deger >= 1)
               {
                    mBuffer[BufferUzunluk] = new Hafiza();
                    mBuffer[BufferUzunluk].Adres = Adres;
                    mBuffer[BufferUzunluk].Deger = Deger;
                    BufferUzunluk++;
                    if (BufferUzunluk >= 1000)
                    {
                        Array.Resize(ref mHafiza, mHafiza.Length + mBuffer.Length);
                        int degisken = 0;
                        for (int j = mHafiza.Length - BufferUzunluk; j < mHafiza.Length; j++)
                        {
                            mHafiza[j] = (Hafiza) mBuffer[degisken].Clone();
                            degisken++;
                        }
                        mBuffer = new Hafiza[1000];
                        BufferUzunluk = 0;
                    }
                    mHafiza[mHafiza.Length - 1] = new Hafiza();
                    mHafiza[mHafiza.Length - 1].Adres = Adres;
                    mHafiza[mHafiza.Length - 1].Deger = Deger;
               }
            }
            if (BufferUzunluk > 0)
            {
               Array.Resize(ref mHafiza, mHafiza.Length + BufferUzunluk);
               int degisken = 0;
               for (int i = mHafiza.Length - BufferUzunluk; i < mHafiza.Length; i++)
               {
                    mHafiza = (Hafiza)mBuffer[degisken].Clone();
                    degisken++;
               }
            }
Bu kod ile Buffer isminde degisken atadik ve uzunlugunu 1000 olarak ayarladik daha sonra 1 den büyük olan degerler Buffer dizisine eklendi ve her eklemede BufferUzunluk isimli degisken 1 adet artirildi. Eger BuffferUzunluk isimli degiskennin uzunlugu 1000 olur veya 1000 geçerse içerisideki degerleri ana dizimiz olan mHafiza dizisine ekledi ve içerigini bosaltti ve BufferUzunluk isimli degiskenin degerini 0 yapti.
Islem bittiginde ise eger mBuffer degiskeninin içerisinde veri bulunuyorsa bu degerleride ana dizimiz olan mHafiza dizisine ekledi böylece mHafiza dizisine her seferinde ekleme yapmayip islem süresini bayagi kisaltti.
Buradaki 1000 sinirini artirirsaniz islemin süresi daha kisalabilir ancak asiriya kaçar degeri fazlalistirirsaniz mBuffer isimli degiskenin boyutu artmis oldugundan islemin süresi yine uzayacaktir.

3 - Yapilan Performans Testi
1. Husuda yazmis oldugum kodlari C# içerisindeki DateTime çatisi ile test ettim.
String veritipi üzerinde yaptigim süre testi.
1. Kod Ile Yapilan Test   
string a = "";     
for (int i = 0; i < 1000000; i++)       
{
      a += "a";       
}
Yukaridaki kodu DateTime çatisi ile test ettim ve sonuçlar asagidaki gibidir:
Baslama Zamani: 65628020 (18:13:48:200)
Bitis Zamani: 66366193 (18:26:06:193)
Islem Sonucu: 738173 (00:12:18:173)
Analiz: Yukaridaki görmüs oldugunuz bu sonuca göre islem süresince kahvenizi yapip içebilirsiniz.

2. Kod Ile Yapilan Test
string a = "";
string buffer = "";
for (int i = 0; i < 1000000; i++)
{
      buffer += "a";
      if (buffer.Length >= 500)
      {
            a += buffer;
            buffer = "";
      }
}
Yukaridaki kodu DateTime çatisi ile test ettim ve sonuçlar asagidaki gibidir:
Baslama Zamani: 67394745 (18:43:14:745)
Bitis Zamani: 67397124 (18:43:17:124)
Islem Sonucu: 2379 (00:00:02:379)
Analiz: Sonuçta gördügünüz üzere islem sadece 2 saniye sürdü.

Islem Yapan PC Bilgileri
Windows 7 64 Bit
Inter Core i3 CPU 530 2.93 GHz(4 CPUs)
Ram: 4 GB


Yukaridaki yazimda anlattigim gibi kelime üreten dosya çeviren veya büyük boyutlu dosya isleyen bir uygulama yazdiginiz zaman yukaridaki kodlari örnek baz alabilirsiniz aksi halde islem süresi çok uzun olabilir.
Not: Performans islemleri C# dilinde oldugu gibi VB.NET, C++,Java vb. diller içinde geçerlidir.
   
   
Cyber-Warrior TIM All Legal and illegal Rights Reserved.\CWDoktoray 2001©