Optimizasyon ne zaman erken olur?


82

Knuth'un dediği gibi,

Zamanın yaklaşık% 97'sinde küçük verimlilikleri unutmalıyız: erken optimizasyon tüm kötülüklerin köküdür.

Bu, Stack Overflow'da "en verimli döngü mekanizması hangisidir", "SQL optimizasyon teknikleri?" Gibi soruların cevaplarında sıklıkla ortaya çıkan bir şeydir. ( ve benzeri ). Bu optimizasyon ipuçları sorularının standart cevabı, kodunuzun profilini çıkarmak ve önce bunun bir sorun olup olmadığını görmektir ve değilse, o zaman yeni tekniğinize gerek yoktur.

Sorum şu, eğer belirli bir teknik farklıysa, ancak özellikle belirsiz veya karartılmış değilse, bu gerçekten erken bir optimizasyon olarak kabul edilebilir mi?

İşte Randall Hyde tarafından yazılan Erken Optimizasyon Yanılgısı adlı ilgili bir makale .


42
"Prematüre optimizasyon tüm kötülüklerin köküdür" diye bağıran pek çok kişinin bu alıntıyı zamanından önce optimize etmesi biraz ironik: (devam)
bazı

22
"Küçük verimlilikleri unutmalıyız, diyelim ki zamanın yaklaşık% 97'si: erken optimizasyon tüm kötülüklerin köküdür. Yine de fırsatlarımızı o kritik% 3'te kaçırmamalıyız" (Donald Knuth)
bazı

2
Sanırım bunu CA Hoare söyledi. Knuth bile öyle diyor.
jamesh

1
evet, Tony Hoare ilk önce "erken optimizasyonun tüm kötülüklerin köküdür" dedi, ancak Knuth onu alıntıladı / başka kelimelerle ifade etti, inanıyorum ki
nickf

2
Sözün çoğu zaman kötüye kullanıldığını ve bağlamından çıkarıldığını kabul etsem de, "erken" olduğu için tanımı gereği her zaman doğrudur (Bununla birlikte, çoğunlukla özensiz tasarım ve kod için bir gerekçe olarak yanlış kullanılır). Tanım gereği, optimizasyon, tasarım sırasında veya başka bir noktada, geliştirmenin en elverişli noktasında gerçekleştiyse, "erken" değildi.
Lawrence Dol

Yanıtlar:


103

Don Knuth okuryazar programlama hareketini başlattı çünkü bilgisayar kodunun en önemli işlevinin programcının niyetini bir insan okuyucuya iletmek olduğuna inanıyordu . Performans adına kodunuzun anlaşılmasını zorlaştıran herhangi bir kodlama uygulaması erken bir optimizasyondur.

Optimizasyon adına tanıtılan bazı deyimler o kadar popüler hale geldi ki, herkes onları anlıyor ve erken değil, beklenen hale geldi . Örnekler şunları içerir:

  • Kullanma işaretçi Aritmetik yerine dizi gösterimini gibi deyimlerin kullanımı da dahil olmak üzere, C

    for (p = q; p < lim; p++)
    
  • Yerel değişkenlere genel değişkenleri yeniden bağlama gibi Lua

    local table, io, string, math
        = table, io, string, math
    

Bu tür deyimlerin ötesinde , tehlikede kısayollar kullanın .

Tüm optimizasyon,

  • Bir program çok yavaş (birçok kişi bu bölümü unutuyor).

  • Optimizasyonun işleri iyileştirebileceğini gösteren bir ölçümünüz (profil veya benzeri) var .

(Hafıza için optimize etmeye de izin verilir.)

Soruya doğrudan cevap:

  • "Farklı" tekniğiniz programın anlaşılmasını zorlaştırıyorsa , bu erken bir optimizasyondur .

DÜZENLEME : Yorumlara yanıt olarak, araya ekleme sıralaması gibi daha basit bir algoritma yerine hızlı sıralama kullanmak , herkesin anladığı ve beklediği bir deyim örneğidir . (Kitaplık sıralama yordamını kullanmak yerine kendi sıralama rutininizi yazsanız da, çok iyi bir nedeninizin olduğunu umuyoruz .)


13
Tanımlarınıza göre; Bir hızlı sıralama uygulaması, bir baloncuk sırasına göre okumak ve anlamak daha zorsa, bu erken bir optimizasyondur. Bellek için optimize edemiyor musunuz? Büyük seyrek matrisler için aynı örnekleri aramayı deneyin. IMHO, çoğu optimizasyon tasarım aşamasında yapılmalıdır. i, e, çok erken.
SmacL

1
@frankodwyer: ancak işaretçiyi artırmak, muhtemelen bir sayacı artırmaktan ve dizi gösterimini kullanmaktan daha hızlıdır ve erken optimizasyon olur.
Joachim Sauer

5
@Norman: Quicksort artık her yerde bulunmasına rağmen , ilk icat edildiğinde değildi ve bu nedenle QED, yazarın hiçbir işiyle uğraşmadığı erken bir optimizasyondu, değil mi?
Lawrence Dol

5
@ Yazılım Maymun: Kesinlikle. Tüm CS araştırmaları, vergi mükelleflerinin parasının boşa harcanmasıdır ve derhal durdurulmalıdır.
Norman Ramsey

11
İcat ettiğiniz de dahil olmak üzere herhangi bir sıralama algoritması, uygun yorumlarla sortQuickly (...) adlı ayrı bir işlev olarak yazılırsa açık ve özdür.
ilya n.

40

IMHO, optimizasyonunuzun% 90'ı, algılanan güncel ve daha da önemlisi gelecekteki gereksinimlere göre tasarım aşamasında gerçekleşmelidir. Uygulamanız gereken yüke ölçeklenmediği için bir profil oluşturucu çıkarmanız gerekiyorsa, çok geç bırakmışsınızdır ve IMO, sorunu düzeltmekte başarısız olurken çok fazla zaman ve çaba harcayacaktır.

Tipik olarak, değerli olan tek optimizasyonlar, size hız açısından büyük bir performans artışı veya depolama veya bant genişliği açısından bir çarpan kazandıranlardır. Bu tür optimizasyonlar tipik olarak algoritma seçimi ve depolama stratejisi ile ilgilidir ve mevcut koda döndürmek son derece zordur. Sisteminizi uyguladığınız dile ilişkin kararı etkileyecek kadar derine inebilirler.

Bu yüzden tavsiyem, kodunuza değil gereksinimlerinize göre erken optimize edin ve uygulamanızın olası uzun kullanım ömrüne bakın.


6
"Çok geç bıraktığın" sonucuna katılmıyorum. Temel olarak, bir varsayım geçerli olmadığında profil oluşturma gerekir ve profilleyicinin size NE varsayımın ihlal edildiğini söylemesi gerekir. Örneğin Java'da StringBuffers için "0 konumundaki karakteri sil" in junit testleri için iyi çalıştığını, ancak büyük dizeler için ÇOK yavaş olduğunu buldum. Profilci onu suçlu olarak saptayana kadar bu koddan şüphelenmedim!
Thorbjørn Ravn Andersen

7
Deneyimlerime dayanarak, "profilleyiciye ihtiyacınız olduğunda, çoktan geç oldu" görüşüne katılıyorum - performans sorunlarımın çoğu tekil darboğazlar değil, birden çok katılımcıya yayılmış durumda. Ama sonra, düşük seviyeli kod ve maliyet konusunda güçlü bir geçmişim var ve ilk dize karakterinin kaldırılmasına dayanan (önemli ölçüde tekrarlanan) herhangi bir şeyden içgüdüsel olarak kaçınırdım. "Tasarım sırasında optimize et" için +1.
peterchen

@peterchen sadece meraktan soruyorum, "ilk dize karakterinin kaldırılması" için ne yapardınız?
Ghos3t

1
@ user258365: Kaba kuvvet, alt dizeler için bir kopya oluşturması gerekmeyen bir dize gösterimi kullanmak olacaktır. Bu, değişmez referans sayılan dizeler için "neredeyse önemsiz" dir. Alternatif olarak, değiştirme (sözde kod) gibi algoritmik değişiklikler while (s[0]==' ') s = s.substring(1) for(i=0; i<s.len && s[i]==' '; ++i); s=s.substring(i)--- ancak bu, potansiyel performans sorunlarını zaten bilmeyi gerektirir (profil oluşturucular burada sürekli öğrenme için değerli araçlardır).
peterchen 01

@ ThorbjørnRavnAndersen, bir ekibin bir projeyi bitirmesine yardımcı olmak için danışman olarak çalıştım, ancak bu mümkün değildi çünkü ciddi performans sorunları planlanmadı (spagetti kodu dışında). Tüm hastaların geçmişiyle birlikte kronolojik bir tablo göstermesi gerekiyordu. Google Haritalar'ın tüm dünyayı getirmesi gibi tüm veriler için tek bir istekte bulunuldu. Kötü kod geliştirmek, daha sonra profil oluşturmayı beklemek projenin başarısız olmasına neden oldu.
Pedro Amaral Couto

31

Profil çıkarmadıysanız, erken.


3
Bunun arkasındaki fikre katılıyorum, ancak aynı zamanda: uygulama tamamen CPU döngüleri ile sınırlandırılmadıkça, hem tekrarlanabilir hem de genelleştirilebilir bir ölçüm elde etmek zordur - ve ne kadar kararlı olursa o kadar az gerçekçi olur.
peterchen

1
Yukarıdaki cevapla yaşadığım sorun, bir algoritmayı kodlamadan önce optimize edemeyeceğiniz anlamına gelmesidir. Benim çalışma şeklim, algoritmayı işlevsel gereksinimleri karşılayacak şekilde tasarlama eğilimindedir. Performans gereksinimlerinde başarısız olma olasılığının olup olmadığına bakın (örneğin, yüksek düzeyde karmaşıklık ve büyük veri kümelerine ulaşma olasılığı) ve kodlamaya başlamadan önce algoritmayı optimize edin. Optimizasyon, en uygun çözüme ulaşmak için basitçe iyileştirmedir, genellikle en verimli şekilde tasarım aşamasında yapılır.
SmacL

2
Ben katılmıyorum Knuth küçük verimliliklerden bahsediyordu. Optimizasyon genellikle tasarım aşamasında gerçekleşir. Genellikle büyük bir performans etkisine sahip olan ve daha sonra mutlaka değiştirilemeyen uygun veri yapılarının ve algoritmaların seçimini içerir.
haslersn

@haslersn: "Knuth küçük verimliliklerden bahsediyordu" Donald Knuth: "Bugünün yazılım mühendislerinin çoğunun paylaştığı geleneksel akıl, küçüklerin verimliliğini göz ardı etmeyi gerektiriyor; ancak bunun kötüye kullanımlara aşırı tepki olduğuna inanıyorum (...) kurulan mühendislik disiplinleri% 12 iyileşme, kolayca elde marjinal (...)" olarak kabul asla
Pedro Amaral Couto

27

Sorum şu, eğer belirli bir teknik farklıysa, ancak özellikle belirsiz veya karartılmış değilse, bu gerçekten erken bir optimizasyon olarak kabul edilebilir mi?

Um ... Öyleyse elinizin altında iki teknik var, aynı maliyette (kullanmak, okumak, değiştirmek için aynı çaba) ve biri daha verimli. Hayır, daha verimli olanı kullanmak bu durumda erken olmaz.

Yazdığınız şeyin göreceli hızının hiçbir zaman önemli olmayacağını bilseniz bile, bir yerlerde asılı daha verimli bir sürüm olması ihtimaline karşın, ortak programlama yapılarına / kitaplık rutinlerine alternatifler aramak için kod yazmanızı kesintiye uğratmak. .. Bu erken.


3
Kabul edildi, eğer bir algoritmanın kullanım durumunuz için daha verimli olduğunu biliyorsanız, kesinlikle daha verimli olanı kullanın. En verimli algoritmayı bilmiyorsanız, sahip olduklarınızı kullanın ve daha sonra bunun bir sorun olup olmadığını görmek için profil yapın.
grepsedawk

10

Erken optimizasyondan kaçınma konseptinde gördüğüm sorun şu:

Bunu söylemekle yapmak arasında bir kopukluk var.

Pek çok performans ayarı yaptım, büyük faktörleri başka türlü iyi tasarlanmış kodlardan çıkararak, görünüşe göre erken optimizasyon olmadan yaptım. İşte bir örnek.

Neredeyse her durumda, yetersiz performansın nedeni dörtnala genellik dediğim şeydir ; soyut çok katmanlı sınıfların kullanımı ve basit kavramların daha az zarif ama tamamen yeterli olacağı kapsamlı nesne yönelimli tasarım .

Bildirime dayalı mimari ve basitçe bir nesnenin boole özelliğini ayarlamanın faaliyetlerin sınırsız bir dalgalanma etkisine sahip olabileceği bilgi gizleme gibi bu soyut tasarım kavramlarının öğretildiği öğretim materyalinde verilen sebep nedir? Verimlilik .

Öyleyse, bu erken optimizasyon muydu, değil miydi?


Soyutlama ve genellemeyle ilgili en büyük sorunlardan birini gösterdiği için bu yanıtı beğendim. Daha geniş bir kullanım senaryosu yelpazesini desteklemek için bir sınıf hiyerarşisini genelleştirirken, en tipik kullanım durumları için performansı ciddi şekilde düşürmek çok kolaydır. Aynı zamanda, işlevselliğin amaçlanan kullanım ölçeği için kabul edilebilir bir performans düzeyinde sağlanıp sağlanmadığını kontrol etmeden, belirli bir işlevsellik sağlayan bir sınıfa bağlanmak da kolaydır.
SmacL

1
"basit kavramların daha az zarif ancak tamamen yeterli olacağı " Basit kod, gereksinimleri karşıladığında, karmaşık kod basit koddan nadiren daha zariftir. (Yine de, birisi daha karmaşık bir durumda çalıştırmaya çalışırsa, basit kodunuzun aslında desteklenmeyen durumun / girdinin açık bir göstergesiyle patlamasını sağlamanız gerektiğini iddia ediyorum.)
jpmc26

8

İlk önce kodu çalışır hale getirin. İkinci olarak, kodun doğru olduğunu doğrulayın. Üçüncüsü, hızlı olun.

Aşama 3'ten önce yapılan herhangi bir kod değişikliği kesinlikle erken. Bundan önce yapılan tasarım seçimlerinin nasıl sınıflandırılacağından tam olarak emin değilim (uygun veri yapılarını kullanmak gibi), ancak iyi performans gösterenlerden çok programlaması kolay soyutlamaları kullanmaya yönelmeyi tercih ediyorum. Profil oluşturmaya başlayabileceğim ve sonuçları karşılaştırmak için doğru (ancak sıklıkla yavaş) bir referans uygulamasına sahip olabileceğim bir aşama.


8

Veritabanı perspektifinden, tasarım aşamasında optimal tasarımı düşünmemek en iyi ihtimalle çılgınlıktır. Veritabanları kolayca yeniden düzenlenmez. Kötü bir şekilde tasarlandıktan sonra (bu, optimizasyonu dikkate almayan bir tasarım, erken optimizasyon saçmalığının arkasına nasıl saklanmaya çalışsanız da), veritabanı için çok temel olduğundan neredeyse hiçbir zaman bundan kurtulamaz. tüm sistemin çalışması. Beklediğiniz durum için en uygun kodu göz önünde bulundurarak doğru şekilde tasarlamak, bir milyon kullanıcı olana kadar beklemekten çok daha az maliyetlidir ve uygulama boyunca imleçler kullandığınız için insanlar çığlık atmaktadır. Sargeable kod kullanma, neyin mümkün olan en iyi indeksler olacağının seçilmesi, vb. Gibi diğer optimizasyonlar, yalnızca tasarım zamanında yapılması mantıklıdır. Hızlı ve kirli denmesinin bir nedeni var. Hiçbir zaman iyi çalışamayacağı için, çabukluğu iyi kodun yerine kullanmayın. Açıkçası, veritabanlarında performans ayarlamasını anladığınızda, aynı zamanda daha iyi performans gösterme olasılığı daha yüksek olan veya iyi çalışmayan bir kod yazmak için gerekenden daha az kod yazabilirsiniz. İyi performans gösteren veritabanı tasarımının ne olduğunu öğrenmek için zaman ayırmamak, geliştiricinin tembelliğidir, en iyi uygulama değil.


7

Bahsettiğiniz şey, karma tabanlı bir arama konteyneri kullanmak gibi optimizasyon ile çok sayıda anahtar arama yapılacağı zaman bir dizi gibi dizine alınmış bir konteynır kullanmaktır. Bu erken optimizasyon değil , tasarım aşamasında karar vermeniz gereken bir şey.

Knuth kuralının ilgili olduğu optimizasyon türü, en yaygın kod yollarının uzunluğunu en aza indirgemek, en çok çalıştırılan kodu örneğin montajda yeniden yazarak veya kodu basitleştirerek optimize ederek daha az genel hale getirmektir. Ancak, kodun hangi bölümlerinin bu tür bir optimizasyona ihtiyaç duyduğundan emin olana kadar bunu yapmanın hiçbir faydası yoktur ve optimizasyon, kodu anlamayı veya sürdürmeyi zorlaştırır (yapabilir mi?), Bu nedenle "erken optimizasyon tüm kötülüklerin köküdür".

Knuth ayrıca programınızın kullandığı algoritmaları, bir soruna yönelik yaklaşımı optimize etmek yerine, her zaman daha iyi olduğunu söylüyor. Örneğin, küçük bir ayarlama size optimizasyonla% 10 hız artışı sağlayabilirken, programınızın çalışma şeklini temelden değiştirmek onu 10 kat daha hızlı hale getirebilir.

Bu soruya gönderilen diğer birçok yoruma tepki olarak: algoritma seçimi! = Optimizasyon


6

Makalenin amacı, tipik olarak optimizasyonun kıvrımlı ve karmaşık olmasıdır. Ve tipik olarak , siz mimar / tasarımcı / programcı / bakımcı olarak neler olup bittiğini anlamak için açık ve öz bir koda ihtiyacınız var.

Belirli bir optimizasyon açık ve öz ise, denemekten çekinmeyin (ancak geri dönün ve bu optimizasyonun etkili olup olmadığını kontrol edin). Önemli olan, performansın faydaları, optimizasyonların yazılması ve sürdürülmesinin indüklenen maliyetlerinden daha ağır basana kadar, geliştirme süreci boyunca kodu açık ve öz tutmaktır.


2
Aslında, biraz "optimizasyon", iş için uygun algoritmanın seçilmesine bağlıdır; bu, yüksek düzeyde sonuçları olan üst düzey bir faaliyet - Knuth'un alıntısındaki "küçük verimliliklerden" çok uzak.
Shog9

4

Yalnızca bir performans sorunu onaylandığında optimize etmeye çalışıyorum.

Erken optimizasyon tanımım, 'bir performans sorunu olduğu bilinmeyen kod üzerinde boşa harcanan çaba.' Optimizasyon için kesinlikle bir zaman ve yer vardır. Ancak işin püf noktası, ekstra maliyeti yalnızca uygulamanın performansına dahil olduğu ve ek maliyetin performans isabetinden daha ağır bastığı yerlerde harcamaktır.

Kod (veya bir DB sorgusu) yazarken 'verimli' kod yazmaya çalışıyorum (yani amaçlanan işlevini hızlı ve eksiksiz, makul en basit mantıkla gerçekleştiren kod) 'Etkili' kodun 'optimize edilmiş' ile aynı şey olmadığına dikkat edin. kodu. İyileştirmeler genellikle koda ek karmaşıklık getirir ve bu da o kodun hem geliştirme hem de bakım maliyetini artırır.

Tavsiyem: Optimizasyon maliyetini yalnızca faydayı ölçebildiğiniz zaman ödemeye çalışın.


4

Programlama sırasında bir dizi parametre çok önemlidir. Bunlar arasında:

  • Okunabilirlik
  • Sürdürülebilirlik
  • Karmaşıklık
  • Sağlamlık
  • Doğruluk
  • Verim
  • Geliştirme süresi

Optimizasyon (performans için gitmek) genellikle diğer parametrelerin pahasına gelir ve bu alanlardaki "kayıp" ile dengelenmelidir.

İyi performans gösteren iyi bilinen algoritmaları seçme seçeneğiniz olduğunda, önceden "optimize etmenin" maliyeti genellikle kabul edilebilir.


1
Yukarıdaki listenizdeki en önemli QA parametresini kaçırıyorsunuz; Gereksinimleri karşılama. Bir yazılım parçası hedeflenen kitlenin gereksinimlerini karşılamıyorsa, diğer tüm parametreler anlamsızdır. Performans kabul edilebilir değilse, gereksinimler karşılanmamıştır.
SmacL

3
Bunun doğruluk kapsamında olduğu söylenebilir. Ayrıca, 'olabildiğince hızlı' anlamında 'performans' çok nadiren gereksinimler arasındadır ve Ola'nın diğer ihtiyaçlarla bir değiş tokuş olduğu noktası olsa bile geçerliliğini korumaktadır.
frankodwyer

4

Optimizasyon, çok yüksek seviyeden çok düşük seviyeye kadar farklı ayrıntı düzeylerinde gerçekleşebilir:

  1. İyi bir mimari, gevşek bağlantı, modülerlik vb. İle başlayın.

  2. Problem için doğru veri yapılarını ve algoritmaları seçin.

  3. Önbelleğe daha fazla kod / veri sığdırmaya çalışarak belleği optimize edin. Bellek alt sistemi CPU'dan 10 ila 100 kat daha yavaştır ve verileriniz diske sayfalanırsa, 1000 ila 10.000 kat daha yavaştır. Bellek tüketimi konusunda dikkatli olmak, bireysel talimatları optimize etmekten daha büyük kazançlar sağlar.

  4. Her işlev içinde, akış kontrol ifadelerini uygun şekilde kullanın. (Değişmez ifadeleri döngü gövdesinin dışına taşıyın. Bir anahtar / büyük / küçük harfte en yaygın değeri ilk sıraya koyun vb.)

  5. Her ifade içinde, doğru sonucu veren en etkili ifadeleri kullanın. (Çarpma ile vardiya vb.)

Bölme ifadesinin mi yoksa kaydırma ifadesinin mi kullanılacağına ilişkin nit-toplama, mutlaka erken optimizasyon değildir . Öncelikle mimariyi, veri yapılarını, algoritmaları, bellek ayak izini ve akış kontrolünü optimize etmeden bunu yaparsanız, henüz erken.

Ve tabii ki, bir hedef performans eşiği tanımlamazsanız , herhangi bir optimizasyon erkendir.

Çoğu durumda ya:

Y) Hedef performans eşiğine üst düzey optimizasyonlar gerçekleştirerek ulaşabilirsiniz, bu nedenle ifadelerle uğraşmanıza gerek yoktur.

veya

B) Tüm olası optimizasyonları gerçekleştirdikten sonra bile, hedef performans eşiğinizi karşılayamazsınız ve düşük düzeyli optimizasyonlar, okunabilirlik kaybını haklı çıkarmak için performansta yeterli fark yaratmaz.

Tecrübelerime göre, çoğu optimizasyon problemi mimari / tasarım veya veri yapısı / algoritma seviyesinde çözülebilir. Bellek ayak izi için optimizasyon genellikle (her zaman olmasa da) gereklidir. Ancak akış kontrolü ve ifade mantığını optimize etmek nadiren gereklidir. Ve gerçekten gerekli olduğu durumlarda, nadiren yeterlidir.


3

Norman'ın cevabı mükemmel. Her nasılsa, rutin olarak, aslında en iyi uygulamalar olan bazı "erken optimizasyonlar" yaparsınız, çünkü aksi takdirde yapmanın tamamen verimsiz olduğu bilinmektedir.

Örneğin Norman'ın listesine eklemek için:

  • String + String (bir döngüde) yerine Java'da (veya C #, vb.) StringBuilder birleştirmesini kullanma;
  • C gibi döngüden kaçınmak: for (i = 0; i < strlen(str); i++)(çünkü burada strlen, her döngüde çağrılan, her seferinde dizeyi yürüyen bir işlev çağrısıdır);
  • Çoğu JavaScript uygulamasında öyle görünüyor, yapmak daha hızlı for (i = 0 l = str.length; i < l; i++)ve yine de okunabilir, yani tamam.

Ve bunun gibi. Ancak bu tür mikro optimizasyonlar asla kodun okunabilirliği pahasına olmamalıdır.


3

Ekstrem durumlar için profilleyici kullanma ihtiyacı bırakılmalıdır. Projenin mühendisleri, performans darboğazlarının nerede olduğunun farkında olmalıdır.

Bence "erken optimizasyon" inanılmaz derecede özneldir.

Eğer bir kod yazıyorsam ve Hashtable kullanmam gerektiğini biliyorsam , o zaman bunu yapacağım. Bunu kusurlu bir şekilde uygulamayacağım ve sonra hata raporunun bir ay veya bir yıl sonra birisi onunla bir sorun yaşadığında gelmesini bekleyeceğim.

Yeniden tasarım, bir tasarımı başlangıçtan itibaren bariz şekillerde optimize etmekten daha maliyetlidir.

Açıkçası bazı küçük şeyler ilk seferde gözden kaçacak, ancak bunlar nadiren anahtar tasarım kararlarıdır.

Bu nedenle: Bir tasarımı optimize etmek, IMO'nun kendi başına bir kod kokusu olduğu anlamına gelmez.


Sorun şu ki, kodun problem olacağını hiç düşünmediğiniz bölümlerinde sık sık darboğazlar ortaya çıkıyor. Profil oluşturma, bahaneden vazgeçer ve programın gerçek maliyet merkezlerini gösterir. Başlangıçtan itibaren bariz şeyler yapmak en iyisidir, ancak diğer her şey için profilleme vardır.
Chris Smith

2

Knuth'un orijinal alıntısının, gotosıcak noktaları ortadan kaldırmanın bir yolu olarak dikkatle seçilmiş ve ölçülmüş alanlarda kullanımını teşvik eden bir makaleden geldiğini belirtmek gerekir . Sözü, gotobu kritik döngüleri hızlandırmak için kullanma gerekçesini haklı çıkarmak için eklediği bir uyarı oldu .

[...] yine, eğer, örneğin, n'nin ortalama değeri yaklaşık 20 ise ve arama rutini programda yaklaşık bir milyon ya da daha çok kez gerçekleştirilmişse, bu, genel çalışma hızında dikkate değer bir tasarruftur. Bu tür döngü optimizasyonlarını [kullanarak gotos] öğrenmek zor değildir ve daha önce de söylediğim gibi, bunlar bir programın sadece küçük bir bölümünde uygundur, ancak yine de çoğu zaman önemli tasarruflar sağlarlar. [...]

Ve devam ediyor:

Günümüz yazılım mühendislerinin çoğunun paylaştığı geleneksel anlayış, küçüklerin verimliliğini göz ardı etmeyi gerektirir; ancak bunun, "optimize edilmiş" programlarında hata ayıklayamayan veya bakımını yapamayan aptal programcılar tarafından uygulandığını gördükleri suistimallere aşırı tepki olduğuna inanıyorum. Yerleşik mühendislik disiplinlerinde, kolayca elde edilen% 12'lik bir iyileşme asla marjinal olarak kabul edilmez; ve aynı bakış açısının yazılım mühendisliğinde de geçerli olması gerektiğine inanıyorum. Elbette, tek seferlik bir işte bu tür optimizasyonları yapmaya zahmet etmem, ancak söz konusu kaliteli programlar hazırlamak olduğunda, kendimi bu tür verimlilikleri reddeden araçlarla sınırlamak istemiyorum [yani, goto bu bağlamdaki ifadeler].

Tırnak işaretlerinde nasıl "optimize edilmiş" kullandığını aklınızda bulundurun (yazılım muhtemelen gerçekten verimli değildir). Ayrıca, sadece bu "kuruş ve kiloluk aptal" programcıları nasıl eleştirmediğini, aynı zamanda küçük verimsizlikleri her zaman görmezden gelmenizi önererek tepki veren insanları da not edin. Son olarak, sık alıntılanan kısma:

Hiç şüphe yok ki, verimlilik derecesi kötüye kullanıma yol açar. Programcılar, programlarının kritik olmayan bölümlerinin hızı hakkında düşünmek veya endişelenmek için çok fazla zaman harcarlar ve bu verimlilik girişimleri, hata ayıklama ve bakım düşünüldüğünde aslında güçlü bir olumsuz etkiye sahiptir. Zamanın% 97'sinde küçük verimlilikleri unutmalıyız; erken optimizasyon, tüm kötülüklerin köküdür.

... ve sonra profil oluşturma araçlarının önemi hakkında biraz daha:

Ölçme araçlarını kullanan programcıların evrensel deneyimleri sezgisel tahminlerinin başarısız olması olduğundan, bir programın hangi bölümlerinin gerçekten kritik olduğuna dair ön yargıda bulunmak çoğu zaman bir hatadır. Yedi yıl boyunca bu tür araçlarla çalıştıktan sonra, bundan sonra yazılan tüm derleyicilerin tüm programcılara programlarının hangi bölümlerinin en çok maliyete mal olduğunu belirten geri bildirim sağlayacak şekilde tasarlanması gerektiğine ikna oldum; gerçekten de, özellikle kapatılmadığı sürece bu geri bildirim otomatik olarak sağlanmalıdır.

İnsanlar, onun alıntısını her yerde kötüye kullandılar, çoğu zaman mikro optimizasyonların tüm makalesi mikro optimizasyonları savunurken erken olduğunu öne sürdüler! Her zaman küçükteki verimlilikleri göz ardı ederek, bu "geleneksel bilgeliği" yankılayan eleştirdiği insan gruplarından biri, başlangıçta kısmen, her tür mikro optimizasyonun cesaretini kıran bu tür tiplere yönelik olan sözünü genellikle kötüye kullanıyor. .

Yine de, profilciyi tutan deneyimli bir el tarafından kullanıldığında , uygun şekilde uygulanan mikro optimizasyonlar lehine bir alıntıydı. Bugünün analojik eşdeğeri, "İnsanlar yazılımlarını optimize etmek için gözü kapalı saplamalar yapmamalı, ancak özel bellek ayırıcılar, referansın yerelliğini iyileştirmek için kilit alanlara uygulandıklarında büyük bir fark yaratabilir" veya " El yazısı SIMD kodu kullanarak SoA temsilcisinin bakımı gerçekten zordur ve onu her yerde kullanmamalısınız, ancak deneyimli ve rehberli bir el tarafından uygun şekilde uygulandığında belleği çok daha hızlı tüketebilir. "

Knuth'un yukarıda tanıtıldığı gibi dikkatlice uygulanan mikro optimizasyonları tanıtmaya çalıştığınız her seferinde, acemileri çok heyecanlanmaktan ve tüm yazılımlarını kullanmak üzere yeniden yazmak gibi optimizasyonda körü körüne bıçaklamaktan caydırmak için bir sorumluluk reddi beyanı atmak iyidir goto. Kısmen yaptığı şey buydu. Onun sözü, büyük bir feragatnamenin parçasıydı, tıpkı bir motosikletin alevli bir ateş çukurunun üzerinden atlaması gibi, amatörlerin bunu evde denememesi gerektiği ve aynı zamanda uygun bilgi ve ekipman olmadan deneyenleri ve yaralananları eleştiren bir feragatname ekleyebilir. .

"Erken optimizasyonlar" olarak nitelendirdiği şey, ne yaptıklarını etkili bir şekilde bilmeyen insanlar tarafından uygulanan optimizasyonlardı: Optimizasyona gerçekten ihtiyaç olup olmadığını bilmeyen, uygun araçlarla ölçüm yapmayan, belki de derleyicileri veya bilgisayar mimarileri ve hepsinden önemlisi, "kuruş ve pound aptalca" idi; daha uzun süre etkili bir şekilde hata ayıklama ve bakım.

Eğer "pennywise-and-pound-aptalca" kategorisine uymuyorsanız, gotokritik bir döngüyü hızlandırmak için a kullanıyor olsanız bile Knuth standartlarına göre zamanından önce optimizasyon yapmıyorsunuzdur (bu olası değildir bugünün optimize edicilerine karşı çok yardımcı olmak için, ancak olsaydı ve gerçekten kritik bir alanda, o zaman erken optimizasyon yapmazdınız). Gerçekten ihtiyaç duyulan alanlarda yaptığınız her şeyi gerçekten uyguluyorsanız ve bundan gerçekten faydalanıyorlarsa, Knuth'un gözünde harikasınız demektir.


1

Benim için erken optimizasyon, çalışan bir sisteme sahip olmadan önce ve gerçekten onun profilini çıkarmadan ve darboğazın nerede olduğunu bilmeden önce kodunuzun verimliliğini artırmaya çalışmak anlamına gelir. Bundan sonra bile, okunabilirlik ve sürdürülebilirlik çoğu durumda optimizasyondan önce gelmelidir.


1

Bilinen en iyi uygulamaların erken optimizasyonlar olduğunu düşünmüyorum. Kullanım senaryolarına bağlı olarak potansiyel performans sorunları olan ne olursa olsun yanma süresiyle ilgilidir. İyi bir örnek: Bir nesne üzerindeki yansımayı optimize etmeye çalışarak bir hafta yakarsanız, bunun bir darboğaz olduğuna dair kanıtınız olmadan zamanından önce optimize ediyorsunuz demektir.


1

Bir kullanıcı veya iş gereksinimi nedeniyle uygulamanızdan daha fazla performansa ihtiyacınız olduğunu görmezseniz, optimizasyon konusunda endişelenmeniz için çok az neden vardır. O zaman bile, kodunuzun profilini çıkarana kadar hiçbir şey yapmayın. Sonra en çok zaman alan parçalara saldırın.


0

Gördüğüm gibi, bir şeyi farklı senaryolarda ne kadar performans kazanabileceğinizi bilmeden optimize ederseniz, erken bir optimizasyondur. Kodun amacı, insanların okumasını gerçekten en kolay hale getirmelidir.


0

Benzer bir soruda yayınladığım gibi, optimizasyon kuralları:

1) Optimize etmeyin

2) (yalnızca uzmanlar için) Daha sonra optimize edin

Optimizasyon ne zaman erken olur? Genelde.

Bunun istisnası belki tasarımınızda veya yoğun olarak kullanılan iyi bir şekilde kapsüllenmiş koddadır. Geçmişte, derleyicinin ürettiği derleyiciye bakmanın ve bir iç döngüdeki tek bir gereksiz talimatı kaldırmanın% 30'luk bir hızlanma sağladığı zaman kritik bir kod (bir RSA uygulaması) üzerinde çalıştım. Ancak, daha karmaşık algoritmalar kullanmanın hızlanması, bundan daha fazla büyüklükteki siparişlerdi.

Optimizasyon yaparken kendinize sormanız gereken bir diğer soru da "Burada 300 baud modemi optimize etmeye eşdeğer bir şey mi yapıyorum?" . Başka bir deyişle, Moore yasası optimizasyonunuzu çok geçmeden önemsiz kılar mı? Pek çok ölçeklendirme sorunu, yalnızca soruna daha fazla donanım atarak çözülebilir.

Son olarak, program çok yavaş ilerlemeden önce optimizasyon yapmak için erken. Bahsettiğiniz bu web uygulamasıysa, darboğazların nerede olduğunu görmek için yük altında çalıştırabilirsiniz - ancak olasılık, diğer sitelerin çoğuyla aynı ölçeklendirme sorunlarına sahip olmanız ve aynı çözümlerin geçerli olmasıdır.

düzenleme: Bu arada, bağlantılı makale ile ilgili olarak, yapılan varsayımların çoğunu sorgulardım. İlk olarak, Moore yasasının 90'larda çalışmayı bıraktığı doğru değil. İkinci olarak, kullanıcının zamanının programcının zamanından daha değerli olduğu açık değildir. Çoğu kullanıcı (en azından söylemek gerekirse) mevcut her CPU döngüsünü çılgınca kullanmıyor, muhtemelen ağın bir şeyler yapmasını bekliyorlar. Ayrıca, programcının zamanı başka bir şeyi uygulamaktan, kullanıcı telefonda iken programın yaptığı bir şeyi birkaç milisaniye azaltmaya kaydırıldığında bir fırsat maliyeti vardır. Bundan daha uzun olan herhangi bir şey genellikle optimizasyon değil, hata düzeltmedir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.