Okunabilen kodu temizleyin, kodu okumak zor hızlı. Çizgiyi ne zaman geçmelisin?


67

Kod yazarken kodumu daima olabildiğince temiz ve okunabilir hale getirmeye çalışıyorum.

Her şimdi ve sonra daha hızlı hale getirmek için çizgiyi geçmeniz ve güzel temiz koddan hafif çirkin koda geçmeniz gereken bir zaman gelir.

Bu çizgiyi geçmek ne zaman uygundur?


69
Kendi sorunuza cevap verdiniz, çizgiyi geçmeniz gerektiğinde çizgiyi
geçersiniz

6
Ayrıca, "kirli kodunuz" bundan 6 ay sonra donanımdaki "temiz kod" kadar hızlı çalışabilir. Yine de, Windows’un yaptığı gibi denize girmeyin. :)
Mateen Ulhaq

21
Anlaşılması zor bir algoritma ile anlaşılması zor bir kod arasında önemli bir fark vardır. Bazen uygulamanız gereken algoritma karmaşıktır ve kodun karmaşık olması gerektiği için kafa karıştırıcı olması gerekir. Ancak, kodun kendisi zor olan nokta ise, kodun düzeltilmesi gerekir.
tylerl

8
Bir çok durumda akıllı bir derleyici / yorumlayıcı temiz ve okunabilir kodu optimize edebilir, böylece "çirkin" kodla aynı performansa sahip olur. Bu yüzden, profilden başka bir şey söylenmediği sürece küçük bir bahane var.
Dan Diplo

1
Bugünlerde derleyiciler söz konusu olduğunda, çirkin kodunuz büyük olasılıkla temiz kodunuzla aynı olacaktır (gerçekten tuhaf şeyler yapmamanız şartıyla). Özellikle .NET'te, değişkenlerinizi nasıl tanımladığınızın performans üzerinde bir etkisi olacağı C ++ / MFC günleri gibi değildir. Bakım kodu yazın. bazı kodlar karmaşık hale gelecektir ancak bu çirkin olduğu anlamına gelmez.
DustinDavis

Yanıtlar:


118

Çizgiyi geçtiğinizde

  • Sen var ölçülen kodunuzu olduğunu istenen kullanım için çok yavaş .
  • Kodu almayı gerektirmeyen alternatif iyileştirmeler denediniz.

İşte gerçek dünyadan bir örnek: Çalıştığım deneysel bir sistem çok yavaş veri üretiyordu, çalışma başına 9 saatten fazla alıyordu ve CPU'nun sadece% 40'ını kullanıyordu. Kodu çok fazla karıştırmak yerine, tüm geçici dosyaları bellek içi dosya sistemine taşıdım. 8 yeni çirkin olmayan kod satırı eklendi ve şimdi CPU kullanımı% 98'in üzerinde. Sorun çözüldü; çirkinliğe gerek yok.


2
Ayrıca orijinal, daha yavaş, daha temiz kodu hem referans uygulaması olarak sakladığınızdan, hem de donanım değiştiğinde ve daha hızlı, hackier kodunuz artık çalışmadığında geri döndüğünüzden emin olun.
Paul R,

4
@PaulR Bu kodu nasıl saklıyorsunuz? Yorum şeklinde? Bu yanlıştır, imo - yorumlar modası geçmez, kimse onları okuyamaz ve şahsen kodla yorum yaptığını görürsem genellikle kaldırırım - bu kaynak kontrolü içindir. Ne işe yaradığını açıklayan bir yöntem hakkında bir yorum, imo.
Evgeni

5
@Eugene: Genelde fooadlandırılmış bir rutinin orjinal halini tutar ve ismini değiştiririm foo_ref- tipik olarak fookaynak dosyada hemen üstünde bulunur . Benim test koşum ben çağırır foove foo_refdoğrulama ve göreli performans ölçümü için.
Paul R

5
@ Yaparsanız, optimize edilmiş versiyonun ref fonksiyonundan daha yavaş olması durumunda testin başarısız olması iyi bir fikir olabilir. Bu, daha hızlı yapmak için yaptığınız varsayımların artık doğru olmaması durumunda olabilir.
user1852503

58

Bu sahte bir ikilik. Kodu hızlı ve kolay bir şekilde yapabilirsiniz .

Yapma şekliniz, özellikle olabildiğince basit bir veri yapısıyla, temiz bir şekilde yazmaktır.

Sonra zaman boşalmasının nerede olduğunu ( daha önce değil, yazdıktan sonra çalıştırarak) bulup tek tek düzeltin. (İşte bir örnek.)

Eklendi: Her zaman, zaman ve hafıza arasındaki bir tradeof veya hız ve sürdürülebilirlik arasındaki bir tradeoff gibi haksızlık mı duyuyoruz? Bu tür eğriler iyi mevcut olsa da, verilen herhangi bir programın eğri üzerinde veya hatta yakınında herhangi bir yerde olduğu varsayılmamalıdır .

Eğride bulunan herhangi bir program (belirli bir programlayıcıya vererek) kolayca hem daha yavaş hem de daha az bakım yapılabilir hale getirilebilir ve daha sonra eğri yakınında hiçbir yerde kalmaz. Böyle bir program daha sonra hem daha hızlı hem de daha iyi durumda olması için yeterli alana sahiptir.

Deneyimlerime göre, birçok programın başladığı yer burasıdır.


Katılıyorum. Gerçekten de temiz olmayan hızlı kod, daha sonra doğru şekilde değiştiremediğiniz için yavaşlayacaktır.
edA-qa mort-ora-y

22
Ben do not sahte bir ikilik katılıyorum; IMO, özellikle kitaplığın kodunda ( uygulama kodunda çok fazla değil ) bölünmenin çok gerçek olduğu senaryolar var . Daha fazlası için cevabımı gör.
Marc Gravell

1
Marc, yorumlardaki cevaplara "link" URL'sini bağlayabilirsin. programmers.stackexchange.com/questions/89620/…

Hepimiz kodun daha hızlı çalışmasını sağlamak için gereken zamanları bulduk. Ancak en iyi çözümü bulmak için profilleyici ile yapılan denemeden sonra (kod çirkinleşiyordu) bu, kodun çirkin kalması gerektiği anlamına gelmez. İlk başta açık görünmeyen en iyi çözümü bulma meselesidir, ancak bir zamanlar genellikle temiz bir şekilde kodlanabilir. Bu nedenle, sahte bir ikilik olduğunu ve oyuncaklarınızla eğlendikten sonra odanızı düzeltmemek için sadece bir bahane olduğuna inanıyorum. Bence onu em ve odanı topla.
Martin York

Bunun sahte bir ikilik olduğunu kabul etmiyorum. Çok fazla grafik çalışması yaptığım için bana en açık örnek dar grafik döngülerinde: Ne kadar sıklıkla yapıldığını bilmiyorum, ama C ile yazılmış oyun motorlarının Core rendering işleminde kullanılması yaygındı. Her son hız düşüşünü sıkmak için döngüler. Bu aynı zamanda Python'da programladığınız ancak C ++ ile yazılmış modülleri kullandığınız durumları düşündürüyor. "Okunması zor" her zaman görecelidir; hız için daha düşük bir dile bıraktığınızda, bu kodun geri kalanından okunması daha zordur.
jhocking

31

OSS varlığımda, performansa yönelik pek çok kütüphane çalışması yapıyorum; bu, arayanın veri yapısına (yani kütüphanenin dışına), gelen tasarımlara hiçbir zorunluluğu olmadan (tasarım gereği) bağlıdır. İşte bu yapmak için en iyi yol performant (I .NET-topraklarda olduğum beri) IL-yaydıkları anlamına gelir meta programlama vardır. Bu çirkin, çirkin bir kod, ama çok hızlı.

Bu şekilde, kütüphane kodunun uygulama kodundan daha "çirkin" olabileceğini , girdiler üzerinde daha az (ya da belki hiç) kontrolü olmadığını kabul ettim , bu yüzden farklı mekanizmalar yoluyla bazı görevleri başarması gerekiyor. Ya da geçen gün ifade ettiğim gibi:

"deliliğin uçurumunu kodlamak, böylece yapmak zorunda değilsin "

Şimdi, uygulama kodu biraz farklıdır, çünkü "normal" (akıllıca) geliştiricilerin tipik olarak işbirliği / profesyonel zamanlarının çoğuna yatırım yaptıkları; her birinin hedefleri ve beklentileri (IMO) biraz farklıdır.

IMO, yukarıdaki yanıtların hızlı ve kolay olduğunu gösteren cevaplar , geliştiricinin veri yapıları üzerinde daha fazla kontrole sahip olduğu ve meta programlama gibi araçlar kullanmadığı uygulama koduna atıfta bulunuyor . Bununla birlikte, farklı delilik seviyeleri ve farklı ek yük seviyeleri ile meta programlama yapmanın farklı yolları vardır. Bu arenada bile uygun soyutlama seviyesini seçmelisin. Ancak, aktif olarak, pozitif olarak, gerçekten beklenmedik verileri en hızlı şekilde ele almasını istersiniz ; iyi çirkin olabilir. Onunla başa çıkmak; p


4
Sadece kod çirkin olduğu için, sürdürülemez olması gerektiği anlamına gelmez. Yorumlar ve girintiler ücretsizdir ve çirkin kod genellikle yönetilebilir bir varlığın içine yerleştirilebilir (dile bağlı olarak sınıf, modül, paket, işlev). Kod aynı derecede çirkin olabilir, ancak en azından insanlar yapmak üzere oldukları değişikliklerin etkilerini yargılayabilirler.
tdammers

6
Gerçekten de ondamcılar ve mümkün olduğu kadar yapmaya çalışıyorum; ama biraz domuzun üstüne ruj sürmek gibi.
Marc Gravell

1
Belki de çirkin sözdizimi ve çirkin algoritmalar arasında bir ayrım yapmalısınız - çirkin algoritmalar bazen gereklidir, ancak çirkin sözdizimi genellikle affedilmez IMO'dur.
tdammers

4
@IMO çirkin sözdizimi, yaptığınız şey normal doğanın altındaki birkaç soyutlama seviyesinden kaynaklanıyorsa , kaçınılmazdır .
Marc Gravell

1
@ marc ... bu ilginç. Meta / soyut'a çirkin davranmaya ilk tepkim, belirli bir dilin / plaka biçiminin, ikisini birbirine bağlayan bazı yasalardan ziyade meta kodlamaya elverişli olmadığı şüphesiydi. Beni inandırıcı olan şey, ifadesinde cebirden, hatta somut aritematiğinden neredeyse çirkin olmayan küme teorisiyle biten matematikteki ilerici metal seviyelerinin örneği olduğudur. Ama sonra set-notasyonu .... farklı tamamen dil ve her abstration seviyesi altında kendi dili vardır muhtemelen
explorest

26

Kodu profilden çıkardığınızda ve gerçekten önemli bir yavaşlamaya neden olduğunu doğruladığınızda.


3
Ve "önemli" nedir?
Rook

2
@ hotpaw2: Bu akıllıca bir cevap - geliştiricilerin en azından bir şekilde daha iyi durumda olduğu varsayılıyor. Aksi takdirde evet, kabarcık sıralamasından daha hızlı bir şey kullanmak (genellikle) iyi bir fikirdir. Ancak çok sık birileri (sıralamada kalmaya devam edecekler),% 1'lik bir fark için heatsort için hızlı destek takas eder, sadece bir başkasının aynı sebepten altı ay sonra geri aldığını görmek için.

1
Temiz olmayan bir kod yapmak için hiçbir neden yoktur. Verimli kodunuzu temiz ve bakımı kolay hale getiremiyorsanız, yanlış bir şey yapıyorsunuz demektir.
edA-qa mort-ora-y

2
@SF. - Müşteri, daha hızlı olabilirse, her zaman çok yavaş bulacaktır. Kodun "temizliğini" önemsemiyor.
Rook

1
@Rook: Müşteri (önemsiz) arayüz kodunu çok yavaş bulabilir. Bazı oldukça basit psikolojik hileler, kod olaylarını anında harekete geçirmek yerine arka plan rutine ertelemek, bir ilerleme çubuğu göstermek veya bunun gibi bir şey göstermek, etkinlik arka planda gerçekleştirilirken önemsiz sorular sormak için kullanıcı deneyimini geliştirir. ... bunlar yeterli olmadığında, gerçek optimizasyonu düşünebilirsiniz.
SF.

13

Hızlı kod, hızlı çalışan kodla ilgili değildir. Normalde okunması zor bir kod yazılmıştır, çünkü daha hızlı çalıştığından değil, daha hızlı yazılmıştır.

"Kirli" kodun daha hızlı hale getirilmesi amacıyla yazılması tartışmasız bir durumdur, çünkü değişikliklerin gerçekten bir şeyleri geliştirdiğini kesin olarak bilmiyorsunuz. Knuth en iyisini koydu:

“Küçük etkinlikleri unutmalıyız, zamanın% 97'sini söyleyelim: erken optimizasyon tüm kötülüklerin köküdür . Ancak bu kritik% 3'teki fırsatlarımızı kaçırmamalıyız. Akıl yürütme, kritik koda dikkatlice bakmakta akıllıca olacaktır, ancak bu kod tanımlandıktan sonra . "

Başka bir deyişle, önce kodu temiz yazın. Ardından, sonuçta ortaya çıkan programın profilini görüntüleyin ve o bölümün gerçekte performans darboğazı olup olmadığını görün. Eğer öyleyse, bölümü gerektiği şekilde optimize edin ve optimizasyonları açıklamak için bol miktarda dökümantasyon yorumu (muhtemelen orijinal kod dahil) eklediğinizden emin olun. Ardından, gerçekte bir iyileştirme yaptığınızı doğrulamak için sonucu görüntüleyin.


10

Soru “ kodu okumak hızlı zor ” dediğinden , basit cevap asla değildir. Okumak zor bir kod yazmak için asla bir bahane bulamazsınız. Neden? İki sebep.

  1. Bu gece eve giderken bir otobüse çarptığınızda ne olur? Veya (daha iyimser ve daha tipik olarak) bu projeden ayrıldı ve başka bir şeye atandı mı? Karışık kod karışıklığınızla yaptığınız küçük yarar, başka hiç kimsenin anlayamadığı gerçeğinden tamamen etkilenir . Bunun yazılım projelerine getirdiği risklerin üstesinden gelmek zor. Bir zamanlar büyük bir PBX ile çalıştımüretici (bir ofiste çalışıyorsanız, muhtemelen telefonlarından birini masanızda bulunduruyorsunuz). Proje yöneticileri, bir gün bana standart bir Linux kutusunu tam özellikli bir telefon alışverişine dönüştüren özel yazılım olan çekirdek ürünlerinin şirket içinde "blok" olarak bilindiğini söyledi. Artık kimse anlamadı. Her yeni bir özellik uyguladılar. derlemeye çarptılar, sonra geriye yaslandılar, gözlerini kapattılar, yirmiye kadar saydılar, sonra işe yarayıp yaramadıklarını görmek için parmaklarını dikizlediler. Hiçbir işletme artık kontrol etmedikleri bir çekirdek ürüne ihtiyaç duymuyor, ancak korkutucu derecede yaygın bir senaryo.
  2. Ama optimize etmem gerek! Tamam, bu soruya verilen diğer cevaplarda mükemmel tavsiyelere ulaştınız: kodunuz performans test durumlarında başarısız oluyor, dikkatle profilini belirlediniz, tıkanıklıkları tespit ettiniz, bir çözüm buldum ... biraz bit bükülmeyi içerir . İyi: şimdi devam et ve optimize et. Ama işte sır (ve bunun için oturmak isteyebilirsiniz): kaynak kodunun boyutunda optimizasyon ve küçültme aynı şey değil. Yorumlar, beyaz boşluklar, parantezler ve anlamlı değişken isimleri, derleyici bunları çöpe atacağı için size kesinlikle hiçbir maliyeti olmayan okunabilirlik için büyük yardımlardır. (Veya JavaScript gibi derlenmemiş bir dil yazıyorsanız - ve evet, JavaScript'i optimize etmek için çok geçerli nedenler var - bunlar bir kompresör tarafından ele alınabilir .) Uzun satırlar halinde sıkışık, minimalist kod Burada yayınlanan ) optimizasyon ile ilgisi yok: bu, mümkün olduğunca az karaktere kod yazarak ne kadar akıllı olduklarını göstermeye çalışan bir programcı. Bu akıllıca değil, aptalca. Gerçekten zeki bir programcı, fikirlerini açıkça başkalarına iletebilen bir programcıdır.

2
Cevabın "asla" olduğu konusunda hemfikir değilim. Bazı algoritmalar doğal olarak anlamak ve / veya verimli bir şekilde uygulamak zordur. Yorum sayısı ne olursa olsun, kodu okumak çok zor olabilir.
Rex Kerr

4

Fırlatma kodu olduğunda. Bunu gerçekten demek: Eğer bir kerelik hesaplama veya görevi gerçekleştirmek ve böyle bir kesinlikle bilmek bir senaryo yazarken sen 'rm kaynak-dosya' çekinmeden, ki yine bu eylemi yapmak zorunda asla o seçebileceğiniz çirkin yol.

Aksi taktirde sahte bir ikiliktir - daha hızlı yapmak için çirkin yapman gerektiğini düşünüyorsanız, yanlış yapıyorsunuz. (Ya da iyi kodun ne olduğu konusundaki ilkelerinizin gözden geçirilmesi gerekir. Soruna en uygun çözüm olduğunda goto kullanımı aslında oldukça şıktır. Ancak, nadiren olur.)


5
Fırlatma kodu diye bir şey yoktur. Her seferinde bir "penaltı atma kodu" hazırladıysam, "işe yarıyor, yeniden yazmak için vaktimiz yok" diye üretime girdi, milyoner olurdum. Yazdığınız her kod satırı, bu gece yıldırım çarptıktan sonra yarın başka bir yetkili programcının alabileceği şekilde yazılmalıdır. Aksi takdirde yazmayın.
Mark Whitaker

Bunun sahte bir ikilik olduğunu kabul etmiyorum; IMO, özellikle kitaplığın kodunda (uygulama kodunda çok fazla değil) bölünmenin çok gerçek olduğu senaryolar var. Daha fazlası için cevabımı gör.
Marc Gravell

@ mark, "başka bir yetkin programcı" gerçekten yetkin ise, o zaman fırlatma kodu da sorun olmamalı :)

@Mark - Kolay. Sadece atma kodunu yazın, böylece herhangi bir üretim testinde başarısız olabilir, belki de düzeltilemez bir şekilde.
hotpaw2

Senin “Atılabilir kodu” üretime bunu yaparsa @ Mark, o zaman yani değil Atılabilir kodu. Kelimenin tam anlamıyla çöpe atılan koddan bahsettiğimi açıklığa kavuşturmak için cevabımda zaman ayırdığımı fark et : yani ilk kullanımdan sonra sil. Aksi halde, düşüncenize katılıyorum ve cevabımdaki kadarını söyledim.
maaku

3

Piyasadaki düşük performansın tahmini maliyeti, söz konusu kod modülünün tahmini kod bakım maliyetinden büyük olduğunda.

İnsanlar hala elle kodlanmış SSE / NEON / etc bükülmüş. Bu yılın popüler CPU yongası üzerinde bazı rakiplerin yazılımlarını denemek ve yenmek için montaj.


İyi bir iş perspektifi, bazen programcılar sadece teknik ötesine bakmak gerekir.
this.josh

3

Unutmayın, okunması zor kodları uygun belgelerle ve yorum yaparak kolayca anlaşabilirsiniz.

Genel olarak, istenen işlevi yapan kolay okunur kod yazdıktan sonra profil. Darboğazlar daha karmaşık görünmesini sağlayan bir şey yapmanızı gerektirebilir, ancak bunu kendiniz açıklayarak düzeltin.


0

Bana göre stabilite oranı (betonda çimentolu, fırında pişmiş, taşa konmuş, kalıcı mürekkeple yazılmış). Kodunuz ne kadar kararsız olursa, gelecekte onu değiştirmeniz gerekme olasılığı ne kadar yüksek olursa, üretken kalabilmek için ıslak kil gibi olması o kadar kolay bir şekilde bükülebilir olmalıdır. Ayrıca esnekliği ve okunabilirliği vurgulamıyorum. Bana göre kod değiştirme kolaylığı, okuma kolaylığından daha önemli. Kod okunması kolay ve değiştirilebilecek bir kabus olabilir ve eğer değişecek bir kabussa, uygulama ayrıntılarını ne şekilde okuyabilir ve kolayca anlayabilir? Bu sadece akademik bir alıştırma olmadıkça, tipik olarak bir üretim kod tabanında kodları kolayca anlayabilmenin amacı, gerektiğinde daha kolay bir şekilde değiştirebilme niyetindedir. Değiştirilmesi zorsa, sonra okunabilirliğin faydalarının birçoğu pencereden dışarıya çıkıyor. Okunabilirlik sadece esneklik bağlamında faydalıdır ve esneklik sadece kararsızlık bağlamında yararlıdır.

Doğal olarak, okunması ne kadar kolay ya da zor olursa olsun, akla gelebilecek bir kodu bulundurmak zor olsa bile, değiştirmesi için hiçbir neden yoksa, yalnızca onu kullanmayın. Ve böyle bir kaliteye ulaşmak, özellikle performansın çoğu zaman saymaya meyilli olduğu düşük seviyeli sistem kodu için mümkündür. Hala 80'lerin sonlarından beri değişmeyen düzenli olarak kullandığım C kodum var. O zamandan beri değişmesi gerekmedi. Kod titiz, biraz garip günlerde yazılmış ve ben zar zor anlıyorum. Yine de bugün hala uygulanabilir ve uygulamadan bol miktarda faydalanabilmek için anlamam gerekmiyor.

İyice testleri yazmak istikrarı artırmanın bir yoludur. Bir diğeri dekuplajdır. Eğer kodunuz başka bir şeye bağlı değilse, değişmesi için tek nedeni değişmesi gerekip gerekmediğidir. Bazen, az miktarda kod çoğaltması, kararlılığı önemli ölçüde iyileştirmeye yarayan bir takas mekanizması olarak işlev görebilir; bu durumda, karşılığında, şu anda tamamen başka bir şeyden bağımsız olan bir kod alırsanız. Şimdi bu kod dış dünyadaki değişikliklere karşı hassastır. Bu arada, 10 farklı dış kütüphaneye bağlı olan kod, gelecekte değişmesi için 10 kat daha fazla nedene sahiptir.

Pratikte bir başka yararlı şey, kütüphanenizi kod tabanınızın dengesiz parçalarından ayırmak, hatta üçüncü şahıs kütüphaneleri için yapabileceğiniz gibi muhtemelen ayrı ayrı inşa etmektir. takım). Sadece bu tür bir organizasyon, insanların buna müdahale etmesini önleyebilir.

Bir diğeri minimalizmdir. Kodunuz ne kadar az şey yapmaya çalışırsa, ne yaptığını da o kadar iyi yapabilir. Monolitik tasarımlar neredeyse kalıcı bir şekilde dengesizdir, çünkü onlara ne kadar fazla işlev eklenirse, o kadar eksik görünürler.

Mikro ayarlı paralelleştirilmiş SIMD kodu gibi, kaçınılmaz olarak değiştirilmesi zor olan bir kod yazmayı hedeflediğinizde kararlılık birincil hedefiniz olmalıdır. Kodu değiştirme zorunluluğunu ortadan kaldırarak kodu değiştirmek zorunda kalmayacağınız olasılığını en üst düzeye çıkarırsınız ve bu nedenle gelecekte de sürdürmek zorunda kalmazsınız. Bu, kodun bakımı ne kadar zor olursa olsun bakım maliyetlerini sıfıra indirir.

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.