Çalışmasını sağlayın, temizleyin, KATI yapın, SONRA çalışması gereken kadar hızlı çalışmasını sağlayın .
Bu normal şeylerin sırası olmalı. İlk önceliğiniz, gereksinimleri ortadan kaldıran kabul testlerini geçecek bir şey yapmaktır. Bu sizin birinci önceliğinizdir çünkü müşterinizin birinci önceliği; geliştirme süreleri içinde fonksiyonel gereksinimlerin karşılanması. Bir sonraki öncelik, anlaşılması kolay temiz ve okunabilir kod yazmaktır ve böylece gerektiğinde herhangi bir WTF olmadan gelecek durumunuz tarafından korunabilir (neredeyse hiç "" sorusu "sorusu yoktur; siz veya gittikten sonra birileri geri girin ve bir şeyi değiştirin / düzeltin). Üçüncü öncelik, kodu, yine bakıma yardımcı olan modüler, yeniden kullanılabilir, değiştirilebilir parçalara yerleştiren SOLID yöntemine (veya isterseniz GRASP) uymasını sağlamaktır (sadece ne yaptığınızı ve nedenini anlayamazlar, ancak cerrahi kodları cerrahi olarak çıkarabildiğim ve değiştirebileceğim temiz çizgiler var). Son öncelik performanstır; kod, performans özelliklerine uymak için yeterince önemliyse, önce doğru, temiz ve SOLID yapılması neredeyse kesinlikle önemlidir.
Christopher (ve Donald Knuth) yankılanıyor, "erken optimizasyon tüm kötülüğün köküdür". Buna ek olarak, düşündüğünüz optimizasyon türleri hem küçük (kaynak kodunda bir ad verip vermeseniz de yığında yeni nesnenize bir başvuru oluşturulacaktır) hem de derlenmiş bir fark yaratmayabilecek bir türdür IL. Değişken isimleri IL'ye taşınmaz, bu nedenle değişkeni ilk (ve muhtemelen sadece) kullanımından hemen önce bildirdiğiniz için, IL'nin iki örneğiniz arasında özdeş olduğu bir bira parası bahse girerim. Yani, iş arkadaşınız% 100 doğru; optimize edilmiş bir şey için adlandırılmış değişken vs satır içi örneklemeye bakıyorsanız yanlış yere bakıyorsunuz.
.NET'teki mikro optimizasyonlar neredeyse hiç buna değmez (Vakaların yaklaşık% 99.99'undan bahsediyorum). C / C ++ 'da, belki, ne yaptığınızı biliyorsanız. Bir .NET ortamında çalışırken, kodun yürütülmesinde önemli bir ek yükün bulunduğu donanımın metalinden yeterince uzaktasınız. Bu nedenle, halihazırda kabarma hızından vazgeçtiğinizi ve bunun yerine "doğru" kod yazmak istediğinizi belirten bir ortamda olduğunuz göz önüne alındığında, bir .NET ortamında bir şey gerçekten yeterince hızlı çalışmıyorsa, karmaşıklığı çok yüksek, ya da paralelleştirmeyi düşünmelisiniz. İşte optimizasyon için izlenmesi gereken bazı temel işaretler; Optimizasyondaki verimliliğinizi (harcanan zaman için kazanılan hız) hızlandıracağınızı garanti ediyorum:
- İşlev şeklini değiştirmek, katsayıları değiştirmekten daha önemlidir - WRT Big-Oh karmaşıklığı, bir N 2 algoritmasında uygulanması gereken adım sayısını yarıya düşürebilirsiniz ve yine de yürütüldüğünde bile ikinci dereceden karmaşıklık algoritmasına sahip olursunuz. eskiden yarısı. Bu tür bir sorun için karmaşıklığın alt sınırı buysa, öyle olsun, ancak aynı soruna NlogN, doğrusal veya logaritmik bir çözüm varsa, karmaşıklığı azaltmak için algoritmaları değiştirerek, sahip olduğunuz sorunu optimize etmekten daha fazla kazanacaksınız.
- Karmaşıklığı görememeniz bunun size mal olmadığı anlamına gelmez - Kelimedeki en zarif tek astarların çoğu korkunç performans gösterir (örneğin, Regex prime checker üstel bir karmaşıklık işlevidir, ancak verimli sayının karekökünden daha küçük tüm asal sayılara bölünmesini içeren asal değerlendirme O (Nlog (sqrt (N))) düzenindedir Linq, kodu basitleştirdiği için harika bir kütüphanedir, ancak bir SQL motorunun aksine .Net derleyici, sorgunuzu yürütmenin en etkili yolunu bulmaya çalışmaz.Bir yöntem kullandığınızda ne olacağını ve dolayısıyla bir zincirin daha önce (veya daha sonra) yerleştirilirken neden daha hızlı olabileceğini bilmelisiniz. aynı sonuçlar.
- OTOH, neredeyse her zaman kaynak karmaşıklığı ile çalışma zamanı karmaşıklığı arasında bir dengeye sahiptir - SelectionSort'un uygulanması çok kolaydır; muhtemelen 10LOC veya daha az bir sürede yapabilirsiniz. MergeSort biraz daha karmaşık, Quicksort daha fazla ve RadixSort daha da fazla. Ancak, algoritmalar kodlama karmaşıklığında (ve dolayısıyla "önden" geliştirme süresinde) arttıkça, çalışma zamanı karmaşıklığında azalırlar; MergeSort ve QuickSort NlogN'dir ve RadixSort genellikle doğrusal olarak kabul edilir (teknik olarak NlogM'dir, burada M, N'deki en büyük sayıdır).
- Hızlı kırın - Ucuz olması muhtemel, doğru olması muhtemel olan ve devam edebileceğiniz anlamına gelen bir kontrol varsa, önce bu kontrolü yapın. Örneğin, algoritmanız yalnızca 1, 2 veya 3 ile biten sayıları önemsiyorsa, en olası durum (tamamen rastgele veriler verilir) başka bir basamakla biten bir sayıdır, bu nedenle sayının bitmediğini test edin 1, 2 veya 3'e bakın, sayının 1, 2 veya 3 ile bitip bitmediğini kontrol etmeden önce. Bir mantık parçası A&B gerektiriyorsa ve P (B) = 0,1 iken P (A) = 0,9 ise kontrol edin Önce B, eğer değilse! A sonra! B (beğenmek
if(myObject != null && myObject.someProperty == 1)
) veya B değerlendirmek ( if(myObject != null && some10SecondMethodReturningBool())
) için A'dan 9 kat daha uzun sürer .
- Cevabını zaten bildiğiniz herhangi bir soru sormayın - Bir dizi "düşme" koşulunuz varsa ve bu koşullardan biri veya daha fazlası da kontrol edilmesi gereken daha basit bir koşula bağlıysa, asla ikisini de kontrol etmeyin bunlar bağımsız olarak. Örneğin, A gerektiren bir çekiniz ve A && B gerektiren bir çekiniz varsa, A'yı kontrol etmelisiniz ve eğer doğruysa B'yi kontrol etmelisiniz. Eğer! A, o zaman! A&&B, bu yüzden bile rahatsız etmeyin.
- Bir şeyi ne kadar çok yaparsanız, nasıl yapıldığına daha fazla dikkat etmelisiniz - Bu, gelişimde, birçok düzeyde ortak bir temadır; genel bir gelişme anlamında, "ortak bir görev zaman alıcı veya becerikli ise, daha iyi bir yol bulmak için hem sinirli hem de bilgili olana kadar bunu yapmaya devam edin". Kod terimleriyle, verimsiz bir algoritma ne kadar çok çalıştırılırsa, onu optimize ederek genel performansta o kadar fazla kazanırsınız. İkili bir montaj ve hata ayıklama sembollerini alabilen ve bazı kullanım durumlarından geçtikten sonra en çok hangi kod satırlarının çalıştırıldığını gösteren profil oluşturma araçları vardır. Bu çizgiler ve bu çizgileri yöneten çizgiler, en çok dikkat etmeniz gereken şeydir, çünkü orada elde ettiğiniz verimlilikte herhangi bir artış çoğalır.
- Daha karmaşık bir algoritma, ona yeterince donanım atarsanız daha az karmaşık bir algoritmaya benziyor . Algoritmanızın üzerinde çalıştığınız sistemin (veya bir kısmının) teknik sınırlarına yaklaştığını fark etmeniz gereken bazı zamanlar vardır; daha hızlı olması gerekiyorsa, daha iyi bir donanımda çalıştırarak daha fazla kazanç elde edersiniz. Bu, paralelleştirme için de geçerlidir; bir N 2 , N çekirdek yayınlandığında -complexity algoritması, görünüm doğrusal. Dolayısıyla, yazdığınız algoritma türü için daha düşük karmaşıklığa sahip olduğunuzdan eminseniz, "bölme ve fethetme" yollarını arayın.
- Yeterince hızlı olduğunda hızlı - Belirli bir çipi hedeflemek için elle paketleme tertibatı olmadıkça, her zaman kazanılacak bir şey vardır. Ancak, el paketleme montajı İSTEMİYORSANIZ, müşterinin “yeterince iyi” dediği şeyi daima aklınızda bulundurmalısınız. Yine, "erken optimizasyon tüm kötülüklerin köküdür"; müşteriniz yeterince hızlı aradığında, artık yeterince hızlı olduğunu düşünene kadar işiniz bitti.