C++ Performans Optimizasyonu ve En İyi Pratikler

C++ ile çalışmanın güzel yanlarında birisi de performans konusunda gereklilikleri yeterince iyi karşılaması diyebiliriz. Ancak her güçlü silah gibi “kötü” lerin ellerinde daha da kötü olabilir. Bu nedenle burada C++ ile geliştirme yaparken yapılabilecek ufak iyileştirmeleri “aklıma gelikçe” yazacağım. Her türlü öneri ve düzeltme için yorumlarınıza açığım.

Öncelikle aşağıda çok masum duran kod bloğuna bakalım;

string FindAddr( list<Employee> l, string name ){
   for( list<Employee>::iterator i = l.begin(); i != l.end(); i++ ) {
       if( *i == name ) {
           return (*i).addr;
       }
   }
   return "";
}

Buradaki hatalar:

  1. Pass by value ile parametre olarak geçireceğiniz değişkenler için const& (referans) kullanamaya özen gösterin; çünkü pass by value işlemi listeyi ve stringi kopyalamaya çalışır.
  2. i++ (postincrement) yerine ++i (preincrement) kullanın; çünkü i++ işleminde i değerini bir arttırıp eski değerini geçici bir değişken yaratarak geri dönderir. (Aslında bazı derleyiciler uygun gördüğünde bunu otomatikman yapmaktadır, ama el alışkanlığı olması ve derleyici bağımsız bu optimizasyona sahip  olmak için böyle yapmaya devam edelim.)
  3. *i == name işleminin geçerli olması için Employee sınıfının ya stringe çevrilir olması ya da string alan bir çevirici constructora sahip olması gerekir. Her iki durumda da =operatörünü çağıran geçici birer nesne yaratılır. Geçici nesne yaratılmamasının tek yolu bir =operatörünün tanımlanmış olmasıdır.
  4. return “” gibi bir değer döndürmektense yerel bir değişken tanımlayıp bunu döndürmek daha iyidir. Derleyicinin sizden gizli değişken yaratma işlemlerine dikkat edin, bunun önüne geçmenin bir yolu constructorlarınızı explicit yapmak olabilir. Bir fonksiyonda sadece tek bir return ifadesi kullanamaya çalışın. Bu durum derleyicinin yerel değişkenleri devre dışı bırakacak return value optimizasyonu yapmasını sağlar, yani aşağıdaki kod bloğu yazıldığında derleyici a değeri için optimizasyon yapabilir.
 string a = FindAddr( l, "tolga" ); 
  1. Burada string yerine String& döndürmek geçici değişken yaratmamak için çözüm gibi görüneibilir ama fonksiyon biter bitmez yerel değişkenin geçerliliği biteceği için döndürdüğünüz değer asla geçerli olmayacak ve programınız hiç ummadığınız davranışlar sergileyecektir. Yani asla ama asla yerel değişkenlere referans döndürmeyin!

Toparlayacak olursak doğru şekli:

string FindAddr( const list<Employee> l, string name ){
   for( list<Employee>::iterator i = l.begin(); i != l.end(); i++ ) {
       if( *i == name ) {
           return (*i).addr;
       }
   }
   return "";
}

Şimdi aşağıdaki kodu optimize edelim:

for (int i = 0; i < numPixels; i++)
rendering_context->back_buffer->surface->bits[i] = some_value;

Öncelikle döngünün her aşamasında yapılan pointer-indirection işlemi mutlaka çok zaman harcamaktadır, bunun için bu ifadeyi bir defalık döngünün dışında asıl işaret edilmek istenen  değere bir pointer atamak tüm derefarans işlemini her defasında yapmaya göre işimizi bayağı hızlandıracaktır:

unsigned char *back_surface_bits =
rendering_context->back_buffer->surface->bits;
 for( int i = 0; i < numPixels; i++ )
    back_surface_bits[i] = some_value

yukarıdaki optimizasyonu birkaç adım daha ileri taşımak için; pre-increment tercih ediyor ve pointerı index ile değil arttırma ile kullanıyoruz:

unsigned char *back_surface_bits =
rendering_context->back_buffer->surface->bits;
 for( int i = 0; i < numPixels; ++i, ++back_surface_bits )
     *back_surface_bits = some_value
Reklamlar

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Google+ fotoğrafı

Google+ hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Connecting to %s