C ++ C # 'den daha hızlıdır?


246

Yoksa şimdi tam tersi mi?

Duyduğum kadarıyla, C # 'ın C ++' dan daha hızlı olduğu kanıtlanan bazı alanlar var, ancak kendim test etmek için cesaretim olmadı.

Herhangi birinizin bu farklılıkları ayrıntılı olarak açıklayabileceğini veya bu konuda bilgi için beni doğru yere yönlendirebileceğini düşündüm.


7
Daha rastgele ölçütlerin gönderilmesini önlemek için korumalı. Davanızı yapabileceğinizi düşünüyorsanız, bunu yapmak için 10 temsilciniz olması gerekir.
Robert Harvey

2
Bu nasıl olsa görüş / tartışmacı olarak nasıl kapatılmaz? Hala StackOverflow'da değil miyim? (Yakın önermek değil, sadece meraklı. Tartışılan argümanları teşvik eden soruları seviyorum)
Bill K


Aralık dışı dizi erişimini kontrol eden bir dil, yapmayan dilden daha iyi performans göstermez.
Seva Alekseyev

@SevaAlekseyev Bunu yapan dil değil, derleyici. C ++ 'ın nedenlerinden biri hızlıdır (bariz olanların dışında) C ++ derleyicilerinin son 35 yıldır (daha fazla değilse) olmasıdır. C # derleyicilerinin zamanla daha iyi olmasını engelleyen hiçbir şey yoktur. Bahsettiğiniz dava için, lütfen şu stackoverflow.com/questions/16713076/…
Tuzak

Yanıtlar:


343

C # veya Java gibi bir bayt kodu tabanlı dilin JIT'e sahip olmasının C ++ kodu kadar hızlı olmamasının kesin bir nedeni yoktur. Bununla birlikte, C ++ kodu eskiden çok daha hızlıydı ve bugün hala birçok durumda. Bunun nedeni, daha gelişmiş JIT optimizasyonlarının uygulanması karmaşık olması ve gerçekten harika olanların sadece şu anda ulaşmasıdır.

Yani C ++ çoğu durumda daha hızlıdır. Ama bu sadece cevabın bir parçası. C ++ 'ın gerçekten daha hızlı olduğu durumlar, uzman programcıların kodun cehennemini iyice optimize ettiği yüksek derecede optimize edilmiş programlardır. Bu sadece çok zaman alıcı (ve dolayısıyla pahalı) değildir, aynı zamanda aşırı optimizasyonlar nedeniyle sıklıkla hatalara yol açar.

Öte yandan, yorumlanmış dillerdeki kod, çalışma zamanının sonraki sürümlerinde (.NET CLR veya Java VM), hiçbir şey yapmadan daha hızlı hale gelir. Ve JIT derleyicilerinin yapabileceği birçok yararlı optimizasyon vardır. Ayrıca, bazıları çöp toplamanın genellikle manuel bellek yönetimi kadar hızlı veya daha hızlı olması gerektiğini ve birçok durumda olduğunu iddia etmektedir. Genel olarak tüm bunları C ++ veya C'de uygulayabilir ve başarabilirsiniz, ancak çok daha karmaşık ve hataya eğilimli olacaktır.

Donald Knuth'un dediği gibi, "erken optimizasyon tüm kötülüklerin köküdür". Uygulamanızın çok performans açısından kritik aritmetikten oluşacağından ve bunun darboğaz olacağını ve C ++ 'da kesinlikle daha hızlı olacağından ve C ++' nın diğerinizle çakışmayacağından eminseniz gerçekten C ++ gereksinimlerini karşılayın. Başka bir durumda, önce uygulamanızı size en uygun dile uygun şekilde uygulamaya odaklanın, ardından çok yavaş çalışıyorsa performans darboğazlarını bulun ve ardından kodu nasıl optimize edeceğinizi düşünün. En kötü durumda, yabancı bir işlev arabirimi aracılığıyla C kodunu çağırmanız gerekebilir, bu nedenle kritik parçaları daha düşük seviyeli dilde yazabileceksiniz.

Doğru bir programı optimize etmenin nispeten kolay olduğunu, ancak optimize edilmiş bir programı düzeltmenin çok daha zor olduğunu unutmayın.

Hız avantajlarının gerçek yüzdelerini vermek imkansızdır, büyük ölçüde kodunuza bağlıdır. Çoğu durumda, programlama dili uygulaması darboğaz bile değildir. Http://benchmarksgame.alioth.debian.org/ adresindeki ölçütleri büyük ölçüde şüphecilikle alın, çünkü bunlar büyük olasılıkla kodunuza hiç benzemeyen aritmetik kodu test eder.


92
<quote> yorumlanmış dillerdeki kod çalışma zamanının sonraki sürümlerinde hızlanır </quote> Derleyicinin daha iyi bir sürümü tarafından derlenen kodlar da hızlanır.
Martin York

47
Aslında en az bir neden var: JIT hızlı olmalı ve bir C ++ derleyicisinin kullanabileceği çeşitli gelişmiş optimizasyonlara zaman harcayamaz.
Nemanja Trifunovic

63
"ancak aynı zamanda aşırı optimizasyon nedeniyle hatalara da yol açar." [alıntıya umutsuzca ihtiyaç var]. Ulusal bir laboratuvarda çalışıyorum ve kodumuzun dışına çıkıyoruz. Bu genellikle buggy kodu ile sonuçlanmaz.
Todd Gamblin

35
"Doğru bir programı optimize etmek nispeten kolaydır, ancak optimize edilmiş bir programı düzeltmek çok daha zordur."
gradbot

20
Inge: Orada doğru yolda olduğunuzdan emin değilsiniz. Evet, C # başka bir dilde uygulandı, ancak JIT derleyicisi makine kodu üretiyor, bu yüzden yorumlanmış bir dil değil. Bu nedenle, C ++ uygulamasıyla sınırlı değildir. Neden bir şeye yönetici eklemeyi daha hızlı hale getirdiğini sanmıyorum.
Martin Probst

202

C # daha hızlı olmayabilir, ancak YOU / ME'yi daha hızlı yapar. Yaptığım şey için en önemli ölçü bu. :)


68
Haha, Larry Wall tarafından konuyla ilgili güzel bir alıntı var. Perl hakkında konuşuyor, ancak dil ve performans içeren tüm tartışmalar için düşünülebilir: "..Fortran ve C gibi eski bilgisayar dilleri pahalı bilgisayar donanımını verimli kullanmak için tasarlandı. Buna karşılık Perl, pahalı bilgisayar programcıları verimli kullanmak "
Falaina

60
1. "C #, C ++ 'dan çok daha hızlıdır" 2. "Doğru olamaz" 1. "Elbette" 2. "Ne kadar?" 1. "Genellikle 3-4 ay arası"
Dmitry S.

2
gerçekten kullandığınız kütüphanelere bağlı C ++ için, C # genellikle daha hızlı değildir, .NET, üretkenlik söz konusu olduğunda
Ion Todirel

Bazı kod yazmak için C yerine Python'u kullanmanızın nedeni de budur ... ancak bazı ağır hesaplamalar oluşturduktan sonra performanstaki farkı hissedebilirsiniz.
Ch3shire

Bu sizin alışık olduğunuz şeye bağlıdır. C ++ C # sahip daha hızlı program. Temel görevler için tekerleği yeniden icat etmek istemediğiniz için kütüphane bilgisi bunun büyük bir parçasıdır. C / C ++ ana sorun, akıllı işaretçilerle hemen hemen çözülmüş olan işaretçi yönetimi idi. C ++ ciddi .NET ve Java sunduğu gibi geniş bir kütüphane eksik olduğunu söyledi ve bu geliştirme büyük ölçüde hızlandırabilir. Bu std oğlanlar zamanlarını kütüphane uzantıları yerine şablon iyileştirmeleri için harcamak istedikleri için bu yakında çözülmeyecek.
gast128

87

Beş portakal daha hızlı. Ya da daha doğrusu: (doğru) battaniye cevabı olamaz. C ++ statik olarak derlenmiş bir dildir (ancak daha sonra profil yönlendirmeli optimizasyon da vardır), C # bir JIT derleyicisi tarafından desteklenir. “Ne kadar daha hızlı” gibi soruların, büyüklük emirleri vererek bile cevaplanamayacağı kadar çok fark vardır.


177
Çirkin beş portakal iddianızı destekleyecek kanıtınız var mı? Deneylerim, şablon metaprogramlama yaparken 3 mango iyileştirmesi ile en fazla 2 portakal gösteriyor.
Alex

42
Mayada o daha hızlı hors d'oeuvres clamming değil.
Chris

11
Deneyimlerime göre oldukça 5.2 portakal. Ancak bu, kullandığınız meyve-metreye bağlıdır.
Dio F

4
Güncelleme, StackOverflow'un kendisi berbat ve yorumları verimsiz işliyor
KeksArmee

87

Bu soruya kabul edilen (ve iyi değerlendirilmiş) cevabın bir kısmına şunu söyleyerek katılmıyorum:

JITted kodunun uygun şekilde optimize edilmiş bir C ++ (veya çalışma zamanı ek yükü olmayan başka bir dil) programından daha yavaş çalışmasının birçok nedeni vardır :

  • çalışma zamanında JITting koduna harcanan hesaplama döngüleri, tanım gereği, program yürütülmesinde kullanılamaz.

  • JITter'daki herhangi bir etkin yol, CPU'daki talimat ve veri önbelleği için kodunuzla rekabet edecektir. Performans söz konusu olduğunda önbelleğin baskın olduğunu biliyoruz ve C ++ gibi anadillerde tanım gereği bu tür bir çekişme yok.

  • bir çalışma zamanı optimize edicisinin zaman bütçesi, derleme zamanı optimize edicisinin bütçesinden çok daha kısıtlıdır (başka bir yorumcunun belirttiği gibi)

Sonuç: Sonuçta, sen olacak neredeyse kesinlikle C # yapabileceğinden daha C ++ daha hızlı uygulanmasını oluşturabileceksiniz .

Şimdi, bununla birlikte, ne kadar hızlı , çok fazla değişken olduğu için gerçekten ölçülemez: görev, sorun alanı, donanım, uygulamaların kalitesi ve diğer birçok faktör. Performans farkını belirlemek için senaryonuzda testler yaparsınız ve daha sonra ek çaba ve karmaşıklığa değip değmeyeceğine karar verirsiniz.

Bu çok uzun ve karmaşık bir konudur, ancak C # 'ın çalışma zamanı optimize edicisinin mükemmel olduğu ve derleme zamanı ile C ++ tarafından kullanılamayan belirli dinamik optimizasyonları gerçekleştirebildiği tamlık uğruna bahsetmeye değer hissediyorum. statik) optimize edici. Bununla bile, avantaj hala tipik olarak yerel uygulamanın mahkemesinde derindir, ancak dinamik optimize edici, yukarıda verilen " neredeyse kesinlikle" niteleyicisinin nedenidir .

-

Göreceli performans açısından, diğer bazı cevaplarda gördüğüm rakamlar ve tartışmalardan da rahatsız oldum, bu yüzden yukarıda verdiğim ifadelere biraz destek vereceğimi düşündüm.

Bu ölçütlerle ilgili sorunun büyük bir kısmı, C # yazıyormuşsunuz gibi C ++ kodu yazamamanız ve temsili sonuçlar almayı beklemenizdir (örn. C ++ 'da binlerce bellek ayırma işlemi yapmak size korkunç sayılar verecektir.)

Bunun yerine, biraz daha deyimsel C ++ kodu yazdım ve sağlanan C # kodu ile karşılaştırıldığında @Wiory. C ++ kodunda yaptığım iki büyük değişiklik:

1) kullanılan vektör :: rezerv ()

2) daha iyi önbellek konumu elde etmek için 2d dizisini 1d'ye düzleştirdi (bitişik blok)

C # (.NET 4.6.1)

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);
}

Çalışma süresi (Serbest Bırakma): Başlatma: 124ms, Dolgu: 165ms

C ++ 14 (Clang v3.8 / C2)

#include <iostream>
#include <vector>

auto TestSuite::ColMajorArray()
{
    constexpr size_t ROWS = 5000;
    constexpr size_t COLS = 9000;

    auto initStart = std::chrono::steady_clock::now();

    auto arr = std::vector<double>();
    arr.reserve(ROWS * COLS);

    auto initFinish = std::chrono::steady_clock::now();
    auto initTime = std::chrono::duration_cast<std::chrono::microseconds>(initFinish - initStart);

    auto fillStart = std::chrono::steady_clock::now();

    for(auto i = 0, r = 0; r < ROWS; ++r)
    {
        for (auto c = 0; c < COLS; ++c)
        {
            arr[i++] = static_cast<double>(r * c);
        }
    }

    auto fillFinish = std::chrono::steady_clock::now();
    auto fillTime = std::chrono::duration_cast<std::chrono::milliseconds>(fillFinish - fillStart);

    return std::make_pair(initTime, fillTime);
}

Çalışma süresi (Serbest Bırakma): Başlatma: 398µs (evet, bu mikrosaniye), Dolgu: 152ms

Toplam Çalışma süresi: C #: 289ms, C ++ 152ms (kabaca% 90 daha hızlı)

Gözlemler

  • C # uygulamasının aynı 1d dizi uygulamasına değiştirilmesi Init: 40ms, Fill: 171ms, Toplam: 211ms ( C ++ hala neredeyse% 40 daha hızlıydı ) verdi.

  • C ++ 'da "hızlı" kod tasarlamak ve yazmak her iki dilde de "normal" kod yazmaktan daha zordur.

  • C ++ 'da kötü performans elde etmek şaşırtıcı derecede kolaydır; bunu çekilmemiş vektör performansı ile gördük. Ve bunun gibi birçok tuzak var.

  • C # 'ın performansı, çalışma zamanında olup bittiğini düşündüğünüzde oldukça şaşırtıcı. Ve bu performansa erişmek nispeten daha kolaydır.

  • C ++ ve C # performansını karşılaştıran daha fazla fıkra verileri: https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=gpp&lang2=csharpcore

Sonuç olarak, C ++ size performans üzerinde çok daha fazla kontrol sağlıyor. Bir işaretçi kullanmak istiyor musunuz? Referans? Yığın bellek? Yığın? Dinamik polimorfizm veya statik polimorfizm (şablonlar / CRTP aracılığıyla) ile bir vtable çalışma zamanı yükünü ortadan kaldırmak? C ++ 'da ... er, almak zorunda , ideal böylece çözüm iyi adresleri sorun sen tackling olduğunu, (ve daha fazla) kendinizi tüm bu seçimler yapmak.

Kendinize bu kontrolü gerçekten isteyip istemediğinizi sorun, çünkü yukarıdaki önemsiz örnek için bile, performansta önemli bir gelişme olsa da, erişmek için daha derin bir yatırım gerektirdiğini görebilirsiniz.


16
@Quonux yorum için teşekkür ederim. Tabii ki bu bir "gerçek program" değil. Karşılaştırmaların noktası, JITted kodunun bir şekilde yerelden daha hızlı olduğuna dair kanıt olarak bu sayfanın başka bir yerinde sunulan bir C # karşılaştırmasını yeniden düzenledi - değil ve kıyaslama potansiyel olarak yeni insanlar için yanıltıcıydı.
U007D

9
@Quonux neden böyle yazmak zorundasın? Senin gibi insanlar beni yığın akışından hoşlanmamasına neden oluyor.
Markus Knappen Johansson

5
@MarkusKnappenJohansson Kötü bir gün geçirdim;), ben de bir insanım, downvote'umu kaldırdım, ancak görüşüm hala geçerli. Oh lütfen sadece "aptal" insanlar var çünkü SO sevmiyorum :). Güzel bir tane var.
Quonux

9
TAMAMEN YANLIŞ BENCHMARK. C ++ sürümünde belleğin bir kısmını ayırırsınız (ve daha sonra bu işlemin mikrosaniyeyi nasıl yürüttüğüne hayret edersiniz). C # sürümünde 5000 ARRAYS (bellekteki nesneleri örnekleme) oluşturuyorsunuz. C ++, C #'dan daha hızlı ... ancak fark% 40'a yakın değil ... şu anda <% 10 aralığında. Örneğinizin gösterdiği gibi, programcıların kendi seçtikleri dile sadık kalmaları gerektiğidir (ve profilinizden kariyer C ++ programcısı olduğunuz açıktır). C # 'da 2B dizi yapabilirsiniz int[,]... bunu örnekle takip edin.
nikib3ro

3
Ne söyleyebilirim, C ++ örneğinizdeki kod tam anlamıyla sadece bellek vaktinden ayırıyor. PROPER C # uygulaması, 2 boyutlu diziyi 1 boyutlu formatta dizine ayırmak için gerekli olan belleği ayıran 'List <double> arrs = new List <double> (ROWS * COLS)' yazacaktır (örn. C ++ ile yaptıklarınız). 2 boyutlu bir dizi ayırmak ve manuel olarak düzleştirmek için kesinlikle hiçbir neden yoktur - ön testinizdeki büyük miktarda yineleme, boktan performansın nedenidir. Tepegöz hala C # daha fazla olacağını, ancak önemli miktarda değil hayal.
JDSweetBeat

62

Deneyimlerime göre (ve her iki dilde de çok çalıştım), C # ile karşılaştırıldığında ana sorun C ++ ile karşılaştırıldığında yüksek bellek tüketimi ve bunu kontrol etmek için iyi bir yol bulamadım. Sonunda .NET yazılımını yavaşlatan bellek tüketimiydi.

Başka bir faktör, JIT derleyicisinin gelişmiş optimizasyonlar yapmak için çok fazla zaman harcamamasıdır, çünkü çalışma zamanında çalışır ve son kullanıcı çok fazla zaman alırsa bunu fark eder. Öte yandan, bir C ++ derleyicisi derleme zamanında optimizasyon yapmak için gereken her zaman vardır. Bu faktör IMHO bellek tüketiminden çok daha az önemlidir.


6
İşteki bir projede, aynı anda birçok GB'yi bellekte tutmak ve hepsinde pahalı hesaplamalar yapmak da dahil olmak üzere çok büyük miktarda veri çıkarmak zorunda kaldık - bu, tüm tahsislerin hassas kontrolünü gerektiriyordu, C ++ hemen hemen tek seçenekti. C ++ için +1. Öte yandan, bu sadece bir projeydi, zaman simülasyonlarımızın çoğunu yavaş simülatörlerle etkileşime girerek geçirdik ve hata ayıklama bir kabus olabilir, bu yüzden diğer tüm programlar için programcı zamanı optimize eden bir dil kullanabilmeyi diledim şey.
Bogatyr

7
@IngeHenriksen: Dispose deseninin iyi farkındayım, ancak yönetilen bellekle hiç yardımcı olmuyor.
Nemanja Trifunovic

10
@IngeHenriksen imha sadece Dispose yönteminin çağrılmasını sağlar. İmha etme, toplanan çöpleri asla serbest bırakmaz. Dispose yöntemi yalnızca dosya tanıtıcıları gibi yönetilmeyen kaynakları temizlemek için tasarlanmıştır ve bellek yönetimi ile ilgisi yoktur.
doug65536

1
@NemanjaTrifunovic: "JIT derleyicisi gelişmiş optimizasyon yapmak için çok fazla zaman harcayamaz". Çok uzun sürecekleri için JIT'ler tarafından yapılmayan bazı optimizasyonlardan bahsedebilir misiniz?
Jon Harrop

5
@ user3800527: RAM eklemek her zaman mümkün olsa bile (ve her Microsoft Office kullanıcısına RAM eklediğini hayal edin) sorunu çözmeyecektir. Bellek hiyerarşiktir ve bir C # programı, C ++ birinden daha fazla önbellek kaybına sahiptir.
Nemanja Trifunovic

35

C ++ 'ın hala daha üstün olduğu (ve gelecek yıllar boyunca) polimorfik kararlar derleme zamanında önceden belirlendiğinde ortaya çıkan belirli bir senaryo gerçekleşir.

Genel olarak, kapsülleme ve ertelenmiş karar verme iyi bir şeydir, çünkü kodu daha dinamik, değişen gereksinimlere adapte etmeyi ve çerçeve olarak kullanmayı kolaylaştırır. Bu nedenle C # 'da nesne yönelimli programlama çok verimlidir ve “genelleme” terimi altında genelleştirilebilir. Ne yazık ki, bu tür bir genelleme çalışma zamanında bir maliyet getirmektedir.

Genellikle, bu maliyet önemli değildir, ancak sanal yöntem çağrılarının ve nesne oluşturma yükünün bir fark yaratabileceği uygulamalar vardır (özellikle sanal yöntemler, yöntem çağrısı satır içi gibi diğer optimizasyonları önlediğinden). Bu, C ++ 'ın büyük bir avantajı olduğu için , çalışma zamanı üzerinde hiçbir etkisi olmayan , ancak mutlaka OOP'tan daha az polimorfik olmayan farklı bir genelleme elde etmek için şablonları kullanabilirsiniz . Aslında, OOP'yi oluşturan tüm mekanizmalar sadece şablon teknikleri ve derleme zamanı çözünürlüğü kullanılarak modellenebilir.

Bu gibi durumlarda (ve kuşkusuz, bunlar genellikle özel sorunlu alanlarla sınırlıdır), C ++, C # ve karşılaştırılabilir dillere karşı kazanır.


6
Aslında, Java VM'leri (ve muhtemelen .NET) dinamik gönderimi önlemek için büyük çaba harcarlar. Temel olarak, polimorfizmlerden kaçınmanın bir yolu varsa, VM'nizin bunu yapacağından emin olabilirsiniz.
Martin Probst

3
+1 Ben her zaman küçük C ++ bilen onların önemini takdir edecek şekilde bilen C # meslektaşlarıma açıklamakta sorun yaşıyorum. Oldukça güzel açıkladın.
Roman Starkov

9
@crtracy: yüksek performanslı bilgi işlem uygulamaları olmadan bahsinizi oynarsınız. Hava tahmini, biyoinformatik ve sayısal simülasyonları düşünün. Bu alanlarda C ++ performans kurşun edecek değil başka hiçbir kod yüksek soyutlama aynı düzeyde karşılaştırılabilir performans elde edebilirsiniz, çünkü küçültmek.
Konrad Rudolph

5
@Jon Elma ve portakal. Sizin özel iddianız “C # metaprogramlama bağlamında C ++ 'dan daha büyük büyüklük sıralarıdır”, “önceden derlenmiş kod kullanmak yorumlanmış koddan daha büyük büyüklük sıralarıdır”. Biz buna rağmen, çalışma zamanı kod oluşturmanın derleme zamanı kod üretmekten “daha ​​genel” olduğu iddiası da açıkça yanlıştır - her ikisinin de güçlü ve zayıf yanları vardır. Derleme zamanı kod oluşturma statik tip güvenliğini sağlamak için tip sistemi kullanır - çalışma zamanı kod üretme ki (o yapamaz yapabilirsiniz güçlü tip güvenliğini değil sağlamak statik tip güvenliği).
Konrad Rudolph

5
@ user3800527 Bu cevabın bütün noktasını kaçırdığınızı düşünüyorum. Tabii ki, kapsüllemeyi kırarak ve düşük seviyeli yapılara düşerek bu sorunu çözebilirsiniz - montajı (çoğu) herhangi bir dilde yazabilirsiniz. C ++ 'yı (neredeyse) benzersiz kılan ve yüksek performanslı programlama için benzersiz bir şekilde uygun olan şey, çalışma zamanı maliyeti olmadan yüksek seviyeli soyutlamalar oluşturabilmenizdir . Bu nedenle, üstün performans elde etmek için C ++ 'da derleme benzeri kod yazmanıza gerek yoktur: iyi yazılmış bir C ++' da elle yazılmış bir döngü kadar verimli olacaktır. Asla C # 'da olmayacak. sort(arr, generic_comparer)
Konrad Rudolph

20

C ++ (veya bu konu için C) veri yapılarınız üzerinde ayrıntılı kontrol sağlar. Eğer bit-twiddle istiyorsanız bu seçeneğiniz var. Java / .NET kitaplıklarının dahili veri yapılarını kullanan büyük yönetilen Java veya .NET uygulamaları (OWB, Visual Studio 2005 ) bagajı yanlarında taşır. Küp veya ETL tasarımı için 400 MB'den fazla RAM ve BIDS kullanan OWB tasarımcı oturumlarını 100'lerin MB'larına girerken gördüm .

Öngörülebilir bir iş yükünde (bir işlemi birçok kez tekrarlayan çoğu kriter gibi) bir JIT, pratik bir fark olmayacak kadar iyi optimize edilmiş bir kod alabilir.

IMO büyük uygulamalarda fark kodun kullandığı veri yapıları kadar JIT değildir. Bir uygulamanın bellek ağırlıklı olduğu durumlarda, daha az verimli önbellek kullanımı elde edersiniz. Modern CPU'lardaki önbellek özledikleri oldukça pahalıdır. C veya C ++ 'nın gerçekten kazandığı yer, CPU önbelleği ile güzel oynamak için veri yapıları kullanımınızı optimize edebileceğiniz yerdir.


19

Grafikler için standart C # Graphics sınıfı, C / C ++ ile erişilen GDI'dan çok daha yavaştır. Bunun kendi başına dil ile ilgisi olmadığını biliyorum, daha fazla toplam .NET platformu ile, ancak Grafikler geliştiriciye bir GDI değiştirme olarak sunulan şeydir ve performansı o kadar kötü ki grafik yapmaya bile cesaret edemem Bununla.

Bir grafik kütüphanesinin ne kadar hızlı olduğunu görmek için kullandığımız basit bir karşılaştırmamız var ve bu sadece bir pencerede rastgele çizgiler çiziyor. C ++ / GDI, 10000 satır ile hala çabukken, C # / Graphics 1000 gerçek zamanlı olarak zorluk çekiyor.


5
Cevabınız beni çok etkiledi. Güvenli olmayan kod ve kilit parçalarıyla aynı ölçütü test ettiniz ve rastgele çizgileri kendiniz çizdiniz mi? Şimdi bu ilginç bir şey olurdu.
Pedery

2
@ Peded hayır hayır. sadece GDI ve .NET.Graphics'i en temel yollarla kullanmak. "Rastgele çizgileri kendiniz çizerek" ne demek?
QBziZ

1
O zaman belki de C # ne kadar hızlı olabileceğine dair daha gerçekçi bir metrik elde etmek için bunu test etmeyi düşünmelisiniz. İşte tekniğe güzel bir genel bakış: bobpowell.net/lockingbits.htm
Pedery

6
Bir çerçeve arabelleğine ayrı pikseller koyarak kendimiz yapmak istediğimiz bu değil. Her şeyi kendiniz uygulamak zorundaysanız, kodlamak için bir API / Platform'a sahip olmanın anlamı nedir? Benim için bu bir argüman değil. Çizim çizgileri için GDI'daki bir çerçeve tamponuna asla ayrı pikseller koymamız gerekmedi ve bunu .NET'te de yapmayı düşünmüyoruz. Bana göre gerçekçi bir metrik kullandık ve .NET'in yavaş olduğu ortaya çıktı.
QBziZ

1
Peki, blob tespitinin ne olduğu hakkında küçük bir fikrim var, ama sadece bir zamanlamayı belirtmek hiçbir şey kanıtlamaz. C ++ ile bir tane yazdınız mı? JavaScript'te mi? Ve bunları C # ile karşılaştırıldı? Bunun yanı sıra, damla algılamanın birçok grafik ilkel kullandığını düşünmüyorum. Yanlışsa beni düzeltin, ama sanırım piksel üzerinde işlem yapan istatistiksel algoritmalar.
QBziZ

13

Çöp toplama, Java # 'ın gerçek zamanlı sistemler için KULLANILMAMASININ ana nedenidir.

  1. GC ne zaman olacak?

  2. Ne kadar sürer?

Bu belirleyici değildir.


5
Büyük bir Java hayranı değilim ama Java'nın gerçek zamanlı bir GC kullanamayacağını söyleyen hiçbir şey yok.
Zan Lynx

5
Bakmaya özen gösterirseniz, çok sayıda gerçek zamanlı GC uygulaması vardır. (GC, araştırma kağıtları ile dolup taşan bir alandır )
Arafangion

FWIW, Richard Jones, çöp toplama kitabının diğer şeylerin yanı sıra son teknoloji ürünü gerçek zamanlı GC tasarımlarını kapsayan güncellenmiş bir versiyonunu yayınladı.
Jon Harrop

11
Bu saçma bir argüman, Windows (ve Linux) Gerçek Zamanlı İşletim Sistemleri değil. C ++ kodunuz herhangi bir zamanda 18 ms'lik aralıklarla değiştirilebilir.
Henk Holterman

2
@HenkHolterman Doğru, ancak her zaman montajda bir önyükleyici yazabilir, bunu uygulamanız için bir çekirdek önyüklemesine bağlayabilir ve C ++ uygulamalarınızı doğrudan donanıma (RT btw'de) yürütebilirsiniz. Bunu C # ve C # sadece derlenmiş derleme taklit gördüm ve C # kullanmak için daha az nokta yapmak bir ton C kodu kullanın gördüm herhangi bir çaba yapamazsınız. Tüm bunları okumak biraz komik, çünkü C # .NET çerçevesi olmadan gerçekten işe yaramaz.
zackery.fix

11

C # 'ın performansta C ++ ile karşılaştırılabilir olup olmadığını belirlemek zorunda kaldık ve bunun için bazı test programları yazdım (her iki dil için Visual Studio 2005 kullanarak). Çöp toplama olmadan ve sadece dil dikkate alındığında (çerçeve değil) C #, temel olarak C ++ ile aynı performansa sahiptir. Bellek ayırma, C # 'da C ++' dan çok daha hızlıdır ve veri boyutları önbellek sınırlarının ötesinde artırıldığında C # 'ın determinizmde hafif bir kenarı vardır. Ancak, tüm bunların sonunda ödenmesi gerekiyordu ve çöp toplama nedeniyle C # için deterministik olmayan performans isabetleri şeklinde büyük bir maliyet var.


1
C ++ 'da, farklı ayırma yöntemleri kullanma seçeneğiniz vardır, bu nedenle bellek C #' a nasıl tahsis edildiğine (AOT?) Bağlı olarak, C ++ 'da aynı şekilde (ancak çok daha hızlı) yapılabilir.
zackery.fix

5
@ zackery.fix .NET, yığın ayırmada ilginç bir kenara sahiptir, çünkü yalnızca yeni bir nesne ayırmak için bir işaretçiyi hareket ettirmek zorundadır. Bu sadece sıkıştırıcı çöp toplayıcı nedeniyle mümkündür. Elbette aynı şeyi C ++ 'da yapabilirsiniz, ancak C ++ bunu yapmaz. Aynı argümanı "C # yapabilirdi ama yapmaz, bu yüzden çöp" ve "C ++ yapmaz, ama yapabilirdi, bu yüzden harika" demek nasıl komik? :)
Luaan

9

Her zamanki gibi, uygulamaya bağlıdır. C #'ın muhtemelen önemsiz derecede yavaş olduğu durumlar ve C ++ 'ın 5 veya 10 kat daha hızlı olduğu diğer durumlar, özellikle işlemlerin kolayca SIMD'lendiği durumlarda vardır.


VM'ler için en iyi durum, oluşturulan kodun çalışma zamanı derlemesi olacaktır (örn. Çalışma zamanında okunan normal ifadeyi eşleştirmek için), çünkü statik olarak derlenmiş vanilya C ++ programları yalnızca JIT derleyicisinin yerleşik olmadığı için yorumlamayı kullanabilir.
Jon Harrop

Gelecekten not: .NET, yaygın olarak kullanılmasa da, yaklaşık 2014'ten beri SIMD ve arkadaşları için destek veriyor.
Luaan

9

Sorduğunuz şey olmadığını biliyorum, ancak C # yazmak genellikle C ++ 'dan daha hızlıdır , bu da ticari bir ortamda büyük bir bonus.


2
Çoğu zaman daha hızlı olduğunu söyleyebilirim :)
Tuzak

8

C / C ++, büyük diziler veya diziler üzerinde (her boyutta) ağır döngü / yineleme olan programlarda çok daha iyi performans gösterebilir. C / C ++ 'da grafiklerin genellikle çok daha hızlı olmasının nedeni budur, çünkü ağır dizi işlemleri neredeyse tüm grafik işlemlerinin altındadır. .NET, tüm güvenlik denetimleri nedeniyle dizi indeksleme işlemlerinde kötü bir şekilde yavaştır ve bu özellikle çok boyutlu diziler için geçerlidir (ve evet, dikdörtgen C # dizileri pürüzlü C # dizilerinden bile daha yavaştır).

C / C ++ bonusları, doğrudan işaretçilerle yapışırsanız ve Boost std::vectorve diğer yüksek seviyeli kaplardan ve inlinemümkün olan her küçük işlevden kaçınırsanız en belirgindir . Mümkün olduğunca eski okul dizilerini kullanın. Evet, üst düzey kapsayıcılardan kaçındığınız gibi Java veya C # ile aynı şeyi gerçekleştirmek için daha fazla kod satırına ihtiyacınız olacaktır. Dinamik olarak boyutlandırılmış bir diziye ihtiyacınız varsa, new T[]ilgili bir delete[]ifadeyle eşleştirmeyi (veyastd::unique_ptr) - ekstra hızın fiyatı daha dikkatli kodlamanız gerektiğidir. Ancak karşılığında, hem Java hem de .NET'teki yoğun nesne yönelimli programların yanı sıra büyük çapta yönetilenlerin yürütme süresinin% 20'si veya daha fazlası olabilen yönetilen bellek / çöp toplayıcısının yükünden kurtulursunuz. bellek dizini indeksleme maliyetleri. C ++ uygulamaları, belirli durumlarda bazı şık derleyici anahtarlarından da yararlanabilir.

C, C ++, Java ve C # alanlarında uzman bir programcıyım. Son zamanlarda, son 3 dilde tam olarak aynı algoritmik programı uygulamak için nadir bir fırsat vardı. Programda çok sayıda matematik ve çok boyutlu dizi işlemleri vardı. Bunu 3 dilde de büyük ölçüde optimize ettim. Sonuçlar normalde daha az titiz karşılaştırmalarda gördüğüm tipikti: Java, C # 'dan yaklaşık 1.3x daha hızlıydı (çoğu JVM, CLR'den daha optimize edildi) ve C ++ ham işaretçi sürümü, C #' dan yaklaşık 2.1x daha hızlı geldi. C # programının sadece güvenli kod kullandığını unutmayın; bence C ++ 'da kullanmadan önceunsafe anahtar kelimeyi .

Herkes C # karşı bir şey var düşünüyorum, ben C # muhtemelen benim en sevdiğim dil olduğunu söyleyerek kapanacaktır. Şimdiye kadar karşılaştığım en mantıklı, sezgisel ve hızlı geliştirme dilidir. Tüm prototiplememi C # ile yapıyorum. C # dilinin Java üzerinde birçok küçük, ince avantajı vardır (evet, Microsoft'un oyuna geç girip Java'yı kopyalayarak Java eksikliklerinin çoğunu düzeltme şansı olduğunu biliyorum). CalendarHerkes Java sınıfına kadeh kaldırmak ? Microsoft, CLR ve .NET JITter'ı optimize etmek için gerçekten çaba harcarsa, C # ciddi şekilde ele geçirebilir. Dürüst olmak gerekirse, henüz C # dilinde çok şey yaptılar, neden ağır vuruş derleyici optimizasyonları ile takip etmiyorlar? Belki hepimiz yalvarırsak.


3
"Sadece new T[]karşılık gelen bir ile eşleştirmek için hatırlamak gerekir delete[]" - Hayır. Bunu senin std::unique_ptriçin yapacak.
emlai

grafiklerde bir şey yazdığınızdan dolayı neden c # 'da güvenli kod yazıyorsunuz, güvensiz kod kullanmayı ve tekrar karşılaştırmayı düşündünüz mü?
user3800527

7

> Duyduğumdan ...

Zorluğunuz, duyduklarınızın güvenilir olup olmadığına karar vermede görünüyor ve bu zorluk, bu sitedeki yanıtları değerlendirmeye çalıştığınızda tekrarlanacaktır.

İnsanların burada söylediklerinin, ilk duyduğunuzdan daha az veya daha güvenilir olup olmadığına nasıl karar vereceksiniz?

Bunun bir yolu kanıt istemektir .

Birisi "C # 'ın C ++' dan daha hızlı olduğunu kanıtladığı bazı alanlar var" iddiasında onlara neden söylediklerini sorun, size ölçümleri göstermelerini isteyin, size programları göstermelerini isteyin. Bazen bir hata yapmış olabilirler. Bazen gerçek olduklarını gösterebilecekleri bir şeyi paylaşmak yerine sadece bir fikir ifade ettiklerini öğreneceksiniz.

Çoğu zaman bilgi ve fikir insanların iddia ettikleri şeylerle karıştırılır ve hangisinin hangisi olduğunu bulmaya çalışmanız gerekir. Örneğin, bu forumdaki yanıtlardan:

  • " Http://shootout.alioth.debian.org/ adresindeki ölçütleri büyük ölçüde şüphecilikle alın, çünkü bunlar büyük olasılıkla kodunuza hiç benzemeyen aritmetik kodu test eder."

    Kendinize "bu büyük ölçüde test aritmetik kodunun" ne anlama geldiğini gerçekten anlayıp anlamadığınızı sorun ve daha sonra kendinize yazarın iddiasının doğru olduğunu gerçekten gösterip göstermediğini kendinize sorun.

  • "Bu oldukça işe yaramaz bir test, çünkü gerçekten bireysel programların ne kadar iyi optimize edildiğine bağlı; Bunlardan bazılarını 4-6 kat veya daha fazla hızlandırmayı başardım, böylece optimize edilmemiş programlar arasındaki karşılaştırmanın oldukça saçma."

    Kendinize yazarın size "bazılarını 4-6 kez veya daha fazla hızlandırmayı başardığını" gösterip göstermediğini sorun - bunu yapmak kolay bir iddia!


Sizinle daha fazla anlaşamadım ve bu forumda sorduğumun nedeni ... Sonuçta, cevapların bir yerde olması gerekiyor, değil mi? :)
Tuzak

1
Evet. Cevap, duruma bağlı.".
user49117

6

'Sınırsız paralel' problemler için, C ++ üzerinde Intel TBB ve OpenMP kullanırken C # ve TPL ile yapılan benzer (saf matematik) problemlere kıyasla kabaca 10 kat performans artışı gözlemledim. SIMD, C #'ın rekabet edemediği bir alandır, ancak aynı zamanda TPL'nin büyük bir yükü olduğu izlenimini edindim.

Bununla birlikte, sadece çoklu iş parçacığı ve hızlı sonuçlar alabileceğimi bildiğim performans açısından kritik görevler için C ++ kullanıyorum. Diğer her şey için, C # (ve bazen F #) gayet iyi.


5

Gerçek kesin cevaplar olmadan son derece belirsiz bir soru.

Örneğin; Performans kesinlikle çok daha iyi olduğu için C ++ 'da oluşturulan 3D oyunları oynamayı tercih ederim. (Ve XNA, vb. Biliyorum, ama gerçek olana yakın bir şekilde gelmez).

Öte yandan, daha önce de belirtildiği gibi; istediğiniz şeyi hızlı bir şekilde yapmanıza izin veren bir dilde geliştirmeniz ve ardından gerekirse optimize etmeniz gerekir.


4
Birkaç örnek verebilir misiniz? C # 'da yavaş bulduğunuz oyunlar
Karl

1
Kurulumla birlikte gelen örnek uygulamalar bile yavaşladı.
David The Man

9
Çöp toplayıcı, C # ile oyun yapmak için büyük bir sorumluluktur, çünkü herhangi bir zamanda başlayabilir ve büyük duraklamalara neden olabilir. Açık bellek yönetimi, oyun geliştirme için daha kolay olur.
postfuturist

3
Modern oyunların çoğu GPU ile sınırlıdır. Bu tür oyunlar için mantığın (CPU'da yürütülen)% 10 daha yavaş olması önemli değildir, yine de CPU ile değil, GPU ile sınırlıdır. Çöp toplayıcı gerçek bir sorundur ve bellek atamaları iyi ayarlanmamışsa rasgele kısa donmalara neden olur.
Michael Entin

2
@postfuturist: PC'de bu doğru değil; çöp toplayıcı içeri girmek ve dışarı çıkmak için çok iyi bir iş çıkarıyor. Ancak, XBox 360 ve Zune / Windows-7-Phone'da çöp toplayıcı neredeyse PC'de olduğu kadar akıllı değildir ; Ben de hiç yazmadım, ama bana çöp toplayıcısını söyleyen insanlar çok büyük bir problem.
BlueRaja - Danny Pflughoeft

5

.NET dilleri C ++ kodu kadar hızlı veya daha hızlı olabilir, ancak C ++ kodunun .NET çalışma zamanının GC için duraklatması gerektiği için daha sabit bir verimi olacaktır. çok akıllı olsa bile .

Bu nedenle, herhangi bir duraklama olmadan hızlı bir şekilde sürekli çalışması gereken bir kodunuz varsa, .NET , çalışma zamanı GC'sine çok dikkat etseniz bile , bir noktada gecikme getirecektir .


6
-1: Bu aslında bir efsane. Birincisi, idiyomatik C ++ 'ın gecikmesi aslında korkunçtur ve .NET'ten çok daha kötüdür, çünkü RAII büyük veri yapıları kapsam dışında kaldığında yıkıcıların çığlarına neden olurken, modern GC'ler artımlı ve .NET'ler bile eşzamanlıdır. İkincisi, aslında GC'deki duraklamaları ayırmadan tamamen kaldırabilirsiniz.
Jon Harrop

2
Bunu yaparsanız, yöntemlerin çoğu geçici nesneler oluşturduğundan BCL'yi kullanmayı bırakmanız gerekir.
Florian Doyon

5
Bu oldukça doğrudur, .net 4'e kadar GC artımlı hale getirilmedi. GC için her seferinde saniye duraklatan büyük bir C # uygulamamız var. Performans açısından kritik uygulamalar için bu bir katildir.
Justin

5
Donanımı zorlayan programların C ++ kullanma eğiliminde olmasının bir nedeni vardır. İhtiyacınız olduğunda daha hassas ayarlanmış kontrole sahipsiniz. Performans yalnızca sistemi iterken önemlidir, aksi takdirde size zaman kazandırmak için C # veya Java kullanın.
VoronoiPotato

4
önbellek davranışını yönetemezseniz, optimize edilmiş c ++ kodunu yenemezsiniz. L1'den ana belleğe yapılan bir önbellek kaçışı, işleminizi 100 kez yavaşlatabilir.
DAG

4

Teorik olarak, uzun süren sunucu tipi uygulama için, JIT-derlenmiş bir dil, yerel olarak derlenmiş bir karşıttan çok daha hızlı olabilir . JIT derlenmiş dili genellikle ilk olarak oldukça düşük seviyeli bir ara dile derlendiğinden, derleme zamanında bir çok üst düzey optimizasyon yapabilirsiniz. En büyük avantajı, JIT'in uygulamanın nasıl kullanıldığına dair daha fazla veri aldığı için kod bölümlerini anında yeniden derlemeye devam etmesidir. Şube tahmininin mümkün olduğunca sık başarılı olmasını sağlamak için en yaygın kod yollarını düzenleyebilir. Her ikisini de önbellekte tutmak için genellikle birlikte çağrılan ayrı kod bloklarını yeniden düzenleyebilir. İç döngüleri optimize etmek için daha fazla çaba harcayabilir.

Bunun .NET veya JRE'lerden herhangi biri tarafından yapıldığından şüpheliyim, ancak üniversitede olduğumda araştırılıyordu, bu yüzden bu tür şeylerin kısa sürede gerçek dünyaya girebileceğini düşünmek mantıklı değil. .


4

Yoğun bellek erişimi gerektiren uygulamalar, ör. görüntü işleme genellikle yönetilmeyen bir ortamda (C ++) yönetilen (C #) daha iyi kapalı yazılır. İşaretçi aritmetikleri ile optimize edilmiş iç döngüler, C ++ 'da kontrolü çok daha kolaydır. C # 'da, aynı performansa yaklaşmak için güvenli olmayan koda başvurmanız gerekebilir.


4

vectorC ++ ve C # eşdeğeri - Listve basit 2d dizileri test ettik .

Visual C # / C ++ 2010 Express sürümlerini kullanıyorum. Her iki proje de basit konsol uygulamaları, bunları standart (özel ayar yok) sürümü ve hata ayıklama modunda test ettim. C # listeleri benim pc daha hızlı çalışır, dizi başlatma da C # daha hızlı, matematik işlemleri daha yavaş.

Intel Core2Duo P8600@2.4GHz, C # - .NET 4.0 kullanıyorum.

Vektör uygulama C # listesinden farklı olduğunu biliyorum, ama ben sadece nesneleri (ve dizin erişimci kullanabilmek) saklamak için kullanacağım koleksiyonları test etmek istedim.

Tabii ki hafızayı temizlemeniz gerekiyor (her kullanım için diyelim new), ama kodu basit tutmak istedim.

C ++ vektör testi :

static void TestVector()
{
    clock_t start,finish;
    start=clock();
    vector<vector<double>> myList=vector<vector<double>>();
    int i=0;
    for( i=0; i<500; i++)
    {
        myList.push_back(vector<double>());
        for(int j=0;j<50000;j++)
            myList[i].push_back(j+i);
    }
    finish=clock();
    cout<<(finish-start)<<endl;
    cout<<(double(finish - start)/CLOCKS_PER_SEC);
}

C # liste testi:

private static void TestVector()
{

    DateTime t1 = System.DateTime.Now;
    List<List<double>> myList = new List<List<double>>();
    int i = 0;
    for (i = 0; i < 500; i++)
    {
        myList.Add(new List<double>());
        for (int j = 0; j < 50000; j++)
            myList[i].Add(j *i);
    }
    DateTime t2 = System.DateTime.Now;
    Console.WriteLine(t2 - t1);
}

C ++ - dizi:

static void TestArray()
{
    cout << "Normal array test:" << endl;
    const int rows = 5000;
    const int columns = 9000;
    clock_t start, finish;

    start = clock();
    double** arr = new double*[rows];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    finish = clock();

    cout << (finish - start) << endl;

    start = clock();
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    finish = clock();

    cout << (finish - start) << endl;
}

C # - dizi:

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

}

Zaman: (Serbest Bırak / Hata Ayıkla)

C ++

  • 600/606 ms dizi başlangıcı,
  • 200/270 msn dizi dolgusu,
  • 1sn / 13sn vektör başlatma ve doldurma.

(Evet, 13 saniye, her zaman hata ayıklama modundaki listeler / vektörlerle ilgili sorun yaşıyorum.)

C #:

  • 20/20 ms dizi başlatma,
  • 403/440 msn dizi dolgusu,
  • 710/742 msn list init & fill.

1
İndeks erişimciyi std :: listesinde görmek isterim. Her neyse, liste, bırakma modu ile 37 saniye sürer. Hata ayıklamadan bırakma: 3s listesi, 0,3 s vektör. Muhtemelen kayıttan çıkarılma sorunu veya sth. Örnek: nopaste.pl/12fb
Wiory

2
Daha kesin ölçümler için System.DateTime.Now, kronometre sınıfını kullanmamalısınız.
Sam

4
C ++ 'da vektör için bu kadar yavaş doldurma süreleri alma nedeninizin bir kısmı push_back kullanmanızdır. Bu, çok sayıda yazıda at yöntemini veya işleci [] kullanmaktan daha yavaş olduğu gösterilmiştir. Bu yöntemlerden herhangi birini kullanmak için yeniden boyutlandırma veya rezerv yöntemini kullanmanız gerekir. Ayrıca, başlatma işleminizin c ++ vektör durumu için bu kadar uzun sürmesinin nedeni, bir kopya veya atama operatörünü (bu durumda hangisi olduğundan emin değilsiniz) c ++ vektörünüzü başlatmaya zorlamanızdır. C ++ dizisi için 5001 yerine 2 yeni çağrı kullanan ve aynı zamanda daha hızlı yinelenen bir algoritma vardır.
Zachary Kraus

5
Bence uygun bir şekilde c ++ yapmadınız. Sadece bir bakış ve çok fazla sorun bulundu. Örn. <Vektör <çift>> myList = vektör <vektör <çift>> ()
DAG

2
Vay. Listelerin yeniden boyutlandırılabilir dizilerle karşılaştırılmasından hangi sonuçların alınabileceğinden emin değilim, ancak böyle vektörleri kullanacaksanız, arkadaşım, rezerv (), reserve () hakkında bilgi edinmek istersiniz.
U007D

3

Buna bağlı. Bayt kodu makine koduna çevrilirse (sadece JIT'e değil) (yani programı çalıştırırsanız) ve programınız çok fazla tahsis / anlaşma kullanırsa, GC algoritmasının sadece bir geçişe (teorik olarak) ihtiyaç duyması daha hızlı olabilir. bir kez tüm bellek boyunca, ancak normal malloc / realloc / free C / C ++ çağrıları her çağrıda bir ek yüke neden olur (çağrı ek yükü, veri yapısı ek yükü, önbellek özlüyor;)).

Bu nedenle teorik olarak mümkündür (diğer GC dilleri için de).

Çoğu uygulama için C # ile meta programlamayı kullanamamanın aşırı dezavantajını görmüyorum , çünkü çoğu programcı yine de kullanmıyor.

Bir diğer büyük avantaj, SQL'in, LINQ "uzantısı" gibi, derleyicinin veritabanlarına çağrıları optimize etmesi için fırsatlar sağlamasıdır (başka bir deyişle, derleyici, tüm LINQ'yu çağrılan işlevlerin satır içi veya kullanımınız için optimize edilmiştir, ancak burada tahmin ediyorum).


1
Herhangi bir uygun C ++ geliştiricisi açıkladığınız sorunlarda çalışmaz. Programlarında sınıfları tokatlayıp C ++ olarak adlandırmaya karar veren sadece kötü C programcılarının bu sorunları var.
Daha

1
tanrıların aşkı için bu 8 yaşında, OMFGz
Quonux

daha iyi bir güncel cevap vermek için çekinmeyin
Quonux

2

Ben hızlı çalışan C # yazılmış uygulamalar yanı sıra hızlı çalışan daha iyi C + + yazılı uygulamalar vardır (iyi C ++ sadece daha eski ... ve UNIX de almak ...)
- soru gerçekten - bu şey nedir, kullanıcılar ve geliştiriciler hakkında şikayet ...
Eh, IMHO, C # durumunda çok rahat kullanıcı arayüzü, çok güzel kütüphaneler hiyerarşisi ve CLI'nin tüm arayüz sistemi var. C ++ durumunda, şablonlar, ATL, COM, MFC ve OpenGL, DirectX ve benzeri gibi zaten yazılmış ve çalışan kodların tüm shebang var ... Geliştiriciler C # durumunda belirsiz çağrılar GC çağrıları şikayet ediyor (program hızlı çalışır ve bir saniyede - patlama! sıkışmış).
C # çok basit ve hızlı kod yazmak için (bu da hata şansını artırmak unutmayın. C ++ durumunda, geliştiriciler bellek sızıntıları şikayet - anlamına gelir ezmeler, DLL arasında çağrıları, yanı sıra "DLL cehennem" - ile sorun destekleme ve kütüphaneleri yenileriyle değiştirme ...
Bence programlama dilinde daha fazla beceriye sahip olursanız, yazılımınızın kalitesi (ve hızı) daha fazla karakterize edilir.


2

Bunu şöyle söylerdim: daha hızlı kod yazan programcılar, mevcut makinelerin hızlı gitmesini sağlayan şeylerden daha bilgili olanlar ve bu arada onlar da hassas düşük seviye ve deterministik sağlayan uygun bir araç kullanan kişilerdir. optimizasyon teknikleri. Bu nedenlerle, bu insanlar C # yerine C / C ++ kullanan kişilerdir. Bunu bir gerçek olarak söyleyebildiğim kadar ileri giderdim.


Notch, manipüle ettiği veri miktarı göz önüne alındığında minecraft'ı oldukça hızlı kodladı. Ayrıca, nispeten kısa bir sürede çoğunlukla tek başına kodladı, bu C ++ 'da neredeyse imkansız olurdu. Ancak optimizasyon teknikleri ile kabul ediyorum - eğer kodunuzu iki kat daha hızlı çalışır şekilde harcamak için ekstra 10x dev zamanınız varsa, muhtemelen buna değer.
Bill K

2

Yanılmıyorsam, C # şablonları çalışma zamanında belirlenir. Bu, C ++ zaman şablonlarını derlemekten daha yavaş olmalıdır.

Ve diğer pek çok kişi tarafından bahsedilen diğer derleme zamanı optimizasyonlarını ve ayrıca daha fazla hız anlamına gelen güvenlik eksikliğini aldığınızda ...

C ++ ham hız ve minimum bellek tüketimi açısından bariz bir seçim olduğunu söyleyebilirim. Ancak bu aynı zamanda kodu geliştirmek ve bellek sızdırmadığından veya boş işaretçi istisnalarına neden olmadığından emin olmak için daha fazla zaman anlamına gelir.

Karar:

  • C #: Daha hızlı geliştirme, daha yavaş çalışma

  • C ++: Yavaş geliştirme, daha hızlı çalışma.


1

Bu gerçekten kodunuzda neyi başarmaya çalıştığınıza bağlıdır. Ben VB.NET, C # ve yönetilen C ++ arasında herhangi bir performans farkı olduğunu sadece kentsel efsane şeyler duydum. Ancak, en azından dize karşılaştırmalarında, yönetilen C ++ 'ın pantolonları C #' dan, bu da VB.NET 'ten yener.

Hiçbir şekilde diller arasındaki algoritmik karmaşıklıkta kapsamlı karşılaştırmalar yapmadım. Ayrıca sadece her dilde varsayılan ayarları kullanıyorum. VB.NET değişkenleri vb bildirimi gerektiren ayarları kullanıyorum. İşte yönetilen C ++ için kullanıyorum kodu: (Gördüğünüz gibi, bu kod oldukça basit). Ben .NET 4.6.2 ile Visual Studio 2013 diğer dillerde aynı çalışıyorum.

#include "stdafx.h"

using namespace System;
using namespace System::Diagnostics;

bool EqualMe(String^ first, String^ second)
{
    return first->Equals(second);
}
int main(array<String ^> ^args)
{
    Stopwatch^ sw = gcnew Stopwatch();
    sw->Start();
    for (int i = 0; i < 100000; i++)
    {
        EqualMe(L"one", L"two");
    }
    sw->Stop();
    Console::WriteLine(sw->ElapsedTicks);
    return 0;
}

1

Performans açısından C # ve C ++ arasında bazı büyük farklılıklar vardır:

  • C # GC / yığın tabanlıdır. Bellek erişiminin yerleşimsizliği olarak ayırma ve GC'nin kendisi ek yüktür
  • C ++ optimizer yıllar içinde çok iyi oldu. JIT derleyicileri sadece sınırlı derleme süresine sahip oldukları ve global kapsamı görmedikleri için aynı seviyeye ulaşamazlar

Ayrıca programcı yeterliliği de rol oynamaktadır. Kötü C ++ kodu gördüm nerede sınıfları her yerde bağımsız değişken olarak değer tarafından geçti. Ne yaptığınızı bilmiyorsanız C ++ 'da performansı daha da kötüleştirebilirsiniz.


0

> Sonuçta, cevaplar bir yerde olmalı, değil mi? :)

Hmm, hayır.

Birkaç cevabın belirttiği gibi , soru cevapları değil yanıt olarak soruları davet eden şekillerde yetersiz belirtilmiştir . Sadece bir yoldan gitmek gerekirse:

Peki hangi programlar? Hangi makine? Hangi işletim sistemi? Hangi veri seti?


Tamamen katılıyorum. İnsanların genel bir soru sorduklarında neden kesin bir cevap beklediklerini merak ediyorum (% 63.5). Bu tür bir sorunun genel bir cevabı olmadığını sanmıyorum.
bana Steve

@callmesteve: Ne demek istediğinizi biliyorum, ama son cümleniz herhangi bir programcıya tebeşir tahtası üzerinde çivi gibi gelmelidir.
Wouter van Nifterick

1
Bu soruyu cevaplıyor gibi görünmüyor ve daha çok bir yorum ya da rant olarak okuyor.
Tas

-13

Bundan esinlenerek, programların çoğunda ihtiyaç duyulan ortak eğitimin yüzde 60'ı ile hızlı bir test yaptım.

İşte C # kodu:

for (int i=0; i<1000; i++)
{
    StreamReader str = new StreamReader("file.csv");
    StreamWriter stw = new StreamWriter("examp.csv");
    string strL = "";
    while((strL = str.ReadLine()) != null)
    {
        ArrayList al = new ArrayList();
        string[] strline = strL.Split(',');
        al.AddRange(strline);
        foreach(string str1 in strline)
        {
            stw.Write(str1 + ",");
        }
        stw.Write("\n");
    }
    str.Close();
    stw.Close();
}

Dize dizisi ve arraylist bu talimatları içermek için bilerek kullanılır.

İşte c ++ kodu:

for (int i = 0; i<1000; i++)
{
    std::fstream file("file.csv", ios::in);
    if (!file.is_open())
    {
        std::cout << "File not found!\n";
        return 1;
    }

    ofstream myfile;
    myfile.open ("example.txt");
    std::string csvLine;

    while (std::getline(file, csvLine))
    {
        std::istringstream csvStream(csvLine);
        std::vector csvColumn;
        std::string csvElement;

        while( std::getline(csvStream, csvElement, ‘,’) )
        {
            csvColumn.push_back(csvElement);
        }

        for (std::vector::iterator j = csvColumn.begin(); j != csvColumn.end(); ++j)
        {
            myfile << *j << ", ";
        }

        csvColumn.clear();
        csvElement.clear();
        csvLine.clear();
        myfile << "\n";
    }
    myfile.close();
    file.close();
}

Kullandığım girdi dosyası boyutu 40 KB'dı.

Ve işte sonuç -

  • C ++ kodu 9 saniye içinde çalıştı.
  • C # kodu: 4 saniye !!!

Oh, ama bu Linux'taydı ... C # Mono üzerinde çalışıyor ... Ve C ++ ile g ++.

Tamam, Windows'da aldığım şey bu - Visual Studio 2003 :

  • C # kodu 9 saniye içinde çalıştı.
  • C ++ kodu - korkunç 370 saniye !!!

7
Orada farklı veri yapıları ve kütüphane kodu kullanıyorsunuz, ancak "370 saniye" korkunç bir şey olduğunu gösteriyor - herhangi bir olasılıkla hata ayıklayıcıda çalıştırmıyorsunuz? Kullandığınız CSV kütüphanesinin performansının, kullandığınız dilin performansından daha ilginç olduğundan şüpheleniyorum. Bu bağlamda bir vektörün kullanımını ve hangi optimizasyonları kullandığınızı sorgularım. Ayrıca, iostreams'in (özellikle "myfile << * j <<", ";"), en azından bazı yaygın uygulamalar için, dosyaya yazmanın diğer yöntemlerinden çok daha yavaş olduğu bilinmektedir.
Arafangion

6
Son olarak, C ++ sürümünde daha fazla iş yapıyorsunuz. (Neden csvColumn, csvElement ve csvLines'i temizliyorsunuz?)
Arafangion

2
While döngüsünün her yinelemesi std :: istream ve std :: vector ve std :: string'lerini imha edecek ve yeniden oluşturacaktır. While gövdesi her yinelemeden kapsam dışına çıkarken, while kapsamındaki tüm bu değişkenler her yinelemeyi tahrip edecek ve inşa edecektir.
doug65536

1
c ++ kodunuzu okuduğunuzdan bir dosyadan başka bir dosyaya kopyalamaya çalışıyorsunuz. Dosya akışları, dizeler, vektörler ve dize akışları arasındaki karmaşık etkileşimleri kullanmak yerine, giriş dosyası akışını çıktı dosyası akışına kopyalamış olabilirsiniz. Bu çok zaman ve hafıza tasarrufu sağlayacaktı.
Zachary Kraus

2
hız testleri yapmak, hafızadaki şeyleri test etmek, en son SSD'lerde ve performans uygulamanıza özel olarak test edilmediğiniz sürece, disk IO'ya ulaşmayın. Bilgisayarlar klavyeye dokunmasanız bile sürekli diske yazar.
user3800527
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.