Büyük yazılım projenizdeki pratikteki karmaşıklığı nasıl ölçersiniz?


11

Üniversitede algoritma kurslarımızda, karma tablolar veya hızlı sıralama gibi pratikte kullanılan çeşitli basit algoritmaların karmaşıklığını tam olarak nasıl hesaplayacağımızı öğreniyoruz.

Ama şimdi büyük bir yazılım projesinde, daha hızlı hale getirmek istediğimizde, tek yaptığımız tek tek parçalara bakmak -burada daha hızlı bir karma tablo ile değiştirilebilecek birkaç iç içe döngü, burada hızlandırılabilecek yavaş bir arama daha süslü bir teknik- ama asla tüm boru hattımızın karmaşıklığını hesaplamıyoruz.

Bunu yapmanın bir yolu var mı? Yoksa pratikte insanlar küresel olarak uygulamayı bir bütün olarak düşünmek yerine, tüm uygulamayı daha hızlı hale getirmek için hızlı bir algoritma kullanarak "yerel olarak" güveniyorlar mı?

(Bana göre çok hızlı olduğu bilinen çok sayıda algoritmayı biriktirirseniz, bir bütün olarak hızlı bir uygulama ile sonuçlandığınızı göstermek önemsiz gibi görünüyor.)

Bunu soruyorum, çünkü başka birisinin yazdığı büyük bir projeyi hızlandırmakla görevlendirildim, burada çok fazla algoritma etkileşime giriyor ve giriş verileri üzerinde çalışıyor, bu yüzden bana tek bir algoritmayı daha hızlı bir şekilde yapma etkisinin tüm uygulama.


1) Bu, geliştirilecek noktaları bulmak için bir test yaklaşımı gerektirir. Karşılaştırma testi, Dayanıklılık testi, Dinamik test (her bir bileşenin bellek / CPU metriklerini izleyerek). 2) İyileştirilecek noktaları bulduktan sonra, bu noktaların temel nedenini bulacaksınız. 3) Doğruluk sağlayarak kök nedenini çözmek için bir çözüm bulun.
18'de

bu testler için 1.
maddede

1
Big O analizi size bir algoritmanın nasıl performans göstereceğini söylemez. Bu performans nasıl anlatır ölçek olarak, nartar.
John Wu

Yanıtlar:


5

Büyük yazılım projeleri birçok farklı bileşenden oluşur ve bunların tümü tipik olarak bir darboğaz değildir. Tam tersi: düşük performansın bir sorun olduğu hayatımda neredeyse her program için, Pareto prensibi uygulandı: kodun% 20'sinden daha azını optimize ederek performans kazançlarının% 80'inden fazlası elde edilebilir (gerçekte, ben sayıların genellikle% 95'ten% 5'e kadar olduğunu düşünün).

Bu nedenle, bireysel parçalara bakmaya başlamak genellikle en iyi yaklaşımdır. Bu nedenle profilleme ( David Arno'nun cevabında açıklandığı gibi ) iyidir, çünkü optimizasyonun size "paranın en büyük patlamasını" vereceği kodun belirtilen% 5'ini tanımlamanıza yardımcı olur. "Tüm uygulamayı" optimize etmek belirli bir aşırı mühendislik riski taşır ve bu% 95'i 10 katına kadar optimize ederseniz, genellikle ölçülebilir bir etkisi olmaz. Ayrıca, profil oluşturmanın, varsayımsal algoritma karmaşıklık tahmininden çok daha fazlasını söylediğini unutmayın, çünkü O (N ^ 3) adımlarını gerektiren basit bir algoritma, N (sürece) O (N günlüğü (N)) gerektiren karmaşık bir algoritmadan daha hızlı olabilir. yeterince küçük.

Profil oluşturma sıcak noktaları ortaya çıkardıktan sonra, onları optimize edebilir. Tabii ki, bir "etkin nokta" sadece bir veya iki satır koddan daha büyük olabilir, bazen daha hızlı hale getirmek için bir bileşenin tamamını değiştirmek zorunda kalır, ancak bu genellikle daha büyük bir programda kod tabanının küçük bir kısmı olacaktır. .

Tipik optimizasyon teknikleri şunları içerir:

  • algoritma ve veri yapılarının kullanımının iyileştirilmesi

  • öncekinin ince ayarı

  • bazı gerçek sıcak noktalarda mikro optimizasyonlar

  • montaj kodu veya CUDA kullanarak kritik bölümleri yeniden kodlama

Bu tekniklerin, bazıları bir bileşeni diğerlerinden daha "bir bütün olarak" görüntüleyen farklı soyutlama düzeyleri üzerinde çalıştığını unutmayın. Yani "tek yaptığımız tek tek parçalara bakmak" ile ne demek istediğinize bağlı - eğer sadece mikro optimizasyonları aklınızda bulunduruyorsanız, "biz" in sadece bunun üzerinde çalıştığına katılmıyorum. Ancak bu tam ölçekli optimizasyonları yalıtılmış parçalara veya bileşenlere uygulamak istiyorsanız, muhtemelen "biz" den daha doğru parçalar üzerinde çalışıyoruz ve beklentilerinizi sorgulamalısınız.


13

Standart, denenmiş ve test edilmiş yöntem kodu profillemektir . Zamanlamaları, bellek kullanımını vb. Ölçmek için çalışan sistemin dinamik analizini yaparsınız. Daha sonra performans darboğazlarını bulmak için sonuçları analiz edin.

Bu darboğazlar daha sonra deneysel olarak yeniden yazılır ve sonuç bir hız artışı, bellek kullanımında azalma vb. Elde edildiğini belirlemek için bir kez daha profillenir. Bu işlem daha sonra kabul edilebilir bir performans kazancı elde edilene kadar tekrarlanır.


1
Bu, performans problemini çözer, bu yüzden bunu yaparız, ancak orijinal soruyu cevaplamaz. Özellikle en kötü durumda zaman veya uzay karmaşıklığı en iyi eksik olabilir statik bir program analiz aracı kullanılarak çözüleceğini düşünüyorum. Performans testleri belirli senaryolar için mükemmeldir, ancak size en kötü durumlar hakkında fazla bilgi vermezler.
Frank Hileman

3
@FrankHileman Bence burada performans pratik bir endişe ve sadece pratik olarak ölçülebilir. Matematiği (algoritmalar) kullanarak bulduktan sonra çözebilseniz bile, yazılımınızın darboğazını bulmak için matematik kullanmazsınız.
Joker

İlgili bir notta, eski zaman slayt gösterisi sunumunda (cam slaytlar), kullanılacak bir ışığın parlaklığını belirlemek için bir fener lamının ortalama yoğunluğunu matematiksel olarak titizlikle nasıl hesaplayacağına dair tam bir teknoloji vardı. Tamamen işe yaramaz: resim iyi görünmüyorsa, daha parlak bir ışık elde edersiniz!
Joker

@Wildcard Performans yalnızca çalışma zamanında ölçülebilirken, statik olarak tahmin edilebilir. Veri yapısının zayıf bir seçimi, performans testlerinde iyi, performans açısından iyi görünebilir, ancak statik bir analizde tahmin edilebilecek uç durumlarda sefil bir şekilde başarısız olabilir. Genel olarak veri yapıları için en kötü durum karmaşıklık analizlerine bakmamızın nedeni de budur.
Frank Hileman

@Wildcard: haklısın, ancak Frank de bu yazının soruyu cevaplamadığı için çok doğru.
Doc Brown

3

Diğer cevaplar doğru olmasına ve yol göstermesine rağmen, bir adımı kaçırdıklarını düşünüyorum. Şu anda çalıştığınız gibi karmaşık bir sistemde, sistemi oluşturan farklı bileşenleri anlamak, bir şeyin neden yavaş olduğunu anlamanın anahtarıdır.

İlk adım, ayrıntılı bir mimari şemaya ellerimi sokmak veya kendim bir tane oluşturmak olacaktır. Yazılımdaki hangi bileşenler tarafından hangi adımların atıldığını ve her adımın ne kadar sürdüğünü öğrenin.

Ayrıca, bileşenlerin birbirleriyle nasıl etkileşime girdiğini de öğrenin. Bu fark yaratabilir.

Örneğin, iki bileşen arasındaki arabirimin ilk bileşen tarafından oluşturulan bir IEnumerable geçtiği C # kod gördüm, daha sonra ikinci bileşen tarafından numaralandırıldı. C # 'da bu, belirli koşullar altında maliyetli olabilecek bağlam değiştirme gerektirir. Çözmenin algoritma üzerinde hiçbir etkisi yoktur. Basit bir .ToList () yöntemi, sonraki adım bu sorunu çözmeden önce toplandığından emin olun.

Dikkate alınması gereken başka bir şey, kodu çalıştırdığınız sistem üzerindeki etkisidir. Donanım etkileşimleri açıkça karmaşık sistemlerde bir faktör olabilir. Disk G / Ç, Büyük Bellek ayırmaları ve Ağ G / Ç için arama yapın. Bazen bunlar sistemi değiştirerek ve hatta donanımı değiştirerek daha verimli bir şekilde çözülebilir.

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.