JIT ve Statik Derleyici
Önceki yazılarda belirtildiği gibi, JIT IL / bayt kodunu çalışma zamanında yerel koda derleyebilir. Bunun maliyetinden bahsedildi, ancak sonuca varılmadı:
JIT'in büyük bir sorunu, her şeyi derleyememesidir: JIT derlemesi zaman alır, bu nedenle JIT kodun yalnızca bazı kısımlarını derlerken, statik bir derleyici tam bir yerel ikili oluşturur: Bazı tür programlar için statik derleyici, JIT'den kolayca daha iyi performans gösterecektir.
Elbette, C # (veya Java veya VB) genellikle uygulanabilir ve sağlam bir çözüm üretmek için C ++ 'dan daha hızlıdır (eğer C ++' nın karmaşık anlambilimlere sahip olması ve C ++ standart kitaplığı, ilginç ve güçlü olmasına rağmen, tam sürümle karşılaştırıldığında oldukça zayıfsa) .NET veya Java'dan standart kitaplığın kapsamı), bu nedenle genellikle, C ++ ile .NET veya Java JIT arasındaki fark çoğu kullanıcı tarafından görülemez ve kritik olan ikili dosyalar için yine de C ++ işlemeyi çağırabilirsiniz. C # veya Java'dan (bu tür yerel çağrılar kendi başlarına oldukça maliyetli olsa bile) ...
C ++ meta programlama
Genellikle, C ++ çalışma zamanı kodunu C # veya Java'daki eşdeğeriyle karşılaştırdığınızı unutmayın. Ancak C ++, Java / C # 'dan daha iyi performans gösterebilen bir özelliğe sahiptir, yani şablon meta programlaması: Kod işleme derleme zamanında yapılacak (bu nedenle, derleme süresi büyük ölçüde artacak) ve sonuçta sıfır (veya neredeyse sıfır) çalışma zamanı elde edilecektir.
Henüz bu yüzden (Ben sadece kavramlarla oynadı ama o zamana kadar, fark JIT için yürütme saniye idi ve bu konuda gerçek bir hayat etkisini görmek var sıfır C ++ için), ama aslında şablon metaprograming değil yanında bu, bahsetmemiz olduğunu önemsiz ...
Düzenleme 2011-06-10: C ++ 'da, türlerle oynama, derleme zamanında yapılır, yani genel olmayan kodu çağıran genel kod üretilir (örneğin, dizeden T türüne genel bir ayrıştırıcı, tanıdığı T türleri için standart kitaplık API'sini çağırır, ve ayrıştırıcıyı kullanıcısı tarafından kolayca genişletilebilir hale getirmek) çok kolay ve çok etkilidir, oysa Java veya C # eşdeğerinin yazılması zahmetlidir ve türler derleme zamanında bilinse bile çalışma zamanında her zaman daha yavaş ve çözülür, Yani JIT'in her şeyi sıraya dizmesi tek umudunuz .
...
Düzenleme 2011-09-20: Blitz ++ ( Ana Sayfa , Wikipedia ) arkasındaki ekip bu şekilde gitti ve görünüşe göre hedefleri, FORTRAN'ın bilimsel hesaplamalardaki performansına, C ++ şablon metaprogramlama yoluyla, çalışma zamanı yürütmeden derleme süresine olabildiğince ilerleyerek ulaşmaktır. . "Yani ben henüz çok bu konuda gerçek bir hayat etkisini görmek var yukarıda yazdım parçası" görünüşte yapar Gerçek yaşamda var.
Yerel C ++ Bellek Kullanımı
C ++, Java / C # 'dan farklı bir bellek kullanımına sahiptir ve bu nedenle farklı avantajları / kusurları vardır.
JIT optimizasyonu ne olursa olsun, hiçbir şey belleğe doğrudan işaretçi erişimi kadar hızlı gidemez (bir an için işlemci önbelleklerini, vb. Görmezden gelelim). Dolayısıyla, bellekte bitişik veriler varsa, ona C ++ işaretçileri aracılığıyla erişmek (yani C işaretçileri ... Hadi Sezar'a sonunu verelim) Java / C # 'dan çok daha hızlı olacaktır. Ve C ++, RAII'ye sahiptir, bu da C # veya Java'dakinden çok daha kolay işlem yapar. C ++ 'nın using
nesnelerinin varlığını kapsaması gerekmez . Ve C ++ 'ın bir finally
cümleciği yoktur. Bu bir hata değildir.
:-)
Ve C # ilkel benzeri yapılara rağmen, C ++ "yığın üzerindeki" nesneler, ayırma ve yok etme işlemlerinde hiçbir maliyeti olmayacak ve temizliği yapmak için bağımsız bir iş parçacığında çalışmak için GC'ye ihtiyaç duymayacaktır.
Bellek parçalanmasına gelince, 2008'deki bellek ayırıcılar, genellikle bir GC: C ++ tahsisi ile karşılaştırılan 1980'den kalma eski bellek ayırıcılar değildir, doğru, ancak daha sonra, bir Linux dosya sisteminde olduğu gibi: Kim sabit diske ihtiyaç duyar parçalanma olmadığında birleştirme? Doğru görev için doğru ayırıcıyı kullanmak, C ++ geliştirici araç setinin bir parçası olmalıdır. Şimdi, ayırıcı yazmak kolay değil ve o zaman çoğumuzun yapacak daha iyi işleri var ve çoğu kullanım için RAII veya GC fazlasıyla iyi.
Düzenleme 2011-10-04: Verimli ayırıcılar hakkında örnekler için: Windows platformlarında, Vista'dan beri Düşük Parçalanma Yığını varsayılan olarak etkindir. Önceki sürümlerde LFH, WinAPI HeapSetInformation işlevi çağrılarak etkinleştirilebilir . Diğer işletim sistemlerinde alternatif ayırıcılar sağlanmıştır (bkz.https://secure.wikimedia.org/wikipedia/en/wiki/Malloc liste için)
Şimdi, bellek modeli, çok çekirdekli ve çok iş parçacıklı teknolojinin yükselişi ile biraz daha karmaşık hale geliyor. Bu alanda sanırım .NET'in avantajı var ve Java üst sıralarda yer aldı bana söylendi. Bazı "çıplak metal" korsanlarının "makinenin yanında" kodunu övmesi kolaydır. Ama şimdi, derleyicinin işine izin vermektense elle daha iyi montaj yapmak çok daha zor. C ++ için, derleyici on yıldan beri genellikle hacker'dan daha iyi hale geldi. C # ve Java için bu daha da kolaydır.
Yine de, yeni standart C ++ 0x, C ++ derleyicilerine basit bir bellek modeli uygulayacak, bu da C ++ 'da etkili çoklu işlem / paralel / iş parçacığı kodunu standartlaştıracak (ve böylece basitleştirecek) ve derleyiciler için optimizasyonları daha kolay ve daha güvenli hale getirecek. Ama sonra, vaatlerinin doğru olup olmadığını birkaç yıl içinde göreceğiz.
C ++ / CLI ve C # / VB.NET
Not: Bu bölümde, C ++ / CLI, yani yerel C ++ değil .NET tarafından barındırılan C ++ 'dan bahsediyorum.
Geçen hafta .NET optimizasyonu üzerine bir eğitim aldım ve statik derleyicinin yine de çok önemli olduğunu keşfettim. JIT'den daha önemli.
C ++ / CLI'de (veya onun atası olan Managed C ++) derlenen aynı kod, C #'da üretilen aynı koddan (veya derleyicisi C # ile aynı IL'yi üreten VB.NET) kat kat daha hızlı olabilir.
Çünkü C ++ statik derleyici, zaten optimize edilmiş kod üretmek için C #'lardan çok daha iyiydi.
Örneğin, .NET'te işlev satır içi işlemi, bayt kodu uzunluğu 32 bayttan az veya buna eşit olan işlevlerle sınırlıdır. Bu nedenle, C #'daki bazı kodlar 40 baytlık bir erişimci üretecek ve bu, JIT tarafından hiçbir zaman satır içi olmayacak. C ++ / CLI'deki aynı kod, JIT tarafından satır içine alınacak 20 baytlık bir erişimci üretecektir.
Başka bir örnek, C # derleyicisi tarafından üretilen IL'de bahsedilmeye devam ederken, C ++ derleyicisi tarafından derlenen geçici değişkenlerdir. C ++ statik derleme optimizasyonu daha az kodla sonuçlanacak ve böylece yine daha agresif bir JIT optimizasyonuna izin verecektir.
Bunun nedeninin, C ++ / CLI derleyicisinin C ++ yerel derleyicinin geniş optimizasyon tekniklerinden yararlandığı gerçeği olduğu düşünülüyordu.
Sonuç
C ++ 'yı seviyorum.
Ama gördüğüm kadarıyla, C # veya Java hepsi daha iyi bir bahis. C ++ 'dan daha hızlı oldukları için değil, niteliklerini topladığınızda, daha üretken olurlar, daha az eğitime ihtiyaç duyarlar ve C ++' dan daha eksiksiz standart kitaplıklara sahip olurlar. Ve programların çoğunda olduğu gibi, hız farklılıkları (öyle ya da böyle) önemsiz olacaktır ...
Düzenle (2011-06-06)
C # /. NET konusundaki deneyimim
Şu anda 5 aylık neredeyse özel profesyonel C # kodlamam var (bu da zaten C ++ ve Java ile dolu CV'mi ve C ++ / CLI dokunuşunu ekliyor).
WinForms (Ahem ...) ve WCF (harika!) Ve WPF (Harika !!!! Hem XAML hem de ham C # aracılığıyla. WPF çok kolay Swing'in bununla kıyaslanamayacağına inanıyorum) ve C # 4.0.
Sonuç olarak, C # / Java'da çalışan bir kod üretmek C ++ 'dan daha kolay / daha hızlı olsa da, C # ile güçlü, güvenli ve sağlam bir kod üretmek (ve Java'da daha da zor) C ++' dan çok daha zordur. Sebepler çoktur, ancak şu şekilde özetlenebilir:
- Jenerikler, şablonlar kadar güçlü değildir ( sorunu anlamak için verimli bir genel Parse yöntemi (dizeden T'ye) veya boost :: lexical_cast'in C # 'da etkin bir eşdeğerini yazmaya çalışın )
- RAII eşsiz kalır ( GC hala sızıntı yapabilir (evet, bu sorunu halletmem gerekiyordu) ve sadece belleği idare edecek. C # 'ler bile
using
kolay ve güçlü değildir çünkü doğru Dispose uygulamaları yazmak zordur )
- C #
readonly
ve Java final
gibi yararlı olarak hiçbir yerde vardır C ++ 'ınconst
( o yerleşik bir C ++ özelliği. Bu tür veriler ilginç bir çözümdür çalışırken siz muazzam iş olmadan C # salt okunur karmaşık veriler örneğin Düğümler (a Ağacı,) maruz hiçbir şekilde var, , ancak her şey değiştirilemez hale getirilemez, bu nedenle, şimdiye kadar yeterli bile değildir ).
Dolayısıyla, C #, çalışan bir şey istediğiniz sürece hoş bir dil olarak kalır, ancak her zaman ve güvenli bir şekilde çalışan bir şeyi istediğiniz anda sinir bozucu bir dildir .
Java, C # ile aynı sorunlara sahip olduğu için daha da sinir bozucu ve daha fazlası: C # using
anahtar kelimesinin eşdeğerinden yoksun olan çok yetenekli bir meslektaşım, kaynaklarının doğru bir şekilde serbest bırakıldığından emin olmak için çok zaman harcadı, oysa C ++ 'daki eşdeğer kolay oldu (yıkıcılar ve akıllı işaretçiler kullanarak).
Bu yüzden, C # / Java'nın üretkenlik kazancı çoğu kod için görülebilir ... koda olabildiğince mükemmel olması için ihtiyacınız olan güne kadar. O gün acıyı anlayacaksın. (sunucumuzdan ve GUI uygulamalarımızdan ne istediğine inanmayacaksınız ...).
Sunucu tarafı Java ve C ++ hakkında
Binanın diğer tarafında sunucu ekipleriyle (GUI ekibine dönmeden önce aralarında 2 yıl çalıştım) iletişimimi sürdürdüm ve ilginç bir şey öğrendim.
Geçtiğimiz yıllarda eğilim, Java sunucu uygulamalarının eski C ++ sunucu uygulamalarının yerini alması yönündeydi, çünkü Java çok sayıda çerçeve / araca sahip ve bakımı, dağıtımı vb. Kolay.
... Düşük gecikme sorunu son aylarda çirkin yüzünü gösterene kadar. Ardından, Java sunucu uygulamaları, yetenekli Java ekibimiz tarafından denenen optimizasyon ne olursa olsun, eski, gerçekten optimize edilmemiş C ++ sunucusuna karşı yarışı basit ve temiz bir şekilde kaybetti.
Şu anda karar, Java sunucularını, performansın hala önemliyken, düşük gecikme hedefiyle ilgilenmediği yerlerde ortak kullanım için tutmak ve düşük gecikme ve ultra düşük gecikme gereksinimleri için zaten daha hızlı olan C ++ sunucu uygulamalarını agresif bir şekilde optimize etmektir.
Sonuç
Hiçbir şey beklendiği kadar basit değil.
Java ve hatta daha fazlası C #, hızlı kod yazabileceğiniz ve çok kısa sürede sonuç alabileceğiniz kapsamlı standart kitaplıkları ve çerçeveleriyle harika dillerdir.
Ancak ham güce, güçlü ve sistematik optimizasyonlara, güçlü derleyici desteğine, güçlü dil özelliklerine ve mutlak güvenliğe ihtiyacınız olduğunda, Java ve C #, son eksik ancak kritik kalite yüzdelerini kazanmanızı zorlaştırır, rekabetin üzerinde kalmanız gerekir.
Ortalama kalitede kod üretmek için C # / Java'da C ++ 'dan daha az zamana ve daha az deneyimli geliştiricilere ihtiyaç duyuyormuşsunuz gibi, ancak diğer yandan, mükemmelden mükemmel kalitede koda ihtiyaç duyduğunuz anda, sonuçları almak aniden daha kolay ve daha hızlı hale geldi doğru C ++ içinde.
Tabii ki, bu benim kendi algım, belki de özel ihtiyaçlarımızla sınırlı.
Ama yine de bugün hem GUI ekiplerinde hem de sunucu tarafı ekiplerinde olan budur.
Tabii ki, yeni bir şey olursa bu gönderiyi güncelleyeceğim.
Düzenle (2011-06-22)
"Performans açısından, C ++ 'nın büyük bir farkla kazandığını görüyoruz. Bununla birlikte, aynı zamanda, çoğu, ortalama bir programcının erişemeyeceği bir karmaşıklık düzeyinde yapılan en kapsamlı ayarlama çabalarını da gerektiriyordu.
[...] Java sürümü muhtemelen uygulanması en basit olanıydı, ancak performans açısından analizi en zor olanıydı. Özellikle çöp toplama etrafındaki etkiler karmaşıktı ve ayarlanması çok zordu. "
Kaynaklar:
Düzenle (2011-09-20)
"Facebook'ta geçerli olan kelime, PHP ve Java kodunu optimize etmek için harcanan muazzam çabanın altını çizen ' makul bir şekilde yazılmış C ++ kodunun hızlı çalışmasıdır. Paradoksal olarak, C ++ kodu yazmak diğer dillerden daha zordur, ancak verimli kod [C ++ ile yazmak diğer dillere göre] çok daha kolay. "
- Herb Sutter de // yapı / , alıntı Andrei Alexandrescu
Kaynaklar: