Kod yazma metodolojisindeki kademeli değişim sistem performansını etkiledi mi? Ve umursamalı mıyım?


35

TD; DR:

Ne sorduğum konusunda bir karışıklık vardı, işte sorunun arkasındaki itici fikir:

Her zaman soruyu ne olduğu gibi düşünürdüm. Aslen iyi ifade etmemiş olabilirim. Fakat niyet her zaman " modüler, ayrık, gevşek birleştirilmiş, ayrıştırılmış, yeniden yapılandırılmış kod " olmuştur ve " tek parça tek bir yerde her şeyi tek bir yerde, tek bir dosyada, sıkı bir şekilde birleştirilmiş olarak " kodundan daha yavaş bir şekilde kendiliğinden yavaşlatır . Gerisi o zaman ya da şimdi ya da sonra rastlayacağım bunun detayları ve çeşitli tezahürleri. Bazı ölçeklerde kesin olarak daha yavaştır. Birleştirilmemiş disk gibi, parçaları her yerden almanız gerekir. Daha yavaş. Kesinlikle. Ama umursamalı mıyım?

Ve soru bununla ilgili değil ...

mikro optimizasyon, erken optimizasyon vb. hakkında değil. "Bunu veya bu kısmı ölüme göre optimize etmek" ile ilgili değil.

Öyleyse nedir?

Yaklaşık olduğu genel metodoloji ve zamanla ortaya çıkan kodu yazma hakkında teknikleri ve düşünme yolları:

  • "Bu kodu sınıfa bağımlılık olarak sok"
  • "sınıf başına bir dosya yaz"
  • msgstr "görünümünüzü veritabanınızdan, denetleyicinizden, etki alanınızdan ayırın".
  • spagetti homojen tek bir kod bloğu yazmayın, birlikte çalışan birçok modüler bileşen yazın

Bu, şu anda - bu on yıl içinde - çoğu çerçevede görülen ve kabul edilen, sözleşmelerde savunulan ve topluluk aracılığıyla kabul edilen kod tarzı ile ilgilidir. Düşüncede 'monolitik bloklardan' 'mikro servislere' doğru bir değişimdir. Ve bununla birlikte makine düzeyinde performans ve ek yük ve ayrıca bazı programcı düzey ek yükler için fiyat geliyor.

Orijinal soru şöyle:

Bilgisayar Bilimleri alanında, programlamaya gelince düşünmede kayda değer bir değişim olduğunu fark ettim. Tavsiyeye oldukça sık rastlanıyorum.

  • daha küçük fonksiyon kodunu yazın (bu şekilde daha test edilebilir ve bakımı yapılabilir)
  • refactor var olan kodu daha küçük ve daha küçük kod parçalarına dönüştürün, yöntem / fonksiyonlarınızın çoğu sadece birkaç satır uzunluğa ve amaçlarının ne olduğu açıktır (daha büyük bir monolitik bloğa kıyasla daha fazla fonksiyon yaratan)
  • Sadece tek bir şey yapan fonksiyonlar yazınız - endişelerin ayrılması vs.
  • daha fazla dosya oluşturun (dosya başına bir sınıf, ayrıştırma amacıyla daha fazla sınıf, MVC, etki alanı mimarisi, tasarım kalıpları, OO, vb. gibi daha fazla dosya sistemi çağrısı yaratan katman amaçları için)

Bu, 2500 satırlık yöntemlere, büyük sınıflara ve tanrı nesnelerine her şeyi yapan "eski" veya "eski" veya "spagetti" kodlama uygulamalarına kıyasla bir değişiklik.

Sorum şu:

çağrı makine koduna, 1s ve 0'lara, montaj talimatlarına, HDD plakasına geldiğinde, tamamen yeniden yapılandırılmış küçükten küçüğe fonksiyonlar ve yöntemler içeren mükemmel sınıf-ayrımlı OO kodumun da ortaya çıkmasından kaygılanmalı mıyım? Fazladan ek yük?

ayrıntılar

Sonunda OO kodunun ve yöntem çağrılarının ASM'de nasıl ele alındığını ve DB aramalarının ve derleyici çağrılarının bir HDD tablasındaki hareketli aktüatör koluna nasıl çevrildiğini yakından bilmesek de, bir fikrim var. Her ekstra işlev çağrısının, nesne çağrısının veya "#include" çağrısının (bazı dillerde) ek komutlar oluşturduğunu ve böylece kodun hacmini artırdığını ve gerçek "kullanışlı" kod eklemeden çeşitli "kod kablolaması" ek yükleri eklediğini düşünüyorum. . Ayrıca, gerçekten donanımda çalıştırılmadan önce ASM'de iyi optimizasyonların yapılabileceğini, ancak optimizasyonun yalnızca bu kadar da yapabileceğini hayal ediyorum.

Bu nedenle, benim sorum - ne kadar ek yük (boşlukta ve hızda) iyi ayrılmış kod (yüzlerce dosya, sınıf ve tasarım desenleri, vb. tek bir dosyada her şey ", bu ek yük nedeniyle mi?

Netlik için GÜNCELLEME:

Aynı kodu almanın ve bölmenin, yeniden düzenlemenin, daha fazla fonksiyona ve nesneye, yönteme ve sınıfa ayırmaya başlamanın, daha küçük kod parçaları arasında daha fazla parametre geçirmesine neden olacağını varsayıyorum . Çünkü kesin olarak, yeniden düzenleme kodunun iş parçacığını devam ettirmesi gerekir ve bu parametre geçirmeyi gerektirir. Daha fazla yöntem veya daha fazla sınıf veya daha fazla Fabrika Yöntemi tasarım deseni tasarlar, tek bir yekpare sınıf veya yöntemde olduğundan daha fazla bilgiyi geçmenin daha fazla yükü ile sonuçlanır .

Bir yerde (TBD'den alıntı), tüm kodun% 70'inin ASM'nin MOV komutundan oluştuğu söylendi - gerçek CPU işlemlerini yapmadan değil, uygun değişkenlerle yükleme CPU kayıtları yapıldı. Benim durumumda, çeşitli kod parçaları arasında bağlantı ve parametre iletimi sağlamak için CPU zamanını PUSH / POP komutları ile yüklersiniz. Kodunuzu ne kadar küçük yaparsanız, daha fazla ek "bağlantı" gereklidir. Bu bağlantının yazılımın yavaşlamasına ve yavaşlamasına yol açmasından endişe duyuyorum ve bununla ilgili endişelenmem gerekip gerekmediğini ve eğer varsa, ne kadar olsa, gelecek yüzyıl için yazılım geliştiren programcıların şu anki ve gelecekteki programcıları için merak ediyorum. , bu uygulamaları kullanarak oluşturulmuş yazılımlarla yaşamak ve bunları tüketmek zorunda kalacak.

GÜNCELLEME: Birden fazla dosya

Şimdi yavaş yavaş eski kodu değiştiriyor yeni kod yazıyorum. Özellikle, eski sınıflardan birinin (daha önce belirtildiği gibi) ~ 3000 satırlık bir dosya olduğunu not ettim. Şimdi bazı dosyaları bir araya getirmek için kullanıyorum, test dosyaları dahil ve PHP çerçevesi dahil değil, çeşitli dizinlerde bulunan 15-20 dosyadan oluşan bir set haline geliyor. Daha fazla dosya da geliyor. Disk G / Ç'ye geldiğinde, birden fazla dosya yüklemek, büyük bir dosyayı yüklemekten daha yavaştır. Tabii ki tüm dosyalar yüklenmiyor, gerektiğinde yükleniyor ve disk önbellekleme ve bellek önbellekleme seçenekleri mevcut ve yine de bunun bellekten loading multiple filesdaha fazla işlem gerektirdiğine inanıyorum loading a single file. Bunu endişeme ekliyorum.

GÜNCELLEME: Bağımlılık Her şeyi enjekte

Bir süre sonra buna geri döneceğim. Sanırım sorum yanlış anlaşıldı. Ya da belki bazı cevapları yanlış anlamayı seçtim. Bazı cevaplar öne sürüldüğü için mikro-optimizasyondan bahsetmiyorum, (en azından mikro optimizasyon hakkında konuştuğum şeyi aramak bir yanlış isimdir diye düşünüyorum) değil, bir bütün olarak "Refactor code" u sıkı bağlantıyı gevşetmek için , kodun her seviyesinde. Zend Con'dan kısa bir süre önce, bu kod tarzının konvansiyonun temel noktalarından ve merkezlerinden biri olduğu yerlerde geldim. Mantıktan görünümden ayır, modelden görünüm, veritabanından model ve yapabilirseniz, veritabanından verileri ayır. Bağımlılık-Enjekte Her şeyi, bazen sadece hiçbir şey yapmadan kablolama kodu (fonksiyonlar, sınıflar, boylerler) eklemek anlamına gelir, ancak çoğu durumda kod boyutunu iki katına çıkararak bir dikiş / kanca noktası görevi görür.

GÜNCELLEME 2: "Kodu daha fazla dosyaya ayırma" performansı (tüm bilgisayar düzeylerinde) önemli ölçüde etkiler

compartmentalize your code into multiple filesGünümüz bilgisayarını etkileme felsefesi (performans, disk kullanımı, bellek yönetimi, CPU işleme görevleri) nasıl etkiliyor?

hakkında konuşuyorum

Önce...

Varsayımsal olarak henüz oldukça gerçek o kadar uzak geçmişte, kolayca modelini ve görünümü ve denetleyici spagetti ya sahiptir yapan bir dosyanın bir mono-blok yazabilirsiniz değil-spagetti kodlu, ama bu ishal her şey zaten yüklendikten sonra. Geçmişte bazı kriterleri C kodunu kullanarak yapıyorum Tek bir 900Mb dosyayı belleğe yüklemek ve onu büyük parçalarda işlemek çok daha küçük dosyaları yüklemek ve onları daha küçük bir barış-yemeğinde işlemekten çok daha hızlı olduğunu öğrendim. sonunda aynı işi yapan topaklar.

.. Ve şimdi*

Bugün kendimi bir defter gösteren, .. .. bir öğe bir "sipariş" ise, sıralı HTML bloğunu gösteren .. gibi özelliklere sahip bir kod arıyorum. Bir satır öğesi kopyalanabiliyorsa, bir simge görüntüleyen HTML bloğunu ve arkasındaki HTML parametrelerini kopyalayarak yazdırmanızı sağlar. Öğe yukarı veya aşağı taşınabilirse, uygun HTML oklarını görüntüleyin. Vc Yapabilirsiniz, Zend Framework aracılığıyla oluşturmakpartial()aramalar, esasen "parametrelerinizi alan ve onları da çağırdığı ayrı bir HTML dosyasına ekleyen bir işlev çağırın" anlamına gelir. Ne kadar ayrıntılı olmak istediğime bağlı olarak, defterin en küçük kısımları için ayrı HTML işlevleri oluşturabilirim. Biri yukarı ok, aşağı ok, diğeri "bu öğeyi kopyalayabilir miyim" vb. Web sayfasının küçük bir bölümünü görüntülemek için kolayca birkaç dosya oluşturabilirsiniz. Kodumu ve perde arkası Zend Framework kodunu alan sistem / yığın muhtemelen 20-30 farklı dosyaya yakın.

Ne?

Kodları daha küçük birçok ayrı dosyaya bölmek suretiyle oluşturulan makinenin aşınması ve yıpranması ile ilgileniyorum .

Örneğin, daha fazla dosya yüklemek, onları dosya sisteminin çeşitli yerlerinde ve çeşitli fiziksel HDD'lerde konumlandırmak anlamına gelir; bu, daha fazla HDD'nin daha fazla arama ve okuma süresi anlamına gelir.

CPU için muhtemelen daha fazla bağlam anahtarlama ve çeşitli kayıtları yükleme anlamına gelir.

Bu alt blokta (güncelleme # 2), tek bir dosyada yapılabilecek aynı işleri yapmak için birden fazla dosyayı kullanmanın sistem performansını nasıl etkilediğine daha fazla ilgi duyuyorum.

Zend Form API vs basit HTML kullanımı

Zend Form API’yı en son ve en büyük modern OO uygulamalarıyla kullandım, onaylı bir HTML formu oluşturup POSTetki alanı nesnelerine dönüştürme yaptım .

Bunu yapmak için bana 35 dosya aldı.

35 files = 
    = 10 fieldsets x {programmatic fieldset + fieldset manager + view template} 
    + a few supporting files

Hepsi birkaç basit HTML + PHP + JS + CSS dosyasıyla, belki de toplam 4 hafif dosyayla değiştirilebilir.

Daha iyi mi? Değer mi? ... 35 dosya + çok sayıda Zend Zramework kütüphane dosyasını, çalışmasını sağlayan 4 basit dosyaya yüklediğinizi hayal edin.


1
Harika bir soru. Bazı kıyaslamalar yapacağım (bazı iyi davalar bulmak için beni bir güne kadar götür). Bununla birlikte, bu derecedeki hız artışları okunabilirlik ve geliştirme maliyetlerine büyük bir maliyet getirmektedir. Benim ilk tahminim, sonucun önemsiz performans kazancı olduğu.
Dan Sabin,

7
@Dan: Lütfen 1, 5 ve 10 yıllık bakımdan sonra kodu karşılaştırmak için takviminize ekleyebilir misiniz? Hatırlıyorum eğer sonuçları tekrar kontrol edeceğim :)
mattnz

1
Evet, bu gerçek öldürücü. Bence hepimiz daha az arama yapmayı kabul ediyoruz ve fonksiyon çağrıları daha hızlı. Ancak bunun, yeni ekip üyelerini kolayca ve kolayca eğitmek gibi şeylere tercih edildiğini düşünemiyorum.
Dan Sabin

2
Netleştirmek için projeniz için özel hız gereksinimleriniz var mı? Yoksa sadece kodunuzun "daha hızlı gitmesini" mi istiyorsunuz? En son endişe duymazsam, yeterince hızlı ancak bakımı kolay olan kod, yeterince hızlı olandan daha hızlı ancak bir karışıklıktan çok daha iyidir.
Cormac Mulhall

4
İşlevden kaçınma fikri, performansın nedenlerinden dolayı, Dijkstra'nın olgunlaşma öncesi optimizasyon konusundaki meşhur alıntılarında kullandığı saçma sapan bir düşünce türü. Cidden, yapamam
RibaldEddie

Yanıtlar:


10

Sorum şu: makine kodu, 1s ve 0'lara, montaj talimatlarına gelince, küçükten küçüğe kadar çeşitli fonksiyonlara sahip sınıftan ayrılan kodumun fazladan ek yük ürettiğinden endişelenmeli miyim?

Cevabım evet, yapmalısın. Çok fazla küçük işleviniz olmadığı için (bir zamanlar çağıran işlevlerin ek yükü oldukça önemliydi ve programlarınızı döngülere bir milyon küçük çağrı yaparak yavaşlatabilirsiniz, ancak bugün derleyiciler onları sizin için ve geriye kalanları alırlar. CPU fantezi tahmin algoritmalarına dikkat etmek, bunun için endişelenmeyin), çünkü fonksiyonellik kafanızda hassas şekilde kırılmayacak kadar küçük olduğunda, programlarınıza çok fazla katman katma kavramı sunacaksınız. Eğer daha büyük bileşenlere sahipseniz, aynı işi tekrar tekrar gerçekleştirmediklerinden oldukça emin olabilirsiniz, ancak programınızı o kadar ayrıntılı hale getirebilirsiniz ki, kendinizi arama yollarını gerçekten anlayamadığınızı ve bununla sonuçlandığını görebilirsiniz. Bu ancak çalışır (ve bakım gerektirmez).

Örneğin, bana bir web hizmeti için referans proje gösteren bir yerde 1 yöntemle çalıştım. Proje 32.cs dosyadan oluşuyordu - tek bir web servisi için! Bunun çok fazla karmaşıklık olduğunu düşündüm, her bölüm küçük ve kolay bir şekilde anlaşılmış olsa da, genel sistemi tarif etmeye gelince, hemen ne yaptığını görmek için çağrıları takip etmek zorunda kaldım. Ayrıca, beklediğiniz gibi çok fazla soyutlama yapılmıştı. Yeni web servisim 4 .cs dosyadı.

Performansta kabaca aynı olacağını düşündüğüm gibi performansı ölçmedim, ancak madenin sürdürülmesinin çok daha ucuz olduğunu garanti edebilirim. Herkes programlayıcı zamanın CPU zamanından daha önemli olduğunu söylerken, hem geliştirmede hem de bakımda çok sayıda programcı zamana mal olan karmaşık canavarlar yaratır ve bunun kötü davranış için mazeret yarattığını merak etmeniz gerekir.

Bir yerde (TBD'den alıntı), tüm kodun% 70'inin ASM'nin MOV komutundan oluştuğu söylendi - gerçek CPU işlemlerini yapmadan değil, uygun değişkenlerle yükleme CPU kayıtları yapıldı.

Yani edilir CPU'lar olsa gördüklerini sicillere bellekten bitleri taşıyın eklemek veya bunları çıkarmak ve sonra belleğe geri koydu. Bütün hesaplamalar buna bağlı olarak azalır. Unutmayın, bir zamanlar zaman bağlamında anahtarlamayı (örneğin, kayıtların dişlilerin durumunu kaydetme ve geri yükleme) iş parçacığı kodu üzerinde çalışarak geçiren çok iş parçacıklı bir programım vardı. Yanlış yerdeki basit bir kilit, orada gerçekten performansı bozdu ve çok da masum bir kod parçasıydı.

Bu yüzden benim tavsiyem: kodunuzun diğer insanlara iyi görünmesini sağlayan uç noktalardan herhangi birinin arasında makul bir orta yol bulun ve iyi çalışıp çalışmadığını görmek için sistemi test edin. İşlemci, bellek, disk ve ağ IO ile beklediğiniz gibi çalıştığından emin olmak için işletim sistemi özelliklerini kullanın.


Bence şu anda bu en çok benim için konuşuyor. Bana göre, iyi bir orta yol, ezoterik kod ayrıştırma ve çıldırmış fındık (örn. İhtiyacınız olan her şey DI ile bağlanmak yerine) takip ederken ve bazı kavramları (DI gibi) kullanırken kodlama parçalarına zihin haritalama kavramlarıyla başlamaktır. o ya da değil).
Dennis

1
Şahsen, daha "" modern "" kodun profil için biraz daha kolay olduğunu düşünüyorum ... Sanırım kodun daha kolay korunabilir bir parçası, profillemesi de daha kolay, ama küçük parçalara ayırmanın onları sınırladığı bir sınır var. daha az bakım gerektirmez ...
AK_

25

Aşırı özen göstermeden, bu endişeler gibi mikro optimizasyon sürdürülemez kodlara yol açar.

Başlangıçta iyi bir fikir gibi görünüyor, profiler size kodun daha hızlı olduğunu söylüyor ve V & V / Test / QA bile çalıştığını söylüyor. Yakında böcekler bulunur, gereksinimler değişmez ve asla dikkate alınmayan geliştirmeler istenir.

Bir proje kodunun ömrü boyunca bozulur ve daha az verimli hale gelir. Bakım kodu daha yavaş düşeceği için sürdürülemez emsalinden daha verimli hale gelecektir. Bunun nedeni, kod değiştikçe entropi oluşturur -

Anlaşılmaz kodun hızlı bir şekilde daha fazla ölü kodu, yedek yolları ve çoğaltması vardır. Bu, daha fazla hataya yol açar ve performansı da dahil olmak üzere kodun bir bozulma döngüsü yaratır. Çok geçmeden, geliştiriciler yaptıkları değişikliklerin doğru olduğuna dair güvenleri düşük. Bu onları yavaşlatır, temkinli yapar ve yalnızca görebildikleri ayrıntıya değindikleri için genellikle daha entropiye yol açar.

Küçük modüller ve ünite testleriyle bakımı yapılabilir kodların değiştirilmesi kolaydır, artık gerekmeyen kodların tanımlanması ve kaldırılması kolaydır. Bozulan kodun tanımlanması daha kolaydır, tamir edilebilir veya güvenle değiştirilebilir.

SO sonunda, yaşam döngüsü yönetimine giriyor ve “bu daha hızlı, bu yüzden her zaman daha hızlı olacak” kadar basit değil.

Hepsinden önemlisi, yavaş doğru kod hızlı yanlış koddan kademesiz daha hızlıdır.


Thankx. Gittiğim yere biraz sürmek için, mikro-optimizasyondan değil, daha küçük kod yazmaya, daha fazla bağımlılık enjeksiyonunu ve dolayısıyla daha fazla işlevsellik parçasını ve genel olarak kodun daha fazla "hareketli kısmını" içeren daha fazla kod içeren doğru bir hareketten bahsetmiyorum. hepsinin birlikte çalışması için birbirine bağlı olması gerekir. Bunun donanım seviyesinde daha fazla bağlantı / konektör / değişken geçiş / MOV / PUSH / POP / CALL / JMP havlaması ürettiğini düşünmeye meyilliyim. Ayrıca, "kabartmak" için donanım düzeyinde bilgi işlem döngülerinden fedakarlık pahasına olmasına rağmen, kod okunabilirliğine doğru bir değer görüyorum.
Dennis,

10
İşlevlerden kaçınmak performans nedenlerinden dolayı kesinlikle bir mikro-optimizasyondur! Ciddi anlamda. Daha iyi bir mikro-optimizasyon örneği düşünemiyorum. Performans farkının aslında yazdığınız yazılım türü için önemli olduğuna dair hangi kanıtınız var? Hiç yokmuş gibi geliyor.
RibaldEddie

17

Anladığım kadarıyla, inline işaret ettiğiniz gibi, C ++ gibi daha düşük seviyeli kod biçimlerinde bir fark yaratabilir, ancak hafifçe CAN diyebilirim.

Web sitesi özetliyor - kolay bir cevap yok . Bu sisteme, uygulamanızın ne yaptığına, dile bağlı, derleyiciye ve optimizasyona bağlı.

C ++ örneğin, satır içi performansı artırabilir. Çoğu zaman hiçbir şey yapamayabilir ya da performansı düşürebilir, ancak hikayeleri duyduğum halde şahsen hiç karşılaşmadım. Satır içi, derleyici için optimize edilebilecek bir öneriden başka bir şey değildir;

Muhtemelen, eğer daha yüksek seviyeli programlar geliştiriyorsanız, başlangıçta bir tane varsa genel gider endişelenmemelidir. Derleyiciler bugünlerde oldukça zekidir ve yine de bu şeylerle ilgilenmelidir. Pek çok programcının aşağıdakileri yapması gereken kodları vardır: hiçbir zaman derleyiciye güvenme. Bu sizin için geçerliyse, önemli olduğunu düşündüğünüz hafif optimizasyonlar bile olabilir. Ancak, aklınızda bulundurun, her dil bu açıdan farklıdır. Java çalışma zamanında otomatik olarak satır içi optimizasyon yapar. Javascript'te, web sayfanızın satır içi (ayrı dosyalara karşılık olarak) bir destekleyici olması ve bir web sayfasının milisaniyesinin bir sayacı sayılabilir, ancak bu bir IO sorunudur.

Ancak, programcının çok fazla makine kodu yaptığı C ++ gibi bir programla çalıştığı daha düşük seviyeli programlarda, kulak misafiri tüm fark yaratabilir. Oyunlar, özellikle konsollarda CPU boru hatlarının kritik olduğu yerlere iyi bir örnektir ve satır içi gibi bir şey burada ve orada biraz ekleyebilir.

Özellikle satır içi iyi bir okuma: http://www.gotw.ca/gotw/033.htm


Sorumumun bakış açısından bakıldığında, seh başına inline etmeye değil, CPU'nun, veriyolunun ve çeşitli kod parçalarını birbirine bağlayan G / Ç'nin zaman sürecini alan “kodlanmış kablolama” ya odaklandım. Kablolama kodunun% 50 veya daha fazlasının ve çalıştırmak istediğiniz gerçek kodun% 50'sinin olduğu bir nokta olup olmadığını merak ediyorum. İnsanın yazabileceği en katı kodda bile çok fazla kabartı olduğunu hayal ediyorum ve hayatın bir gerçeği gibi görünüyor. Bit ve bayt düzeyinde çalışan gerçek kodun çoğu lojistiktir - değerleri bir yerden bir yere taşımak, bir yere veya başka bir yere atlamak ve sadece bazen ekleme yapmak ..
Dennis

... çıkarma veya diğer işle ilgili işlev. Tıpkı döngü açma, değişkenleri artırmak için ayrılan daha az ek yük nedeniyle bazı döngüleri hızlandırabilir gibi, daha büyük işlevler yazmak, kullanım durumunuz için ayarlanmış olması koşuluyla büyük olasılıkla biraz hız ekleyebilir. Buradaki endişelerim daha genel, daha küçük kod parçaları yazmak için birçok öneri görmek, bu kablolamayı arttırırken, okunabilirlik (umarım) ve mikro düzeyde şişkinlik pahasına faydalanmaktan yararlanıyor.
Dennis,

3
@Dennis - göz önünde bulundurulması gereken bir husus, bir OO dilinde, programcının yazdıkları (a + b) ile hangi kodun üretildiği arasında çok az bir korelasyonun olabileceğidir (basit bir iki kayıt eki? sonra işlev bir nesnenin operatörüne çağırır +?). Bu nedenle, programcı seviyesindeki 'küçük fonksiyonlar', bir zamanlar makine koduna dönüştürülmüş küçük bir şey olabilir.
Michael Kohne

2
@Dennis, Windows için ASM kodu yazmanın (doğrudan, derlenmemiş) "mov, mov, invoke, mov, mov, invoke" satırları boyunca olduğunu söyleyebilirim. Push / pops ile çağrılan bir çağrı yapan bir makro olmak çağrısında bulunurken ... Bazen kendi kodunuzda işlev çağrıları yaparsınız, ancak tüm işletim sistemi çağrıları tarafından cüce edilir.
Brian Knoblauch

12

Bu, 2500 satırı kapsayan yöntemlerin ve her şeyi yapan büyük sınıfların kullanıldığı "eski" veya "kötü" kod uygulamalarına kıyasla bir değişikliktir.

Bunu yapmayı düşünen birinin iyi bir uygulama olduğunu sanmıyorum. Bunu yapan insanlardan performans nedenleriyle şüphe duyuyorum.

Donald Knuth'un ünlü alıntılarının burada çok alakalı olduğunu düşünüyorum:

Küçük etkinlikleri unutmalıyız, zamanın% 97'sini söyleyelim: erken optimizasyon tüm kötülüklerin köküdür.

Bu nedenle, kodunuzun% 97'sinde, yalnızca iyi uygulamaları kullanın, küçük yöntemler yazın (ne kadar küçük olursa olsun, tüm yöntemlerin sadece birkaç satır olması gerektiğini düşünmüyorum) vb. fark eder, ölç . Ölçümler, birçok küçük yönteme sahip olmanın kodunuzu önemli ölçüde yavaşlattığını gösteriyorsa, bunları daha büyük yöntemlerle birleştirmelisiniz. Ancak, daha hızlı olabileceği için sürdürülemez kod yazmayın .


11

Güncel düşünmenin yanı sıra deneyimli programcıları da dinlerken dikkatli olmalısınız. Yıllarca devasa bir yazılımla uğraşan insanların katkıda bulunacakları var.

Tecrübelerime göre, işte yavaşlamalara neden olan şey, ve küçük değiller. Onlar büyüklük düzenleridir:

  • Herhangi bir kod satırının, diğerlerine göre kabaca zaman alacağı varsayımı. Örneğin, cout << endlkarşı a = b + c. İlki, ikincisinden binlerce kat daha uzun sürüyor. Stackexchange'in "Bu kodu optimize etmenin farklı yollarını denedim, ancak bir fark yaratmıyor, neden olmasın?" Şeklinde bir sürü soru var. ortasında büyük bir işlev çağrısı yapıldığında.

  • Herhangi bir fonksiyon veya yöntemin bir kez yazıldığı zaman, elbette gerekli olduğu varsayımı gereklidir. İşlevler ve yöntemler aramak kolaydır ve arama genellikle oldukça etkilidir. Sorun şu ki kredi kartı gibi. İstediğinizden daha fazla harcamaya özendiriyorlar ve harcadıklarınızı gizleme eğilimindeler. Bunun da ötesinde, büyük yazılım soyutlama katmanları üzerinde katmanlara sahiptir, bu nedenle her katmanda yalnızca% 15 atık olsa bile, 5 kattan fazla olan ve yavaşlayan bir faktör 2 olan bileşikler. daha büyük fonksiyonlar, bu problem için nöbetçi olmak ve onu kökten çıkarmak için istekli olmak ve kendinizi disiplin altına almaktır .

  • Dörtnala genelliği. Soyutlamanın değeri, daha az kodla daha fazlasını yapmanıza izin verebilmesidir - en azından umut budur. Bu fikir aşırı uçlara itilebilir. Çok fazla genelliğe sahip olan sorun, her sorunun özel olduğudur ve bunu genel soyutlamalar ile çözdüğünüzde, bu soyutlamalar, probleminizin belirli özelliklerinden yararlanamaz. Örneğin, uzunluğunu asla geçmediğinde büyük boyutlarda etkili olabilecek süslü bir öncelik sırası sınıfının kullanıldığı bir durum gördüm!

  • Dörtnala veri yapısı. OOP çok faydalı bir paradigmadır, ancak veri yapısını en aza indirgemek için birisini teşvik etmemektedir - bunun yerine birisinin karmaşıklığını gizlemeye çalışmasını teşvik etmektedir. Örneğin, eğer A noktası bir şekilde değiştirilirse, A, B ve C'nin de bütün topluluğu tutarlı tutması için kendilerini değiştirebilecekleri bir bildirim olayı yayınlarsa, “bildirim” kavramı vardır. Bu, birçok katmana yayılabilir ve modifikasyonun maliyetini büyük ölçüde büyütebilir. Öyleyse, A’daki değişimin kısa bir süre sonra geri alınabilmesi tamamen olasıdır.veya başka bir değişiklikle değiştirildi; bu, topluluğu tutarlı tutmaya çalışmak için harcanan çabanın bir kez daha yapılması gerektiği anlamına geliyor. Tüm bu bildirim işleyicilerindeki hatalar ve döngüsellik vb. Bu karışıklık, veri yapısını normalleştirilmiş tutmaya çalışmaktan daha iyidir, böylece herhangi bir değişikliğin sadece bir yerde yapılması gerekir. Normalize edilmemiş verilerden kaçınılması mümkün değilse, tutarsızlığı gidermek için periyodik geçişlerin yapılması daha iyidir, kısa bir tasma ile tutarlı tutulması gibi davranmak yerine.

... daha fazlasını düşündüğümde ekleyeceğim.


8

Kısa cevap "evet". Ve genel olarak, kod biraz daha yavaş olacaktır.

Ancak bazen uygun bir OO-ish refactoring, kodu daha hızlı yapan optimizasyonları ortaya çıkarır. Karmaşık bir Java algoritması yaptığımız bir projede çok daha fazla OO-ish, nesnelerin dağınık iç içe dizileri yerine uygun veri yapıları, alıcılar vb. İle çalıştım. Ancak veri yapılarına erişimi daha iyi izole ederek ve kısıtlayarak, Double’nun dev dizilerinden (boş sonuçlar için boş), boş sonuçlar için NaN’ler ile daha organize çiftler dizisine geçebildik. Bu, hızda 10 kat kazanç sağlamıştır.

Zeyilname: Genel olarak, daha küçük, daha iyi yapılandırılmış bir kod, büyük hızlandırmalar elde etmenin en iyi yolunu oluşturan çok iş parçacıklığa daha uygun olmalıdır.


1
Neden Doubles’den s’ye geçiş yapmak doubledaha iyi yapılandırılmış kod gerektiriyor anlamıyorum .
svick

Vay, bir aşağı oy? Orijinal Müşteri kodu, Double.NaN'ler ile ilgilenmedi, ancak boş değerleri temsil etmek için boşları kontrol ediyordu. Yeniden yapılanmadan sonra, bunu (kapsülleme yoluyla) çeşitli algoritma sonuçlarının alıcıları ile halledebiliriz. Elbette, müşteri kodunu yeniden yazabilirdik, ama bu daha kolaydı.
user949300

Kayıt için, bu cevabı düşüren ben değildim.
svick

7

Diğer şeylerin yanı sıra programlama, takaslar ile ilgilidir . Bu gerçeğe dayanarak, evet cevabını veriyorum, daha yavaş olabilirdi . Ama karşılığında ne elde edeceğini düşün. Okunabilir, yeniden kullanılabilir ve kolayca değiştirilebilir bir kod elde etmek olası tüm dezavantajlara kolayca ağır basmaktadır.

@ User949300'de belirtildiği gibi, bu yaklaşımla algoritmik veya mimari olarak iyileştirilebilecek alanları tespit etmek daha kolaydır; Bu genellikle çok daha faydalı ve etkili olmaması kadar olan iyileştirilmesi mümkün OO veya işlev-çağırarak havai (zaten sadece bir gürültüdür hangi ı bahis).


Ayrıca, gerçekten donanım üzerinde çalıştırılmadan önce ASM için iyi optimizasyonlar yapılabileceğini hayal ediyorum.

Ne zaman bir şey bundan hoşlanırsa aklımdan geçerse, derleyiciler üzerinde çalışan en akıllı insanların harcadığı on yılların GCC gibi araçları makine kodu üretmekte benden daha iyi yaptığını hatırlıyorum. Mikrodenetleyicilerle ilgili bir tür şey üzerinde çalışmazsanız, endişelenmenize gerek yok.

Bir kodda gittikçe daha fazla işlev ve gittikçe daha fazla nesne ve sınıf eklenmesinin daha küçük kod parçaları arasında daha fazla parametre geçişine neden olacağını varsayıyorum.

En iyileştirme sırasında bir şeyin zaman kaybı olduğunu varsayarsak, kod performansı hakkında gerçeklere ihtiyacınız vardır. Programladığınız yeri çoğu zaman özel araçlarla harcadığınızı bulun, optimize edin, yineleyin.


Hepsini özetlemek için; Derleyicinin işini yapmasına izin verin, algoritmalarınızı ve veri yapılarını iyileştirme gibi önemli şeylere odaklanın. Sorunuzda bahsettiğiniz tüm desenler size yardımcı olmak için var, onları kullanın.

Not: Bu 2 Crockford'un konuşması kafamın içine fırladı ve sanırım biraz akraba olduklarını düşünüyorum. Birincisi, süper kısa bir CS tarihidir (bu, her zaman kesin bir bilim ile bilmek her zaman iyidir); İkincisi, neden iyi şeyleri reddettiğimizle ilgili.


Bu cevabı en çok sevdim. İnsanlar ikinci sırada derleyiciyi tahmin etmekte ve darboğazların olduğu yerde çekim yapmakta korkunç. Elbette, büyük-O zaman karmaşıklığı, farkında olmanız gereken bir şeydir, ancak büyük 100-sıralı spagetti metodu vs bir fabrika metodu çağrısı + bazı sanal metotların gönderilmesi asla bir tartışma olmamalıdır. Bu durumda performans hiç de ilginç değil. Ayrıca, zor gerçekler ve ölçümler olmadan "optimize etmenin" zaman kaybı olduğunu unutmayın.
sara,

4

Tanımladığınız trendlerin yazılım geliştirme konusunda bir gerçeğe işaret ettiğini düşünüyorum - programcı zamanı CPU zamanından daha pahalıdır. Şimdiye kadar, bilgisayarlar yalnızca daha hızlı ve daha ucuz hale geldi, ancak binlerce uygulama saati değişmezse yüzlerce zaman alabilir. Maaşların, sosyal hakların, ofis alanlarının vb. Maliyetleri göz önüne alındığında, biraz daha yavaş işleyebilecek kodun olması daha düşük maliyetlidir ancak değiştirilmesi daha hızlı ve daha güvenlidir.


1
Kabul ediyorum, ancak mobil cihaz o kadar popüler hale geliyor ki, büyük bir istisna olduğunu düşünüyorum. İşlem gücü artmasına rağmen, bir iPhone uygulaması oluşturamaz ve bir web sunucusunda olduğu gibi bellek ekleyebilmeyi beklersiniz.
JeffO

3
@JeffO: Ben katılmıyorum - Dört çekirdekli işlemcili mobil cihazlar artık normal, performans (özellikle pil ömrünü etkilediği için), bir endişe ise kararlılıktan daha az önemli. Yavaş bir cep telefonu veya tablet kötü eleştiriler alır, dengesiz olduğu kesilir. Mobil uygulamalar çok dinamiktir, neredeyse her gün değişiyor - kaynağın yetişmesi gerekiyor.
mattnz

1
@JeffO: Buna değer, Android'de kullanılan sanal makine oldukça kötü. Kıyaslama ölçütlerine göre, yerel yasalara göre daha yavaş bir büyüklük sırası olabilir (cinsin en iyisi genellikle biraz daha yavaştır). Biliyor musun, kimsenin umurunda değil. Uygulamanın yazılması hızlıdır ve CPU orada oturur ve başparmaklarını sallar ve yine de zamanın% 90'ını kullanıcı girişi bekler.
Jan Hudec

Ham CPU benchmarklarından daha fazla performans var. Android telefonum, AV'nin bir güncelleme taradığı ve daha sonra istediğimden daha uzun süre beklediği ve dört çekirdekli 2 GB RAM modelinde olduğu durumlar dışında iyi çalışıyor! Bugün bant genişliği (ağ veya bellek) muhtemelen ana tıkanıklıktır. Süper hızlı işlemciniz muhtemelen% 99'unun başparmaklarını değiştiriyor ve genel deneyim hala zayıf.
gbjbaanb

4

Pekala 20+ yıl önce, yeni ve "eski ya da kötü" olarak adlandırılmadığınızı tahmin ettiğim kural, işlevleri yazdırılan bir sayfaya sığacak kadar küçük tutmaktı. Daha sonra nokta vuruşlu yazıcılarımız vardı, bu yüzden satır sayısı genellikle sayfa başına satır sayısı için yalnızca bir ya da iki seçenek vardı, kesinlikle 2500 satırdan az.

Sorunun bir çok yönünü soruyorsunuz, sürdürülebilirlik, performans, test edilebilirlik, okunabilirlik. Performansa ne kadar çok eğilirseniz, kod o kadar az korunabilir ve okunabilir hale gelir, bu nedenle her bir programcı için değişebilecek ve değişecek olan konfor seviyenizi bulmanız gerekir.

Derleyici tarafından üretilen kod (makine kodu) ne kadar büyük olursa, işlev o kadar büyük olur, kayıtlardaki ara değerleri yığına dökmek için ihtiyaç daha fazla olur. Yığın çerçeveler kullanıldığında, yığın tüketimi daha büyük boyutlardadır. İşlevler ne kadar küçük olursa, kayıtlarda veride o kadar fazla fırsat kalır ve yığına o kadar az bağımlı olur. Doğal olarak işlev başına daha küçük yığın yığınları gerekir. Yığın çerçevelerin performans için artıları ve eksileri vardır. Daha küçük fonksiyonlar, daha fazla fonksiyon kurulumu ve temizleme anlamına gelir. Tabii ki, aynı zamanda nasıl derleyeceğinize, derleyiciye hangi fırsatları verdiğinize de bağlıdır. Bir 2500 satır işlevi yerine 250 10 satır işlevine sahip olabilirsiniz, derleyicinin tüm işlem boyunca en iyi duruma getirmeyi seçerse / seçerse bir 2500 satır işlevi elde edersiniz. Ancak bu 250 10 satır işlevini alır ve bunları 2, 3, 4, 250 ayrı dosyaya yayarsanız, her bir dosyayı ayrı ayrı derleyin, sonra derleyici olabildiğince çok ölü kodu en iyi duruma getiremez. Buradaki sonuç, her ikisinin de artıları ve eksileri var ve buna genel bir kural koymak mümkün değil ya da en iyisi bu.

Makul büyüklükteki işlevler (bir kişinin ekranda veya sayfada görebileceği bir şey (makul bir fontta)), oldukça büyük olan koddan daha iyi ve anlayabileceği bir şeydir. Ancak bu, diğer birçok küçük işlevi çağıran diğer küçük işlevleri çağıran küçük bir işlevse, bu kodu anlamak için birkaç pencereye veya tarayıcıya ihtiyacınız vardır, böylece okunabilirlik tarafında bir şey satın almazsınız.

unix yolu güzel, cilalı lego bloklarımı kullanarak yapmaktır. Neden kasetleri kullanmayı bıraktıktan yıllar sonra bir kaset fonksiyonu kullanıyorsunuz? Blob işini çok iyi yaptı ve arka tarafta kaset arayüzünü bir dosya arayüzüyle değiştirebilir ve programın etinden faydalanabiliriz. Neden cdrom yazma yazılımını yeniden yazmanız gerekiyor çünkü scsi baskın arayüz ide ile değiştirildi (sonra geri dönecek). Yine cilalanmış alt blokların avantajlarından yararlanın ve bir ucunu yeni bir arayüz bloğu ile değiştirin (ayrıca donanım tasarımcılarının donanım tasarımları üzerindeki bir arayüz bloğunu tattığını anlayın. Her biri iyi tanımlanmış bir amaca ve iyi tanımlanmış girdi ve çıktılara sahip makul büyüklükte cilalanmış lego blokları oluşturun. Testleri bu lego bloklarının etrafına sarabilir ve daha sonra aynı bloğu alabilir ve kullanıcı arayüzünü ve işletim sistemi arayüzlerini aynı blok ve bloğun etrafına sarabilirsiniz, teoride iyi test edilmiş ve iyi anlaşılmış olması durumunda hata ayıklanması gerekmeyecek, sadece ek yeni bloklar eklenmiş olacaktır. her iki ucunda. Tüm blok arayüzleriniz iyi tasarlanmışsa ve iyi anlaşılmış bir işlevsellik, herhangi bir tutkal varsa, minimum düzeyde çok sayıda şey inşa edebilirsiniz. Tıpkı mavi, kırmızı ve siyah ve sarı renkli lego bloklarında olduğu gibi bilinen ebat ve şekillerde birçok şey yapabilirsiniz. Tüm blok arayüzleriniz iyi tasarlanmışsa ve iyi anlaşılmış bir işlevsellik, herhangi bir tutkal varsa, minimum düzeyde çok sayıda şey inşa edebilirsiniz. Tıpkı mavi, kırmızı ve siyah ve sarı renkli lego bloklarında olduğu gibi bilinen ebat ve şekillerde birçok şey yapabilirsiniz. Tüm blok arayüzleriniz iyi tasarlanmışsa ve iyi anlaşılmış bir işlevsellik, herhangi bir tutkal varsa, minimum düzeyde çok sayıda şey inşa edebilirsiniz. Tıpkı mavi, kırmızı ve siyah ve sarı renkli lego bloklarında olduğu gibi bilinen ebat ve şekillerde birçok şey yapabilirsiniz.

Her birey farklıdır, cilalı ve iyi tanımlanmış ve test edilmiş ve okunabilir tanımları değişkendir. Örneğin, bir profesörün programlama kurallarını dikte etmesi, profesyonel olarak sizin için kötü olabileceği veya olamayacağı için değil, bazı durumlarda profesör veya lisansüstü öğrenci asistanlarında kodunuzu okuma ve notlandırma işini kolaylaştırmak için uygun değildir. ... Her bir işin çeşitli nedenlerden dolayı farklı kurallara sahip olabileceğini bulmak için muhtemelen eşit, muhtemelen profesyonelce, genellikle bir ya da birkaç kişi iktidarda olan bir şey hakkında doğru ya da yanlış bir düşünceye sahip olabilir ve bu güçle sizin yapmanıza izin verebilir. orada öyle (ya da istifa et, işten atıl ya da bir şekilde iktidara gel). Bu kurallar, okunabilirlik, performans, test edilebilirlik, taşınabilirlik ile ilgili bir tür gerçeğe dayandıkları kadar fikir temellidir.


“Yani her bireysel programcı için değişebilecek ve değişecek olan konfor seviyenizi bulmanız gerekiyor.” Bence optimizasyon seviyesine, her programcının sevdiklerine göre değil, her bir kod parçasının performans gereksinimlerine göre karar verilmelidir.
svick

Derleyiciye, programcının derleyiciye derleyicileri genel olarak varsayılanı optimize etmemek için optimize etmesini söylediğini varsayarsak (komut satırında IDE kullanılıyorsa farklı bir varsayılan olabilir). Ancak programcı, fonksiyonun boyutunu optimize etmek için yeterli bilgiyi olmayabilir ve birçok hedefle birlikte boşuna gider mi? Elle ayarlama performansının okunabilirlik üzerinde olumsuz bir etkiye sahip olma eğilimi vardır ve özellikle de test edilebilirliğin test edilebilirliği her iki yönde de olabilir.
old_timer

2

Derleyicinizin ne kadar akıllı olduğuna bağlı olarak değişir. Genel olarak, optimize ediciyi zekâya atmaya çalışmak kötü bir fikirdir ve aslında optimize etmek için fırsatların derleyicisini sorabilir. Yeni başlayanlar için, muhtemelen ne yapabileceğinin hiçbir ipucuna sahip değilsiniz ve yaptıklarınızın çoğu da bunun ne kadar iyi yaptığını etkiliyor.

Erken optimizasyon, programcıların bunu yapmaya çalışan ve aslında yapmaya çalıştıkları şeyin kritik yolunda olmayan kodu sürdürmenin zorluğuyla sonuçlanan nosyonudur. Uygulamanızın çoğu IO olaylarını beklerken engellendiğinde, mümkün olduğu kadar CPU'yu sıkıştırmaya çalışmak, örneğin çok fazla gördüğüm bir şey.

En iyisi doğruluğu kodlamak ve gerçek performans darboğazlarını bulmak için bir profilleyici kullanmak ve kritik yolda ne olduğunu ve geliştirilip geliştirilemeyeceğini analiz ederek bunları düzeltmektir. Genellikle birkaç basit düzeltme uzun bir yol gider.


0

[bilgisayar-zaman elemanı]

Daha Gevşetici Bağlantıya ve Küçük Fonksiyonlara Yeniden Yönlendirme Kod Hızını Etkiler mi?

Evet öyle. Ancak bu "dikiş / kablolama" kodunu silmek tercümanlara, derleyicilere ve JIT derleyicilerine bağlıdır ve bazıları bunu diğerlerinden daha iyi yapar, ancak bazıları yapmaz.

Çoklu dosya kaygısı, G / Ç ek yüküne ek olarak hızı da biraz fazla etkiler (bilgisayar zamanında).

[insan-hız elemanı]

(Ve umursamalı mıyım?)

hayır umrumda değil. Bilgisayarlar ve devreler bugünlerde oldukça hızlı ve ağ gecikmesi, veritabanı G / Ç ve önbellekleme gibi diğer faktörler devraldı.

Dolayısıyla yerel kod yürütme işleminde 2x - 4x yavaşlama, genellikle bu diğer faktörler tarafından boğulur.

Birden fazla dosya yükleme işlemine gelince, bu genellikle çeşitli önbellek çözümleriyle halledilir. Bir şeyleri yüklemek ve ilk kez bunları birleştirmek daha fazla zaman alabilir, ancak bir sonraki her seferinde, statik dosyalar için, önbellekleme tek bir dosya yükleniyor gibi çalışır. Önbellekleme, çoklu dosya yüklemesi için bir çözüm olarak gelir.


0

CEVAP (kaçırmış olmanız durumunda)

Evet, umursamalısınız, ancak performansı nasıl değil de kodu nasıl yazdığınıza dikkat edin.

Kısacası

Performans umurumda değil

Soru bağlamında, daha akıllı derleyiciler ve tercümanlar zaten bununla ilgileniyor

Bakım kodunu yazmaya özen gösterin

Bakım maliyetlerinin makul düzeyde insan anlama seviyesine sahip olduğu kod. yani, her birini anlasanız bile kodu anlaşılmaz kılan 1000 küçük işlev yazmayın ve anlaşılması çok büyük olan 1 tanrı nesne işlevini yazmayın, ama insana mantıklı gelen ve iyi işlenmiş 10 iyi işlevsellik yazın. bakımı kolay.

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.