Düşük gecikmeli kod bazen “çirkin” olmak zorunda mı?


21

(Bu, temel olarak doğrulanmamış görüşlere cevap veren insanları önlemek için, düşük gecikmeli sistemler konusunda özel bilgiye sahip olanları hedeflemektedir.

"Güzel" nesne yönelimli kod yazmak ile çok düşük gecikmeli kod yazmak arasında bir denge olduğunu düşünüyor musunuz? Örneğin, C ++ 'da sanal işlevlerden kaçınmak (polimorfizm yükünün üst üste gelmesi vb. Kodu yeniden yazıyor) fakat çok hızlı vb.

Nedene bakar - kimin çirkin gözüktüğünü umursar (bakımı devam ettiği sürece) - hıza ihtiyacınız varsa hıza ihtiyacınız var mı?

Bu tür alanlarda çalışan insanlardan haber almak isterim.


1
@ user997112: Yakın nedeni öz açıklayıcıdır. Diyor ki: "Cevapların gerçekler, referanslar veya belirli bir uzmanlık tarafından desteklenmesini bekliyoruz, ancak bu soru muhtemelen tartışma, tartışma, sorgulama veya genişletilmiş tartışmalar gerektirecektir. Mutlaka doğru oldukları anlamına gelmez, ama üç yakın seçmen tarafından seçilen sebep
Robert Harvey

Her halükarda, bu sorunun yakın oy almasının sebebinin, ince örtülü bir rant olarak algılanmış olabileceğini söyleyebilirim (sanmıyorum olmasına rağmen).
Robert Harvey

8
Boynumu dışarı atacağım: Üçüncü oyu "yapıcı değil" olarak kapatmak için kullandım çünkü soru soran kişinin kendi sorusunu cevapladığını düşünüyorum. İşi yapmak için yeterince hızlı çalışmayan "Güzel" kod, gecikme şartını yerine getiremedi. Yeterince hızlı çalışan "Çirkin" kod, iyi belgelerle daha bakım yapılabilir hale getirilebilir. Güzelliği veya çirkinliği nasıl ölçtüğünüzü başka bir soru için bir konudur.
Blrfl

1
LMAX'in Bozucu için kaynak kodu çok çirkin değil. Bazı 'Java'nın güvenlik modeli ile cehenneme' (Güvenli olmayan sınıf) bölümler ve bazı donanım spesifik değişiklikler (önbellek hattı dolgulu değişkenler) var ama çok okunabilir IMO.
James

5
Carson63000, user1598390 ve her kim başka ilgi @: Eğer soru uçları kadar kapalı, bizim üzerinde kapatılması hakkında sormaya çekinmeyin Meta sitesinde , yorumlarda bir kapatma, özellikle de bir kapatma tartışırken küçük nokta var olmadı . Ayrıca, her kapalı sorunun yeniden açılabileceğini unutmayın, bu dünyanın sonu değil. Elbette, eğer Mayalılar haklıysa, bu durumda sizi tanımak güzeldi!
yannis

Yanıtlar:


31

"Güzel" nesne yönelimli kod yazmak ile çok düşük gecikmeli kod yazmak arasında bir denge olduğunu düşünüyor musunuz?

Evet.

Bu yüzden “erken optimizasyon” ibaresi var. Geliştiricileri performanslarını ölçmeye zorlamak ve yalnızca performansta fark yaratacak bu kodu optimize ederken, uygulama mimarlıklarını baştan itibaren makul bir şekilde tasarlayarak ağır yük altında kalmayacak şekilde optimize eder .

Bu şekilde, mümkün olan en yüksek ölçüde, güzel, iyi tasarlanmış, nesne yönelimli kodunuzu koruyabilir ve yalnızca önemli olan bu küçük bölümleri çirkin kodla optimize edebilirsiniz.


15
"Çalışmasını sağla, sonra hızlı yap". Bu cevap, soruyu okuduğumda söyleyeceğimi düşündüğüm her şeyi kapsar.
Carson63000

13
"Ölçme, tahmin etme" ekleyeceğim
Martijn Verburg

1
Bence, bazı şeyleri gittiğinizde temel işlerden kaçınmanın, okunaklılık pahasına gelmediği sürece faydalı olacağını düşünüyorum. İşlerin özlü, okunaklı olması ve sadece yapılması gereken bariz şeylerin yapılması, kodunuzu yapmak için ne halt edeceğini bilen diğer geliştiriciler gibi birçok dolaylı uzun vadeli perf galibiyetine yol açar. nasıl çalıştığı hakkında.
Erik,

1
"Erken optimizasyon" - optimize edilmiş kod, optimize edilmemiş kod kadar "güzel" olsa bile, bu hala geçerlidir. Önemli olan, hız / amaç için ne yapmanız gerekmediğini düşünerek zaman kaybetmemek. Aslında optimizasyon her zaman hız ile ilgili değildir ve tartışmasız "güzellik" için gereksiz optimizasyon diye bir şey vardır. Kodunuzun okunabilir ve bakımları iyi olması için mükemmel bir sanat eseri olması gerekmez.
Steve314

İkincisi @ Steve314. Bir üründeki performans lideriyim ve çoğu zaman kökeni bir tür performans optimizasyonuna kadar izleyebildiğim, aşırı karmaşık kodları buluyorum. Bu kodun basitleştirilmesi genellikle önemli bir performans iyileştirmesi ortaya çıkarır. Bu tür bir örnek, basitleştirdiğimde (binlerce satır kodun net olarak azaltılması) 5 kat performans iyileştirmesine dönüştü. Açıkçası, hiç kimse gerçekten ölçmek için zaman aldı ve basitçe yavaş kod olacağını düşündüklerini erken optimizasyon yaptı .
Brandon,

5

Evet, verdiğim örnek C ++ vs. Java değil, bildiğim kadarıyla Assembly vs COBOL.

Her iki dil de çok hızlıdır, ancak derlendiğinde COBOL bile, bu talimatları kendiniz Meclis'te yazmak yerine, mutlaka olması gerekmeyen talimat setine yerleştirilmiş birçok talimatı vardır.

Aynı fikir, C ++ 'da kalıtım / polimorfizm kullanarak vs. karşı "çirkin görünümlü kod" yazma sorunuza doğrudan uygulanabilir. Son kullanıcı alt-ikinci işlem zaman dilimlerine ihtiyaç duyuyorsa, çirkin görünen bir kod yazmanın gerekli olduğuna inanıyorum, o zaman nasıl olurlarsa olsunlar onlara programlayıcı olarak bizim görevimiz.

Bununla birlikte, yorumların liberal kullanımı, kod ne kadar çirkin olursa olsun, programcının işlevselliğini ve bakımını büyük ölçüde artırmaktadır.


3

Evet, bir takas var. Bununla, daha hızlı ve daha çirkin olan kodun daha iyi olması gerekmediğini kastediyorum - "hızlı kodun" nicel faydalarının, bu hızı elde etmek için gereken kod değişikliklerinin bakım karmaşıklığına karşı ağırlıklandırılması gerekiyor.

Değişim işletme maliyetinden kaynaklanıyor. Daha karmaşık olan kod, daha yetenekli programcılar gerektirir (ve CPU mimarisi ve tasarım bilgisine sahip olanlar gibi daha odaklanmış bir beceri setine sahip programcılar), kodu okumak ve anlamak ve hataları düzeltmek için daha fazla zaman alır. Bu tür bir kodu geliştirmenin ve korumanın işletme maliyeti, normal olarak yazılmış kodlara göre 10x - 100x arasında olabilir.

Bu bakım maliyeti, müşterilerin çok hızlı yazılımlar için çok yüksek bir primi ödemeye istekli olduğu bazı endüstrilerde doğrulanabilir .

Bazı hız optimizasyonları diğerlerinden daha iyi yatırım getirisi (YG) sağlar. Yani, bazı optimizasyon teknikleri, normalde yazılan koda kıyasla kod sürdürülebilirliği (daha yüksek düzeyde yapı ve daha düşük düzeyde okunabilirliği koruyarak) üzerinde daha az etkili olabilir.

Bu nedenle, bir işletme sahibi şunları yapmalıdır:

  • Maliyet ve faydalara bakın,
  • Ölçümler ve hesaplamalar yapın
    • Programcının program hızını ölçmesini sağlayın
    • Programcının optimizasyon için gerekli geliştirme süresini tahmin etmesini sağlayın
    • Daha hızlı yazılımdan elde edilen gelir hakkında kendi tahminde bulunun
    • Yazılım mimarlarına veya KG yöneticilerine, kaynak kodunun kolay anlaşılırlığının ve okunabilirliğinin azaltılması
  • Ve düşük optimizasyonlu meyvelere yazılım optimizasyonuna öncelik verin.

Bu takaslar şartlara çok özeldir.

Bunlara, yöneticilerin ve ürün sahiplerinin katılımı olmadan en iyi şekilde karar verilemez.

Bunlar platformlara oldukça özeldir. Örneğin, masaüstü ve mobil CPU'ların farklı düşünceleri vardır. Sunucu ve istemci uygulamaları da farklı düşüncelere sahiptir.


Evet, genellikle daha hızlı kodun normal olarak yazılmış koddan farklı göründüğü doğrudur. Farklı olan herhangi bir kodun okunması daha uzun sürer. Bunun çirkinliği ima edip etmediği, sahibinin gözündedir.

Biraz maruz kaldığım teknikler: (herhangi bir uzmanlık seviyesi talep etmeye çalışmadan) kısa vektör optimizasyonu (SIMD), ince taneli görev paralelliği, bellek ön tahsisi ve nesnenin yeniden kullanımı.

SIMD tipik olarak düşük seviyeli okunabilirlik üzerinde ciddi etkilere sahiptir, ancak tipik olarak daha yüksek düzeyde yapısal değişiklikler gerektirmese de (API'nin darboğaz önleme göz önünde bulundurularak tasarlandığı sürece).

Bazı algoritmalar kolayca SIMD'ye dönüştürülebilir (ayrıştırılabilir-vektörleştirilebilir). Bazı algoritmalar SIMD kullanmak için daha fazla hesaplama düzenlemesi gerektirir. Wavefront SIMD paralelliği gibi aşırı durumlarda, avantaj sağlamak için tamamen yeni algoritmalar (ve patentlenebilir uygulamalar) yazılmalıdır.

İnce taneli görev paralelleştirmesi algoritmaların veri akış grafiklerine yeniden düzenlenmesini gerektirir ve başka bir marj avantajı elde edilinceye kadar tekrar tekrar algoritmaya işlevsel (hesaplamalı) ayrıştırma uygular. Ayrışmış aşamalar tipik olarak, işlevsel programlamadan ödünç alınan bir kavram olan devam tarzı ile bağlanır.

İşlevsel (hesaplamalı) ayrıştırma yoluyla, normal olarak doğrusal ve kavramsal olarak açık bir sırayla (yazdıkları sırayla uygulanabilir kod satırları) yazılabilen algoritmalar, parçalara bölünmüş ve çoklu fonksiyonlara dağıtılmış olmalıdır. veya sınıflar. (Aşağıdaki algoritma nesnesine bakınız.) Bu değişiklik, bu koda neden olan ayrıştırma tasarım sürecine aşina olmayan diğer programcıları büyük ölçüde engelleyecektir.

Bu kodun korunmasını sağlamak için, bu kodun yazarlarının, normal olarak yazılmış kod için yapılan kod yorumlama türünün veya UML diyagramlarının çok ötesinde, algoritmanın ayrıntılı belgelerini yazması gerekir. Bu, araştırmacıların akademik makalelerini yazmalarına benzer.


Hayır, hızlı kodun nesne yönelimli olmasıyla çelişmemesi gerekmez.

Başka bir deyişle, hala nesne yönelimli çok hızlı bir yazılım uygulamak mümkündür. Bununla birlikte, bu uygulamanın alt kısmına doğru (hesaplama çoğunluğunun meydana geldiği somun ve civatalar düzeyinde), nesne tasarımı, nesne yönelimli tasarımdan (OOD) elde edilen tasarımlardan önemli ölçüde sapabilir. Alt seviye tasarımı algoritma nesnesine yöneliktir.

Kapsülleme, polimorfizm ve kompozisyon gibi nesne yönelimli programlamanın (OOP) bir kaç faydası, hala düşük seviyeli algoritma-nesnelleştirmesinden elde edilebilir. Bu düzeyde OOP kullanmanın temel nedeni budur.

Nesne yönelimli tasarımın (OOD) çoğu yararı kayboluyor. En önemlisi, düşük seviyeli tasarımda bir sezgisellik yoktur. Diğer bir programcı, ilk önce algoritmanın nasıl dönüştürüldüğünü ve ayrıştırıldığını tam olarak anlamadan alt seviye kodla çalışmayı öğrenemez ve bu anlayış sonuç kodundan elde edilemez.


2

Evet, bazen kodun istenen sürede çalışmasını sağlamak için "çirkin" olması gerekir, ancak tüm kodların çirkin olması gerekmez. Performans, "çirkin" olması gereken kod bitlerini bulmak için önce test edilmeli ve profillendirilmeli ve bu bölümler bir yorum ile belirtilmelidir, böylece gelecekteki kişiler neyin çirkin olduğunu ve sadece tembelliğin ne olduğunu bilirler. Birisi performans nedenleriyle ilgili olarak pek çok kötü tasarlanmış kod yazıyorsa, ispat etmelerini sağlayın.

Hız, bir programın diğer gereklilikleri kadar önemlidir, güdümlü bir füzeye yanlış düzeltmeler yapmak, darbeden sonra doğru düzeltmeleri sağlamakla eşdeğerdir. Bakım, daima çalışma koduna ikincil bir endişedir.


2

Gördüğüm çalışmaların bazıları, okunması kolay kodun okunması zor kodlardan daha hızlı olduğunu gösteriyor. Bu kısmen optimizerlerin tasarlanma şeklinden kaynaklanmaktadır. Bir değişkeni bir sicile optimize etmede daha iyi olma eğilimindedirler, aynı işlemi bir hesaplama sonucu yapmaktan daha iyidir. Nihai sonuca götüren tek bir operatör kullanan uzun ödev dizileri, uzun bir karmaşık denklemden daha iyi optimize edilebilir. Daha yeni optimize ediciler, temiz ve karmaşık kodlar arasındaki farkı azaltmış olabilir, ancak ben bunu ortadan kaldırdıklarından şüpheliyim.

Döngü açma gibi diğer optimizasyonlar gerektiğinde temiz bir şekilde eklenebilir.

Performansı arttırmak için eklenen optimizasyonlara uygun bir yorum eşlik etmelidir. Bu, tercihen öncesi ve sonrası performans ölçütleriyle bir optimizasyon olarak eklendiğini ifade etmelidir.

80/20 kuralının optimize ettiğim kod için geçerli olduğunu buldum. Genel bir kural olarak, zamanın en az% 80'ini almayan hiçbir şeyi optimize etmiyorum. Daha sonra 10 katlık bir performans artışı hedeflemekteyim (ve genellikle bunu başardım). Bu, yaklaşık 4 kat performansı artırır. Uyguladığım çoğu optimizasyon, kodu önemli ölçüde daha az "güzel" hale getirmedi. Kilometreniz değişebilir.


2

Çirkin, diğer geliştiricilerin yeniden kullanacağı veya anlaması gereken düzeyde okuması / anlaması zor demek istiyorsan, derim ki, zarif, okunması kolay bir kod hemen hemen her zaman sonuçta net olacaktır. sürdürmeniz gereken bir uygulamada uzun vadede performans artışı.

Aksi halde, bazen üzerinde katil arayüzü olan güzel bir kutuya çirkin davranmaya değecek bir performans kazanma şansı vardır, ancak benim deneyimime göre, bu oldukça nadir bir ikilemdir.

Çalışırken temel işlerden kaçınma hakkında düşünün. Arkcik püf noktalarını, bir performans probleminin kendini gösterdiği zaman için saklayın. Ve birisinin yalnızca belirli bir optimizasyona aşinalık yoluyla anlayabileceği bir şeyler yazmak zorunda kalırsanız, kod bakış açınızı yeniden kullanmaktan en azından çirkinliği kolaylaştıracak şeyleri yapın. Sefil bir performans sergileyen kod, bunu asla nadiren yapar; çünkü geliştiriciler, bir sonraki adamın miras alacağı şey hakkında çok fazla düşünüyorlardı, ancak sık değişiklikler bir uygulamanın tek sabiti (benim deneyimimdeki çoğu web uygulamaları) ise, katı / esnek olmayan kod. değiştirmesi zor, pratik olarak panikli mesajların kod tabanınızın her yerinde ortaya çıkmaya başlaması için yalvarıyor. Temiz ve yalın, uzun vadede performans için daha iyidir.


İki değişiklik önermek isterim: (1) Hızın gerekli olduğu yerler var. Bu yerlerde, arayüzün anlaşılmasını kolaylaştırmanın, uygulamayı anlaşılmasının kolaylaştırılmasından daha değerli olduğunu düşünüyorum , çünkü ikincisi çok daha zor olabilir. (2) "Nadiren nadiren performans gösteren kod böyle yapar ...", "Kod zarafeti ve sadeliği üzerine güçlü bir vurgu, nadiren sefil performansın nedenidir.
beklenir

Uygulama, bir OOPish konuşmasında kötü bir sözcük seçimiydi. Tekrar kullanım kolaylığı ve düzenlenmesi açısından demek istedim. # 2, az önce 2 olduğum nokta olduğunu belirten bir cümle ekledim.
Erik,

1

Karmaşık ve çirkin aynı şey değil. Her özel performans düşüşünü ortaya çıkarmak için optimize edilmiş ve ilk başta bağlantı ve bağımlılık arapsaçılarına benzeyen kod, aslında onu anladığınızda çok dikkatli bir şekilde tasarlanmış ve oldukça güzel olabilir. Aslında, performans (gecikme veya başka bir şeyle ölçülmüş olsun), çok karmaşık kodu doğrulamak için yeterince önemliyse, kodun iyi tasarlanmış olması gerekir . Değilse, o zaman tüm bu karmaşıklığın daha basit bir çözümden daha iyi olduğundan emin olamazsınız.

Çirkin kod, bana göre, özensiz, kötü düşünülmüş ve / veya gereksiz yere karmaşık olan koddur . Yapmanız gereken koddaki bu özelliklerden herhangi birini isteyeceğinizi sanmıyorum.


1

"Güzel" nesne yönelimli kod yazmak ile çok düşük gecikmeli kod yazmak arasında bir denge olduğunu düşünüyor musunuz? Örneğin, C ++ 'da sanal işlevlerden kaçınmak (polimorfizm yükünün üst üste gelmesi vb. Kodu yeniden yazıyor) fakat çok hızlı vb.

Gecikmeden ziyade verime daha fazla odaklanan bir alanda çalışıyorum, ancak çok kritik bir performans ve "sorta" derim .

Ancak bir problem, bu kadar çok insanın performans kavramlarını tamamen yanlış almasıdır. Acemiler genellikle hemen hemen her şeyi yanlış anlar ve tüm "hesaplama maliyeti" kavramsal modelinin yeniden çalışılması gerekir, sadece algoritmik karmaşıklık haklarını bulabilecekleri tek şeydir. Ara ürünler bir çok şeyi yanlış anlarlar. Uzmanlar bazı şeyleri yanlış anlıyor.

Önbellek özlüyor ve dal yanlış tahminleri gibi metrikler sağlayabilen doğru araçlarla ölçüm yapmak, alanındaki uzmanlık düzeyindeki tüm kişileri kontrol altında tutan şeydir.

Ölçme, neyin optimize edilmediğine de işaret ediyor . Uzmanlar genellikle acemilerden daha az zaman harcayarak daha az zaman harcıyorlar çünkü gerçek ölçülen sıcak noktaları optimize ediyorlar ve karanlıkta vahşi bıçakları optimize etmeyi denemiyorlardı. kod tabanında diğer tüm satırlar hakkında).

Performans için Tasarım

Bununla birlikte, performans için tasarım yapmanın anahtarı , arayüz tasarımında olduğu gibi tasarım bölümünden gelir . Tecrübesizlik sorunlarından biri, bazı genelleştirilmiş bağlamlarda dolaylı bir fonksiyon çağrısı gibi, mutlak uygulama metriklerinde erken bir değişim olma eğiliminde olma eğilimi göstermesidir (maliyet bir optimizasyon noktasından daha iyi anlaşılırsa) (bir dallanma bakış açısı yerine bakış açısı) tüm kod tabanı boyunca bundan kaçınmak için bir nedendir.

Maliyetler görecelidir . Dolaylı bir işlev çağrısının bir maliyeti olsa da, örneğin, tüm maliyetler görecelidir. Milyonlarca öğeden oluşan bir işlevi çağırmak için bu ücreti bir kez ödüyorsanız, bu maliyetten endişe etmek, milyarlarca dolarlık bir ürün satın almak için para biriktirmek için saat harcamak gibidir; bir kuruş çok pahalıydı.

Kaba Arayüz Tasarımı

Performansın arayüz tasarımı yönü, genellikle bu maliyetleri daha kaba bir seviyeye itmek için daha erken çabalar. Örneğin, tek bir partikül için çalışma zamanı soyutlama masrafları ödemek yerine, bu maliyeti partikül sisteminin / yayıcısının seviyesine itebilir, bir partikülü etkin bir şekilde bir uygulama detayına ve / veya bu partikül koleksiyonunun ham verisine dönüştürebiliriz.

Bu nedenle, nesne odaklı tasarımın performans tasarımıyla (gecikme veya verim olsun) uyumsuz olması gerekmez, ancak giderek ufacık granül nesneleri modellemeye odaklanan bir dilde cazibeler olabilir ve en son iyileştirici de yardım et. Tek bir noktayı temsil eden bir sınıfı, yazılımın bellek erişim düzenleri için etkili bir SoA temsili sağlayacak şekilde birleştirmek gibi şeyler yapamaz. Pürüzlülük düzeyinde modellenen arayüz tasarımıyla puan toplama, bu fırsatı sunar ve gerektiğinde daha fazla ve daha fazla optimum çözüm için yinelemeye izin verir. Böyle bir tasarım toplu bellek için tasarlanmıştır *.

* Odaklanmayı unutmayın belleğe burada değil veri veri türleri ve veri yapıları görünümünüzü değiştirmek eğiliminde olacaktır uzun süre performans açısından kritik alanlarda çalışan ve belleğe nasıl bağlanacağını görme gibi. İkili bir arama ağacı artık sabit bir tahsisatçı tarafından desteklenmediği sürece, ağaç düğümleri için muhtemelen ayrık ve önbellek dostu olmayan bellek parçaları gibi durumlarda artık sadece logaritmik karmaşıklıktan ibaret değildir. Görüntü algoritmik karmaşıklığı göz ardı etmiyor, fakat onu artık bellek düzenlerinden bağımsız olarak görmüyor. Biri ayrıca, çalışma tekrarlarını hafıza erişiminin tekrarları olarak görmeye başlar. *

Performans açısından kritik olan pek çok tasarım aslında insanların anlaması ve kullanması kolay olan üst düzey arayüz tasarımları kavramıyla çok uyumlu olabilir. Buradaki fark, bu bağlamdaki "yüksek seviye" nin, büyük miktarda veri toplanması için modellenen bir arabirim ve kaputun altında oldukça düşük seviyeli bir uygulama ile toplu bellek birikimi ile ilgili olacağıdır. Görsel bir benzetme, ses hızında giderken gerçekten rahat, kullanması ve kullanması kolay ve çok güvenli bir araba olabilir, ancak davlumbazı patlatırsanız, içeride küçük miktarda nefes alan şeytanlar vardır.

Daha kaba bir tasarımla daha verimli kilitleme kalıpları sağlamak ve kodda paralellikten faydalanmak için daha kolay bir yol ortaya çıkma eğilimindedir (multithreading burada atlayacağım kapsamlı bir konudur).

Hafıza Havuzu

Düşük gecikmeli programlamanın kritik bir yönü, muhtemelen referansın yerini ve aynı zamanda yalnızca bellek ayırma ve serbest bırakma genel hızını arttırmak için bellek üzerinde çok açık bir kontrol olacaktır. Özel bir tahsisatçı havuzlama hafızası aslında tarif ettiğimiz aynı tasarım zihniyetini yansıtıyor. Toplu için tasarlanmıştır ; kaba bir seviyede tasarlanmıştır. Hafızayı büyük bloklar halinde önceden tahsis eder ve halihazırda küçük parçalara tahsis edilen hafızayı havuzlar.

Bu fikir, pahalı şeyleri (örneğin, genel amaçlı bir tahsisatçıya karşı bir bellek öbeğini tahsis etmek gibi) daha kaba ve kaba bir seviyeye itmekle aynıdır. Bir bellek havuzu, büyük miktarda bellek ile başa çıkmak için tasarlanmıştır .

Tip Sistemleri Ayrı Bellek

Herhangi bir dilde ayrıntılı nesne yönelimli tasarımın zorluklarından biri, çoğu zaman ufacık kullanıcı tanımlı tür ve veri yapılarını tanıtmak istemesidir. Bu tipler, eğer dinamik olarak tahsis edilmişlerse, ufacık parçalara tahsis edilmek isteyebilirler.

C ++ 'da ortak bir örnek, polimorfizmin gerekli olduğu, doğal günaha bir alt sınıfın her bir örneğini genel amaçlı bir bellek ayırıcısına karşı tahsis etmek olduğu durumlar için olacaktır.

Bu, muhtemel-bitişik bellek düzenlerini, küçük bit-bit bitlerine ve adresleme aralığı boyunca dağılmış parçalara ayırır ve bu da daha fazla sayfa hatasına ve önbellek kaybına neden olur.

En düşük gecikme süresi, kekemesiz, deterministik yanıt gerektiren alanlar muhtemelen sıcak noktaların her zaman tek bir darboğaza kaymadığı, küçük verimsizliklerin gerçekten de "biriktirilebilecek" (çoğu insanın hayal ettiği bir şey) Bunları kontrol altında tutmak için bir profilleyicide yanlış bir şekilde oluyor, ancak gecikme kaynaklı alanlarda, aslında küçük verimsizliklerin biriktiği bazı nadir durumlar olabilir). Ve böyle bir birikimin en yaygın nedenlerinden birçoğu bu olabilir: ufacık bellek parçalarının her yere aşırı tahsisi.

Java gibi dillerde, bir dizi int(ancak yine de yüksek hacimli bir arayüzün arkasında) dizisi gibi darboğaz alanlarda (dar döngülerde işlenen alanlar) mümkün olduğunda daha eski düz veri türlerinden oluşan dizilerin kullanılması yararlı olabilir. , ArrayListkullanıcı tanımlı Integernesnelerden biri. Bu, tipik olarak ikincisine eşlik edecek olan bellek ayrımını önler. C ++ 'da, bellek ayırma düzenlerimiz etkin olduğunda, kullanıcı tanımlı türler bitişik olarak orada ve hatta genel bir kapsayıcı içinde tahsis edilebildiği için yapıyı bozmamız gerekmez.

Belleği Tekrar Birleştirmek

Burada bir çözüm, homojen veri türleri için ve hatta homojen veri türleri arasında bile özel bir tahsisatçıya ulaşmaktır. Küçük veri türleri ve veri yapıları bellekteki bit ve baytlara düzleştirildiğinde, homojen bir yapıya bürünür (bazı farklı hizalama gereksinimlerine rağmen). Onlara bellek merkezli bir zihniyetten bakmadığımız zaman, programlama dillerinin tip sistemi, potansiyel olarak bitişik bellek bölgelerini küçük ufacık dağınık parçalara bölmek / ayırmak ister.

Yığın, bunu önlemek ve potansiyel olarak kullanıcı tanımlı tür örneklerinin olası herhangi bir kombinasyonunu içinde saklamak için bu bellek merkezli odağı kullanır. Yığını daha fazla kullanmak, üst kısmı neredeyse her zaman bir önbellek çizgisinde oturduğu için mümkün olduğunda harika bir fikirdir, ancak aynı zamanda bir LIFO modeli olmadan bu özelliklerin bazılarını taklit eden ve ayrık veri türleri arasında belleği bitişik hale getiren bellek ayırıcıları tasarlayabiliriz. daha karmaşık bellek ayırma ve ayırma kalıpları için bile tıkanmalar.

Modern donanım, bitişik bellek bloklarını işlerken (aynı sayfa önbelleğine, aynı sayfaya, örneğin tekrar tekrar erişerek) erişirken en üst noktada olacak şekilde tasarlanmıştır. Buradaki anahtar kelime bitişiktir, çünkü yalnızca ilgi çekici veriler varsa yararlıdır. Bu yüzden performansın anahtarının (aynı zamanda zorluğunun) çoğu, ayrıştırılmış bellek parçalarını tekrar tahliye etmeden önce bütünlüklerine erişen bitişik bloklar halinde tekrar biraraya getirmektir. Programlama dillerinde özellikle kullanıcı tanımlı türlerin zengin tip sistemi buradaki en büyük engel olabilir, ancak uygun olduğunda özel bir tahsisatçı ve / veya hantal tasarımlarıyla soruna her zaman ulaşabilir ve çözebiliriz.

Çirkin

"Çirkin" demek zor. Bu öznel bir ölçümdür ve performans açısından kritik bir alanda çalışan bir kişi "güzellik" fikrini çok daha fazla veri odaklı ve toplu işleyen arayüzlere odaklanan bir fikirle değiştirmeye başlayacaktır.

Tehlikeli

"Tehlikeli" daha kolay olabilir. Genel olarak, performans daha düşük seviyeli kodlara ulaşmak ister. Örneğin, bir bellek ayırıcısı uygulamak, veri türlerinin altına ulaşmadan ve tehlikeli düzeyde ham bit ve bayt düzeyinde çalışmadan mümkün değildir. Sonuç olarak, performans açısından kritik olan bu alt sistemlerdeki dikkatli test prosedürüne odaklanmayı artırarak, uygulanan optimizasyon düzeyiyle testin bütünlüğünü ölçeklendirmeye yardımcı olabilir.

Güzellik

Bununla birlikte, bunların tamamı uygulama detay düzeyinde olacaktır. Hem kıdemli hem de performans açısından kritik bir zihniyet anlayışında “güzellik” uygulama detaylarından ziyade arayüz tasarımlarına yönelme eğilimindedir. Arayüz tasarımı değişikliği karşısında ortaya çıkabilecek birleşme ve basamaklı kırılmalar nedeniyle uygulamalardan ziyade "güzel", kullanışlı, güvenli, verimli arayüzler aramak üstel olarak daha yüksek bir öncelik haline geliyor. Uygulamalar herhangi bir zamanda değiştirilebilir. Genellikle, gerektiğinde performansa ve ölçümlerde belirtildiği gibi tekrarlamaya devam ediyoruz. Arayüz tasarımının anahtarı, tüm sistemleri bozmadan bu tür yinelemelere yer açmak için yeterince kaba bir model oluşturmaktır.

Aslında, emektarların performans açısından kritik gelişime odaklanmasının, genellikle bir dizi performansa sahip büyük ölçekli bir kod temeli içerdiğinden, genellikle genel olarak SE öğrencisi olan güvenlik, test etme, bakım yapılabilirliğe ağırlıklı bir odaklanma eğilimi göstereceğini düşünüyorum. Kritik alt sistemler (parçacık sistemleri, görüntü işleme algoritmaları, video işleme, ses geri bildirimi, ışın izleyicileri, ağ motorları, vb.) bir bakım kabusunda boğulmayı önlemek için yazılım mühendisliğine çok dikkat etmelidir. Dışarıdaki en şaşırtıcı derecede etkili ürünlerin çoğu zaman da en az sayıda böceğe sahip olması bir tesadüf değildir.

TL; DR

Her neyse, bu benim konuyla ilgili, performans açısından kritik olan alanlardaki önceliklerden, gecikmeyi azaltabilecek ve küçük verimsizliklerin birikmesine neden olan ve gerçekte "güzelliği" neyin oluşturduğu (şeylere en verimli şekilde bakarken) olan şey.


0

Farklı olmamak, ama işte yaptığım şey:

  1. Temiz ve bakım yapılabilir şekilde yazınız.

  2. Performans tanısı yapın ve tahmin ettiğiniz sorunları değil, size söylediği sorunları düzeltin. Garantili, beklediğinizden farklı olacaklar.

Bu düzeltmeleri hala açık ve sürdürülebilen bir şekilde yapabilirsiniz, ancak, kod ekleyenlerin neden böyle yaptığınızı bilmeleri için yorum eklemek zorundasınız. Eğer yapmazsan, geri alırlar.

Yani bir takas var mı? Ben öyle düşünmüyorum.


0

Çok hızlı çirkin kodunu yazabilir ve çirkin kodunuz kadar hızlı olan güzel kodu da yazabilirsiniz. Darboğaz, kodunuzun güzelliği / organizasyonu / yapısında değil, seçtiğiniz tekniklerde olacaktır. Mesela engelleyici olmayan soketler kullanıyor musunuz? Tek iş parçacıklı tasarım kullanıyor musunuz? İş parçacığı iletişimi için kilitsiz bir sıra kullanıyor musunuz? GC için çöp üretiyor musunuz? Kritik iş parçacığında herhangi bir engelleme G / Ç işlemi gerçekleştiriyor musunuz? Gördüğünüz gibi bunun güzellikle ilgisi yok.


0

Son kullanıcı için ne önemlidir?

  • performans
  • Özellikler / İşlevsellik
  • tasarlamak

Durum 1: Optimize edilmiş hatalı kod

  • Zor bakım
  • Açık kaynak kodlu bir proje olarak okunması zor

Durum 2: Optimize edilmemiş iyi kod

  • Kolay bakım
  • Kötü kullanıcı deneyimi

Çözüm?

Kolay, optimize performans kritik kod parçaları

Örneğin:

3'ü veri yönetimi, 1'i disk okuma, diğerini disk yazma olmak üzere 5 yöntemden oluşan bir program

Bu 3 veri yönetimi yöntemi, iki G / Ç yöntemini kullanır ve bunlara bağlıdır.

G / Ç yöntemlerini optimize ederdik.

Sebep: G / Ç yöntemlerinin değişme olasılığı daha düşüktür, ne de uygulamanın tasarımını etkiler ve sonuçta, o programdaki her şey bunlara bağlıdır ve bu nedenle performans açısından kritik görünüyorlar, bunları optimize etmek için hangi kodu kullanırdık .

Bu, kodun belirli kısımlarını optimize ederek hızlı tutarken programın iyi kodunu ve yönetilebilir tasarımını elde ettiğimiz anlamına gelir

Düşünüyorum..

Bence kötü kod, insanların cilalama-optimize etmeyi zorlaştırıyor ve küçük hatalar daha da kötüleşebilir, bu nedenle acemi / yeni başlayanlar için iyi bir kod, bu çirkin kodu iyi yazılmışsa daha iyi olacaktır.

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.