C neden bu kadar hızlı ve neden diğer diller hızlı veya daha hızlı değil? [kapalı]


208

StackOverflow podcast'ini dinlerken, jab, "gerçek programcıların" C ile yazdığını ve C'nin "makineye yakın" olduğu için çok daha hızlı olduğunu gösterir. Eski bir iddiayı başka bir gönderi için terk edersek, C'nin diğer dillerden daha hızlı olmasını sağlayan özel olan nedir? Ya da başka bir deyişle: diğer dilleri C kadar hızlı çalıştıran ikililere derlemeyi engelleyecek ne var?


6
Bunun hakkında konuşulan belirli bir şovu listeleyebilir misiniz? Bunu duymak isterim.
Giovanni Galbo

2
Bu sorunun ne kadar kötü bir şekilde cevaplandığına gerçekten şaşırdım (çoğu cevap derlenmiş ve yorumlanmış diller arasındaki temel farkları görmezden gelir, JIT yada yada yada hakkında bilgi sahibi olurum) ve kaç kişinin kendi favori dillerini 'savunmak' (FORTRAN çocuğun ihtiyaçları) bir hap almak için).
Tim Ring

Montaj dilini unutmayın. Hiçbir şey, montaja monte edilmiş eski modellerden daha hızlı veya daha kompakt olamaz. Montaj neredeyse tamamen ikiliktir, bu yüzden en hızlı dilde önyargısızdır.
KKZiomek

3
C en hızlısıdır çünkü ışık ve görelilik hızıdır?
Taraviya ile tanışın

C'nin en hızlı program dili olması elbette yanlıştır. Hiçbir program dili FORTH hızına yaklaşmaz. FORTH nükleer bombaları tetiklemek için kullanılır, en çok uydunun program dilidir, Uluslararası Uzay İstasyonunda ve ayrıca CERN'de ve ITER'de ana program dili. Microsoft C (farklı Sürümler) ve FORTH arasındaki hızı karşılaştırıyordum.
YAWN

Yanıtlar:


200

C ile ilgili çok özel bir şey yok. Bu hızlı olmasının nedenlerinden biri.

Çöp toplama , dinamik yazma ve programcıların program yazmasını kolaylaştıran diğer tesislere destek veren daha yeni diller .

Yakalama, uygulamanın performansını düşürecek ek işlem yükü var. C, bunlardan hiçbirine sahip değildir, bu da ek yük olmadığı anlamına gelir, ancak bu, programcının bellek sızıntılarını önlemek için bellek ayırabilmesi ve serbest bırakabilmesi gerektiği ve değişkenlerin statik yazımıyla uğraşması gerektiği anlamına gelir .

Bununla birlikte, Java ( Java Sanal Makinesi ile ) ve .NET (Ortak Dil Çalışma Zamanı ile) gibi birçok dil ve platform, yerel makine kodu üreten tam zamanlı derleme gibi avantajlarla yıllar boyunca performansı artırmıştır . daha yüksek performans elde etmek için bayt kodu.


3
çöp toplama, manuel bellek yönetiminden daha hızlı olabilir (kısa süreli programlar ve / veya bol miktarda bellek için). GC basit ve hızlı tahsis sağlar ve program şeyleri dağıtmak için zaman harcamaz.
Kornel

2
C programları genellikle belleği gerektiğinde tahsis eder ve yeniden konumlandırır. Bu verimsiz. İyi bir sanal makine büyük parçalar halinde dağıtılacak ve yeniden dağıtılacak ve birçok durumda performansta büyük kazanımlar sağlayacaktır.
skaffman

60
Bir C programının "katı" olmasının yanı sıra aynı yığın tahsisi ve çöp toplama işlemini gerçekleştirmesini engelleyen hiçbir şey yoktur.
ephemient

Çok iyi söylendi, ancak Rob Allen, C'nin Java veya .NET'ten daha az soyutlama sağlayarak daha az çeviri sağladığını söyledi (bu da sizin gibi tam zamanında derleme nedeniyle bu gün daha az doğrudur)
Gab Royer

5
PorneL, manuel yönetim ve mantıklı tahsisler doğru kullanıldığında her zaman tüm GC sistemlerinden daha iyi performans gösterecek ve çok dikkat gösterilecek, kullanım alışkanlıklarınız hakkında mutlak bilgiye sahip olacaksınız, GC yapmıyor ve GC sistemleri ek yük
getiriyor

89

C tasarımcılarının yaptığı bir ticaret var. Yani hızı güvenliğin üstüne koyma kararı aldılar. C olmayacak

  • Dizi dizini sınırlarını kontrol edin
  • Başlatılmamış değişken değerlerini kontrol edin
  • Bellek sızıntılarını kontrol edin
  • Boş işaretçi dereference'ı kontrol edin

Bir dizine indekslediğinizde, Java'da sanal makinede bazı yöntem çağrısı, bağlı kontrol ve diğer akıl sağlığı kontrolleri gerekir. Bu geçerli ve kesinlikle iyidir , çünkü zamanı geldiğinde güvenlik ekler. Ancak C'de, oldukça önemsiz şeyler bile güvenlik altına alınmaz. Örneğin, C, kopyalanacak bölgelerin çakışıp çakışmadığını kontrol etmek için memcpy gerektirmez. O var değil büyük bir iş uygulaması programlamak için bir dil olarak tasarlanmıştır.

Ancak bu tasarım kararları C dilinde hata değildir . Derleyiciler ve kütüphane yazarlarının bilgisayardan her türlü performansı almasına izin verdiği için tasarım gereğidir. İşte C Rationale belgesinin bunu nasıl açıkladığı: C'nin ruhu :

C kodu taşınabilir olmayabilir. Programcılara gerçekten taşınabilir programlar yazma fırsatı vermeye çalışsa da, Komite programcıları portatif olarak yazmaya zorlamak istemedi, C'yi `` yüksek düzeyli bir montajcı '' olarak kullanmayı engelledi: makineye özgü yazma yeteneği kod C'nin güçlü yönlerinden biridir.

C'nin ruhunu koruyun Komite , C'nin geleneksel ruhunu korumak için önemli bir amaç olarak tutuldu. C ruhunun birçok yönü vardır, ancak öz, C dilinin dayandığı temel ilkelerin topluluk hissidir. C ruhunun bazı yönleri aşağıdaki ifadelerle özetlenebilir

  • Programcıya güvenin.
  • Programcının yapılması gerekeni yapmasını engellemeyin.
  • Dili küçük ve basit tutun.
  • Bir işlem yapmanın yalnızca bir yolunu belirtin.
  • Taşınabilir olması garanti edilmese bile hızlı yapın.

Son atasözünün biraz açıklanması gerekiyor. Etkili kod üretme potansiyeli C'nin en önemli güçlerinden biridir. Çok basit bir işlem gibi görünen bir kod patlamasının gerçekleşmemesini sağlamak için, birçok işlem hedef makinenin donanımının bunu yapmak yerine nasıl yaptığı olarak tanımlanır. genel bir soyut kural. Makinenin yaptığı şeyle yaşama istekliliğinin bir örneği, ifadelerde kullanılmak üzere char nesnelerinin genişlemesini yöneten kurallarda görülebilir: char nesnelerinin değerlerinin imzalı veya imzasız miktarlara genişleyip genişlemediği tipik olarak hangi bayt işleminin daha fazla olduğuna bağlıdır hedef makinede verimli.


51
C şiddetle çökmesini null işaretçi deref olup olmadığını kontrol eder :-). Ayrıca zaman zaman yığın karelerinizi ve verilerinizi sıkıştırarak aralık dışı dizi dizinlerini ve başlatılmamış değişkenleri de denetler. Ne yazık ki çalışma zamanında bunları kontrol eder.
paxdiablo

18
C'nin güvenli olmadığını söyleyemem, kulağa ima ettiğiniz gibi geliyor. Aptal olmadığınızı varsayar. Eğer bir silahı aşağı indirip kendinizi ayağınıza vurursanız, C mutlu bir şekilde mecbur kalır ve bunu yapmanıza izin verir, çünkü olduğundan daha akıllı olduğunuzu varsayar. Bu mutlaka kötü bir şey değildir.
Bob Somers

19
@Bob: Kesinlikle. C demek güvenli değildir çünkü tehlikeli şeyler yapmanıza izin verir, bir arabanın güvenli olmadığını söylemek gibidir, çünkü bir uçurumdan gitmenize izin verir. C, sürüş yapan kişi kadar güvenlidir (ancak orada birçok güvensiz sürücü vardır).
Robert Gamble

5
Bob, arabellek taşması gibi böcekler yapmak aptal olduğun anlamına gelmiyor. Bu sadece hala insan olduğun anlamına geliyor. C ve C ++ kötü olmadığını (çok onlar gibi) fark ediyorum .
Johannes Schaub - litb

4
@ JohannesSchaub-litb C büyük ölçekli uygulama programlama için mükemmeldir. Eğer biri merhaba bir dünyadan daha büyük projeler yapmak zor bulursa, sorun dil ile değil programcı ile ...

75

C'de 0.05 saniyede çalışan bir şey oluşturmak için bir ay geçirdiyseniz ve aynı şeyi Java'da yazarak bir gün geçiririm ve 0.10 saniyede çalışırsa, C gerçekten daha hızlı mı?

Ancak sorunuzu cevaplamak için, iyi yazılmış C kodu diğer dillerde iyi yazılmış koddan daha hızlı çalışacaktır çünkü C kodu "iyi" yazmanın bir kısmı, makine düzeyinde manuel optimizasyonlar yapmayı içerir.

Derleyiciler gerçekten çok akıllı olsa da, henüz elle masaj algoritmaları ile rekabet eden ("eller" in iyi bir C programcısına .

Düzenle:

"C yazıyorum ve optimizasyonları düşünmüyorum" satırında birçok yorum var.

Ancak bu gönderiden belirli bir örnek almak için :

Delphi'de şunu yazabilirim:

function RemoveAllAFromB(a, b: string): string;
var
  before, after :string;
begin
  Result := b;
  if 0 < Pos(a,b) then begin
    before := Copy(b,1,Pos(a,b)-Length(a));
    after := Copy(b,Pos(a,b)+Length(a),Length(b));
    Result := before + after;
    Result := RemoveAllAFromB(a,Result);  //recursive
  end;
end;

ve CI'de şunu yazın:

char *s1, *s2, *result; /* original strings and the result string */
int len1, len2; /* lengths of the strings */
for (i = 0; i < len1; i++) {
   for (j = 0; j < len2; j++) {
     if (s1[i] == s2[j]) {
       break;
     }
   }
   if (j == len2) {  /* s1[i] is not found in s2 */
     *result = s1[i]; 
     result++; /* assuming your result array is long enough */
   }
}

Ancak C sürümünde kaç optimizasyon var? Delphi versiyonunda aklıma gelmediğim uygulama hakkında birçok karar veriyoruz. Bir dize nasıl uygulanır? Delphi'de görmüyorum. C olarak, karakter olarak adlandırdığımız bir dizi ASCII tamsayı için bir işaretçi olacağına karar verdim. C'de karakter varlığını birer birer test ediyoruz. Delphi'de Pos kullanıyorum.

Ve bu sadece küçük bir örnek. Büyük bir programda, C programcısı bu tür düşük seviyeli kararları her birkaç kod satırında vermek zorundadır. El işi, el için optimize edilmiş bir yürütülebilir dosya ekler.


45
Adil olmak gerekirse, C'de bir ay sürecek çok fazla bir şey yok, Java'da sadece bir gün sürecek ve bu işlemin gerçekleştirilmesi sadece 0.05 saniye sürecek (yani küçük program).
dreamlax

12
Yıllardır C'de programladım ve neredeyse hiç ima ettiğiniz optimizasyon türlerini yapmak zorunda kalmadım. C'ye (çoğunlukla Perl'den) bir dizi program taşıdım ve genellikle 10x artı hız artışı ve elle kodlanmış optimizasyonlar olmadan bellek kullanımında önemli bir azalma görüyorum.
Robert Gamble

1
Tabii ki mevcut tesislerin eksikliği nedeniyle C'de programlanması oldukça uzun sürebilecek bazı şeyler var, bu yüzden bilgisayar performansı ve programcı performansı (diğer şeylerin yanı sıra) arasında bir ödünleşmedir, bu yüzden C'de her şeyi programlamayız.
Robert Gamble

4
Binlerce veri satırını daha kısa sürede işleyen C ++ programları oluşturduktan sonra Java veya .NET programları başlatılabilir. Daha modern dillerle yaşadığım hayal kırıklıklarından biri. C, minimum çalışma zamanı gereksinimleri gerektiren yalın programlar için mükemmeldir. PowerBasic bunun için de harika.
bruceatk

35
C ayında bir ay süren ve Java'da yazılmış bir programın iki gün daha hızlı olan bir programın yazmak için sadece bir gün sürdüğünü söylemiyor musunuz? Bu programın günde 500.000.000+ kez çalışması gerekiyorsa ne olur? İki kat daha hızlı olmak inanılmaz derecede önemlidir. Binlerce veya milyonlarca CPU üzerinde çalışıyorsa, performansın iki katına ulaşmak için ekstra geliştirme ayının maliyet tasarrufu muazzam olacaktır. Temel olarak, geliştirme platformunu seçmeden önce dağıtımınızın ölçeğini bilmeniz / anlamanız gerekir.
nicerobot

49

Zaten görmedim, bu yüzden söyleyeceğim: C daha hızlı olma eğilimindedir çünkü neredeyse her şey C ile yazılmıştır .

Java C, Python C (veya Java veya .NET vb.), Perl vb. Üzerine inşa edilmiştir. İşletim Sistemi C ile yazılmıştır, sanal makineler C ile yazılmıştır, derleyiciler C ile yazılmıştır, tercümanlar C dilinde yazılır. Bazı şeyler hala daha hızlı olma eğiliminde olan Montaj dilinde yazılır. Gittikçe daha fazla şey, kendisi C'de yazılmış başka bir şeye yazılıyor.

Diğer dillerde (Assembly değil) yazdığınız her ifade, tipik olarak C'deki yerel makine koduna derlenen birkaç ifade olarak uygulanır. C'den daha yüksek bir soyutlama düzeyi elde etmek için bu diğer diller mevcut olduğundan, C'de gerekli olan bu ekstra ifadeler güvenlik ekleme, karmaşıklık ekleme ve hata işleme sağlamaya odaklanma eğilimindedir. Bunlar genellikle iyi şeylerdir, ancak bir maliyeti vardır ve adları hız ve boyuttur .

Şahsen, mevcut spektrumun çoğunu kapsayan düzinelerce dilde yazdım ve şahsen ipucu verdiğiniz büyüyü aradım:

Kekimi nasıl alabilirim ve yiyebilirim? En sevdiğim dilde üst düzey soyutlamalarla nasıl oynayabilirim, sonra hız için C'nin cesur cesedine nasıl düşebilirim?

Birkaç yıllık bir araştırmadan sonra cevabım Python (C'de). Bir göz atmak isteyebilirsiniz. Bu arada, Python'dan da Meclis'e bırakabilirsiniz (özel bir kütüphaneden bazı küçük yardımlarla).

Öte yandan, kötü kod herhangi bir dilde yazılabilir . Bu nedenle, C (veya Assembly) kodu otomatik olarak daha hızlı değildir . Benzer şekilde, bazı optimizasyon hileleri, daha yüksek seviyeli dil kodunun bölümlerini ham C'nin performans seviyesine yakınlaştırabilir. Ancak, çoğu uygulama için programınız zamanının çoğunu insanlara veya donanıma bekleyerek geçirir, bu nedenle fark gerçekten önemli değildir.

Zevk almak.


10
Bu JIT tarafından derlenmiş diller için geçerli değildir. Benim C # makine koduna derlenmiş C'ye çevrilmiş IL için derleniyor gibi değil. Hayır, IL JIT derlemelidir ve JIT'in uygulama dili bu noktada önemsizdir. Sadece makine kodu üretiyor.
Jon Skeet

3
Tanrı, efsanevi Jon Skeet'i sorgulamamı yasaklıyor, ancak üretilen makine kodunun C yerine C # için olduğu tamamen alakalı görünüyor, bu yüzden "daha yüksek seviye", daha fazla işlevselliğe sahip, güvenlik kontrolleri vb. bu nedenle, "eşdeğer" C'den daha yavaş olabilir
Rob Williams

3
@Jon: Ben benzer bir şey söylemek üzereydim ama nokta aslında biraz geçerli çünkü .NET kitaplığı çekirdek bileşenleri birçoğu aslında gerçekten C ile yazılmış ve bu nedenle C hız sınırlamaları vardır. Gelecekte bunun nasıl değişeceğini görmek ilginç olacak.
Konrad Rudolph

1
Bu yanlış bir yol gibi görünüyor, diğer dil derleyici / yorumlayıcı / vms sık sık ama her zaman c (veya en azından en alt katman için) ile yazılmıyor çünkü c oldukça hızlı (ve çoğu durumda en hızlı).
Roman A.Taycher

2
Bu cevap doğru değil. Yukarıda belirtildiği gibi, JIT dilleri için geçerli değildir, aynı zamanda kendi derleyicileri olan diller için de geçerli değildir (bu, eğer olağanüstü çaba harcanırsa, modern C derleyicilerinden daha hızlı kod üretebilir). Kalan diğer tek dil sınıfı yorumlanmış dillerdir ve bunlar sadece C'de yazıldıkları için C'den daha yavaş değildir , aynı zamanda nasıl dilimlerseniz ve yorumlayıcı montajda yazılmış olsa bile, yorumlama yükü nedeniyle , çok büyük.
16'da Skor_36

38

Orada birçok soru var - çoğunlukla cevaplamaya yetkili değilim. Ama bu sonuncusu için:

diğer dilleri C kadar hızlı çalıştıran ikiliye kadar derlenmesini engelleyecek ne var?

Tek kelimeyle, Soyutlama.

C, makine dilinden sadece bir veya 2 soyutlama seviyesidir. Java ve .Net dilleri, derleyiciden en az 3 soyutlama düzeyindedir. Python ve Ruby'den emin değilim.

Tipik olarak, daha fazla programcı oyuncakları (karmaşık veri türleri, vb.), Makine dilinden ne kadar uzak olursanız ve o kadar fazla çeviri yapmanız gerekir.

Ben oraya gidiyorum ama bu temel öz.

Güncelleme ------- Bu yazı hakkında daha fazla ayrıntı içeren bazı iyi yorumlar var.


3
Teknik olarak, Java ve .Net, üzerinde çalıştıkları makinenin makine dilinden sınırsız bir şekilde soyutlanmaktadır. Sanal makinelerde çalışırlar. JIT ile bile, orijinal kod, yerel makine koduna benzeyen bir şey elde etmek için büyük ölçüde masaj yapılmalıdır.
jmucchiello

1
.net kodu bir VM'de çalışmaz. Üzerinde çalıştığı tüm işlemci platformlarında (32 bit x86, 64 bit x86 veya IA64) yerel talimatlar olarak çalışır.
Robert C. Barth

11
@Robert: .net yapar VM kullanın. .net kodu VM tarafından yürütülen bayt koduna derlenir. VM, bayt kodunu çalışma zamanında yerel talimatlara dönüştürür.
Robert Gamble

3
Bu var çok Java ve diğer OO dil soyutlamaları işlemci komut setlerini etkilemiştir dikkat etmek önemlidir. Java VM bu optimizasyonları biliyor ve kullanıyorsa, yeni işlemciler Java'nın daha hızlı çalışmasını sağlayacak talimatlara sahiptir. Çok büyük değil, ama yararlı.
Adam Davis


35

C'nin hızlı olduğu kadar değil, C'nin maliyet modeli şeffaftır . Bir C programı yavaşsa, bariz bir şekilde yavaştır: birçok deyim yürüterek. C'deki işlemlerin maliyeti ile karşılaştırıldığında, nesneler (özellikle yansıma) veya dizeler üzerindeki üst düzey işlemlerin belirgin olmayan maliyetleri olabilir.

Genellikle C kadar hızlı olan ikili dosyaları derleyen iki dil Standart ML ( MLton derleyicisini kullanarak ) ve Objective Caml'dir . Eğer check out kriterler oyunu o bazı kriterleri için, ikili ağaçlar gibi, OCaml sürümü daha hızlı C'den olduğunu göreceksiniz (Ben herhangi bir MLton girdileri bulamadık.) Fakat çok ciddiye çatışmayı yapmayız; söylediği gibi, bir oyun, sonuçlar genellikle insanların kodu ayarlamak için ne kadar çaba harcadığını yansıtır.


Herhangi bir dilde açıkça pahalı olmayan bir kod yazmak mümkündür. Sadece bazı dillerde, önce Lisp veya Forth'un bir iç varyantını yazmanız gerekiyor ...
Donal Fellows

Ayrıca Rust, benchmarklarda C ile eşleşiyor.
stark

18

C her zaman daha hızlı değildir.

C, örneğin Modern Fortran'dan daha yavaştır.

C, bazı şeyler için genellikle Java'dan daha yavaştır. (Özellikle JIT derleyicisinin kodunuzu girmesinden sonra)

C işaretçi takma işleminin yapılmasına izin verir, bu da bazı iyi optimizasyonların mümkün olmadığı anlamına gelir. Özellikle birden fazla yürütme biriminiz olduğunda, bu veri alma tezgahlarına neden olur. Ow.

İşaretçi aritmetiğinin işe yaradığı varsayımı bazı CPU ailelerinde gerçekten yavaş şişirilmiş performansa neden olur (özellikle PIC!).

Temel olarak, bir vektör birimi veya paralelleştirici bir derleyici aldığınızda, C kokuyor ve modern Fortran daha hızlı çalışıyor.

Thunking gibi C programcı püf noktaları (anında çalıştırılabilir değişiklik) CPU prefetch tezgahları neden olur.

Sen sapmayı anladın mı?

Ve iyi arkadaşımız x86, bu günlerin gerçek CPU mimarisiyle çok az ilişkisi olan bir talimat seti yürütüyor. CPU'da gölge kayıtları, yük deposu optimize edicileri. Böylece C sanal metale yakın olur. Gerçek metal, Intel görmenize izin vermiyor. (Tarihsel olarak VLIW CPU'lar bir parça büsttü, bu yüzden belki de çok kötü değil.)

C'de yüksek performanslı bir DSP (belki bir TI DSP?) Programlıyorsanız, derleyicinin C'yi birden çok paralel yürütme biriminde açmak için bazı zor şeyler yapması gerekir. Bu durumda C metale yakın değil, derleyiciye yakın, bu da tüm program optimizasyonunu yapacak. Tuhaf.

Ve son olarak, bazı CPU'lar (www.ajile.com) donanımda Java bayt kodlarını çalıştırır. C bu CPU'da kullanmak için bir PITA olurdu.


1
Son thunking ne zaman C'de yazıldı? Modern x86, çoğunlukla RISC tasarımı için bir arayüzdür, ancak VLIW ile çok az ilgisi vardır ...
Calyth

7
Gönderinizin çoğu C99'un varlığını yok sayar. Ayrıca, birçok C / C ++ derleyicisi bir uzantı olarak C99 restrict anahtar sözcüğünü sunar (işaretçi takma adı sağlamaz).
Evan Teran

Herkesin CWE / SANS ilk 25'i takip ettiğini ve C'de yeni tasarımlar yapmaktan kaçındığını varsayalım. Yani yeşil alan C yok, çok az veya C99 yok.
Tim Williscroft

2
C modern Fortenberry'den daha yavaş olduğunda örnek gösterebilir misiniz?
Adam

C derleyicilerinin en iyi Fortran derleyicileriyle çok iyi rekabet ettiği bir zaman olduğundan emin değilim. Tabii ki FORTRAN 77'de (bırakın 66) yazmak istemeyeceğiniz birçok kod var, ancak daha yeni Fortran standartları giderek daha hoş oldu.
tfb

11

diğer dilleri C kadar hızlı çalıştıran ikili dilime derlenmesini engelleyecek ne var?

Hiçbir şey değil. Java veya .NET dilleri gibi modern diller performanstan ziyade programcı üretkenliğine yöneliktir. Donanım şimdi ucuz günler. Ayrıca ara gösterime derleme, güvenlik, taşınabilirlik gibi çok sayıda bonus verir. .NET CLR, farklı donanımlardan yararlanabilir - örneğin, SSE talimat setini kullanmak için programı manuel olarak optimize etmeniz / yeniden derlemeniz gerekmez.


burada taşınabilirliği tartışabilirim. Gerçekten taşınabilir kod istiyorsanız, başka bir dilde değil, C dilinde yazacaksınız. Yaklaşık 25 işletim sisteminde çalışan bir kodumuz var. Dos ve threadX'ten başlayıp Linux / XP'de bitirmek bana bunu yapabilen başka bir dil gösteriyor :)
Ilya

1
@Ilya katılmıyorum. C'de taşınabilir olmayan kod yazmak kadar kolaydır. Bazılarının 64 bit'e bağlantı vermesinin ne kadar acı verici olduğuna bakın. Doğru bayt kodu yorumlayıcısına sahipseniz, bayt kodu dilleri platform genelinde çalışabilir.
Calyth

1
@IIya, taşınabilir C kodu kural yerine bir istisna, farklı donanım / yazılım platformları arasında C kodu taşıdım ve bunun bir kabus olduğunu biliyorum.
aku

PC kelimesi için bile durum böyle değil. Java'da biraz c / c ++ ile yazılmış çapraz platform uygulamasının gerçekliğine bakın. Gömülü düşük seviyeli gelişim için başka vaka yoktur. C en taşınabilir dildir.
Ilya

@aku -> PORTING kötü kod felaket olabilir kabul ediyorum. ADVANCE-C'de taşınabilir kod yazmak en iyi seçimdir. C ++ bir seçenek olduğunu söyleyebilirim ama gömülü platforma her zaman iyi C derleyicisi bulacaksınız, c ++ için derleyici olmadan kendini bulabilirsiniz.
Ilya

8

Temel faktörler, statik olarak yazılan bir dil ve makine koduna derlenmiş olmasıdır. Ayrıca, düşük seviyeli bir dil olduğundan, genellikle size söylemediğiniz hiçbir şey yapmaz.

Bunlar akla gelen diğer faktörlerdir.

  • Değişkenler otomatik olarak başlatılmaz
  • Dizileri sınırlama yok
  • İşaretlenmemiş işaretçi işleme
  • Tamsayı taşma kontrolü yok
  • Statik olarak yazılan değişkenler
  • İşlev çağrıları statiktir (işlev işaretçileri kullanmadığınız sürece)
  • Derleyici yazarlarının optimizasyon kodunu geliştirmek için çok zamanları oldu. Ayrıca, insanlar en iyi performansı elde etmek için C'de programlanır, bu nedenle kodu optimize etmek için baskı vardır.
  • Dil spesifikasyonunun bölümleri uygulama tanımlıdır, bu nedenle derleyiciler işleri en uygun şekilde yapmakta özgürdür

Statik olarak yazılan dillerin çoğu, özellikle de işaretçi takma adı vb. Nedeniyle C'nin yapamayacağı varsayımları yapabiliyorsa, C'den daha hızlı veya daha hızlı derlenebilir.


C düşük seviye? Sanırım şimdi bu Java ile karşılaştırıldığında göreceli bir anlam evet ama montaj no ile karşılaştırıldığında. İyi yazı, beni düşündürdü.
Mark

Haklısın, kesinlikle göreceli. Demek istediğim, "makineye yakın" ve bellek yönetimi veya dizi boyutlarını takip etmek gibi şeyler yapmanıza yardımcı olmuyor.
Matthew Crumley

2
C düşük seviyeli bir dildir. C her zaman düşük seviyeli bir dil olmuştur. C kodunu çok zorlanmadan montajcıya elle çevirirsiniz.
Robert C. Barth

2
@Robert: C, üst düzey bir dil olarak kabul edildi çünkü meclis ile karşılaştırıldığında (çok yaygındı). Günümüzde kullanılan dillerin çoğuna kıyasla düşük seviyeli bir dil olarak kabul edilir.
Robert Gamble

Dürüst olmak gerekirse, bu çok taraflı bir cevap. Lanet olsun tüm C programcıları sınır kontrol vb yapmak. Yine de C hala C ++ çok daha hızlı.
MarcusJ

8

Meclis dilinin de bir dil olduğunu unuttun sanırım :)

Ama cidden, C programları sadece programcı ne yaptığını bildiğinde daha hızlıdır. Aynı işi yapan diğer dillerde yazılmış programlardan daha yavaş çalışan bir C programı kolayca yazabilirsiniz.

C'nin daha hızlı olmasının nedeni, bu şekilde tasarlanmasıdır. Derleyicinin kodu optimize etmesine yardımcı olan bir çok "düşük seviye" şeyler yapmanızı sağlar. Veya programcı, kodu optimize etmekten sorumlu olduğunuzu söyleyelim. Ancak genellikle oldukça zor ve hataya açıktır.

Diğer diller, daha önce bahsedilenler gibi, programcının verimliliğine daha fazla odaklanmaktadır. Programcı zamanının makine zamanından çok daha pahalı olduğuna inanılmaktadır (eski günlerde bile). Bu nedenle, programcıların programların çalışma süresi yerine program yazma ve hata ayıklama için harcadıkları zamanı en aza indirmek çok mantıklıdır. Bunu yapmak için, programı daha hızlı hale getirmek için yapabileceklerinizden biraz fedakarlık yapacaksınız çünkü birçok şey otomatik.


3
Bir kez C'de ve tekrar Assembly'de bir program yazdıysanız, derleyici sizden daha akıllı olduğu için C sürümü muhtemelen daha hızlı olacaktır.
mk12

7

Çoğunlukla, her C talimatı çok az montajcı talimatına karşılık gelir. Temelde daha üst düzey makine kodu yazıyorsunuz, bu yüzden işlemcinin neredeyse her şeyi kontrol ediyorsunuz. C ++ gibi diğer birçok derlenmiş dilde, düşündüğünüzden çok daha fazla koda dönüşebilecek çok basit görünümlü talimatlar vardır (sanal işlevler, kopya oluşturucular vb.) Ve Java veya Ruby gibi yorumlanmış diller başka bir katmana sahiptir. hiç görmediğiniz talimatları izleyin - Sanal Makine veya Tercüman.


Ve bu üst düzey dillerin bazıları, ilk etapta ekledikleri sarsıntıların çoğunu kaldırabilmeleriyle gurur duyuyorlar. C ++ 'da kopya elizyonu, dönüş değeri optimizasyonu, taşıma / atama taşıma vb.
cmaster - reinstate monica

Yani her şey koddan oluşturulan montaj talimatlarının sayısına gelir. Yüksek seviyeli kod satırı başına daha fazla montaj talimatı var, performans ne kadar fazla acı çekiyor?
ENDEESA

Bu aşırı basitleştirme olabilir, ancak montaj talimatlarının sayısı ile program hızı arasında doğrudan bir ilişki vardır. İşlemcinin her komutu yürütmesi için minimum süre vardır. Yazdığınız komutların sayısını kolayca anlamanıza izin veren IMHO, daha verimli kod yazmanıza yardımcı olur. (Dallanma ve önbellek özlüyor gibi diğer işlemci zaman maliyetleri de vardır, ancak orada bile daha az soyutlama CPU'nun ne yaptığını netleştirmeye yardımcı olur).
10'da


7

C ++ ortalama olarak daha hızlıdır (başlangıçta olduğu gibi, bazı farklılıklar olsa da, büyük ölçüde C'nin bir üst kümesidir). Bununla birlikte, belirli kriterler için, genellikle daha hızlı olan başka bir dil vardır.

https://benchmarksgame-team.pages.debian.net/benchmarksgame/

fannjuch-redux Scala'da en hızlıydı

n-bodyve fastaAda'da daha hızlıydı.

spectral-norm Fortran'da en hızlıydı.

reverse-complement, mandelbrotVe pidigitsATS en hızlı idi.

regex-dna JavaScript'te en hızlıydı.

chameneou-redux en hızlısı Java 7 idi.

thread-ring Haskell'de en hızlıydı.

Testlerin geri kalanı C veya C ++ 'da en hızlıydı.


"C'nin süper bir kümesi olduğu için" - Hayır, C ++, C'nin bir üst kümesi değildir .
PP

1
extern "C"Bir olmak C ++ ile hiçbir ilgisi yoktur kümesidir C
PP

2
Bu şunu demek gibidir system("bash script.sh");herhangi bash komut dosyası için çalışmalarını ve dolayısıyla C Bash bir üst kümesidir. extern "C"ad yönetimi nedeniyle C ++ 'da C bağlantısını sağlar. X'i Y'nin bir üst kümesi olarak adlandırmak, Y'de yapılabilecek her şeyin C ++ için geçerli olmayan X'te de yapılabileceği anlamına gelir. C dilinde geçerli olan ancak C ++ dilinde geçerli olmayan çok az sayıda dil yapısı vardır.
PP

1
@PP C ++ standardında bashkullanılabilir bir komut satırı programı olan hiçbir şey yoktur . Eğer bash'ın hangi versiyonunu / spesifikasyonunu desteklemesi gerekiyorsa ve içeriyorsa, onun süper set olduğunu düşünürdüm.
Peter Lawrey

1
C ++ kodu olmayan C kodu yazmak çok kolay, örn.struct foo { int: this; }; typedef float foo;
Jasen

6

Bu cevapların birçoğu, C'nin neden daha hızlı (veya daha hızlı) olmasının geçerli nedenlerini vermektedir (genel olarak veya belirli senaryolarda). İnkar edilemez:

  • Diğer birçok dil, bize verdiğimiz otomatik özellikleri sağlar. Örneğin, sınır denetimi, çalışma zamanı türü denetimi ve otomatik bellek yönetimi ücretsiz olarak gelmez. Bu özellikleri kullanan kod yazarken düşünemeyeceğimiz, hatta farkına varamayacağımız bu özelliklerle ilişkili en azından bir miktar maliyet vardır .
  • Kaynaktan makineye adım genellikle diğer dillerde C dilinde olduğu gibi doğrudan değildir.
  • OTOH, derlenmiş C kodunun diğer dillerde yazılmış diğer kodlardan daha hızlı çalıştığını söylemek her zaman doğru olmayan bir genellemedir. Karşı örnekleri bulmak kolaydır (veya devam eder).

Tüm bunlara rağmen, fark ettim ki, C'nin diğer birçok dil ile karşılaştırmalı performansını diğer tüm faktörlerden daha fazla etkilediğini fark ettim. Zekâ için:

Diğer diller genellikle daha yavaş çalışan kod yazmayı kolaylaştırır. Çoğu zaman, dilin tasarım felsefeleri tarafından bile teşvik edilir. Sonuç: C programcısının gereksiz işlemler yapmayan kod yazma olasılığı daha yüksektir.

Örnek olarak, tek bir ana pencerenin oluşturulduğu basit bir Windows programını düşünün. AC sürümü, geçilecek bir WNDCLASS[EX]yapıyı doldurur RegisterClass[Ex], ardından CreateWindow[Ex]bir mesaj döngüsü çağırır ve girer. Son derece basitleştirilmiş ve kısaltılmış kod aşağıdaki gibidir:

WNDCLASS wc;
MSG      msg;

wc.style         = 0;
wc.lpfnWndProc   = &WndProc;
wc.cbClsExtra    = 0;
wc.cbWndExtra    = 0;
wc.hInstance     = hInstance;
wc.hIcon         = NULL;
wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszMenuName  = NULL;
wc.lpszClassName = "MainWndCls";

RegisterClass(&wc);

CreateWindow("MainWndCls", "", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
             CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

while(GetMessage(&msg, NULL, 0, 0)){
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

C # 'daki eşdeğer bir program sadece bir kod satırı olabilir:

Application.Run(new Form());

Bu bir kod satırı, yaklaşık 20 satır C kodunun yaptığı tüm işlevleri sağlar ve hata kontrolü gibi dışarıda bıraktığımız bazı şeyleri ekler. Daha zengin, daha dolgun kütüphane (tipik bir C projesinde kullanılanlara kıyasla) bizim için çok fazla iş yaptı, bize kısa görünen ama sahnelerin arkasında birçok adım içeren daha fazla kod parçacığı yazma zamanımızı serbest bıraktı.

Ancak kolay ve hızlı kod şişkinliğini mümkün kılan zengin bir kütüphane gerçekten benim açımdan değil. Küçük tek astarımız gerçekten çalıştığında gerçekte ne olduğunu incelemeye başladığınızda benim açımdan daha belirgin. Eğlenmek için, Visual Studio 2008 veya daha yüksek bir sürümde .NET kaynak erişimini etkinleştirin ve yukarıdaki basit one-linef'e adım atın. Karşılaşacağınız eğlenceli küçük taşlardan biri, alıcıdaki bu yorumu Control.CreateParams:

// In a typical control this is accessed ten times to create and show a control.
// It is a net memory savings, then, to maintain a copy on control.
// 
if (createParams == null) {
    createParams = new CreateParams(); 
} 

On kez . Bir depoladıklarınızı toplamına kabaca eşdeğer bilgi WNDCLASSEXyapısı ve hangi geçirilen CreateWindowExalınır Controlsınıf on kez önce bir saklanan WNDCLASSEXyapısı ve geçirilir RegisterClassExve CreateWindowEx.

Sonuçta, bu çok temel görevi gerçekleştirmek için yürütülen talimatların sayısı C # 'da C'den daha fazla 2-3 büyüklük sırasıdır. Bunun bir kısmı, zorunlu olarak genelleştirilmiş, zenginleştirilmiş bir kütüphanenin kullanılmasından kaynaklanmaktadır. tam olarak ihtiyacımız olan şeyi ve daha fazlasını yapan basit C kodumuz. Ancak bunun bir kısmı, .NET çerçevesinin modülerleştirilmiş, nesneye yönelik doğasının, genellikle prosedürel bir yaklaşımla kaçınılması gereken çok sayıda yürütme tekrarına borç vermesidir.

C # veya .NET framework almaya çalışmıyorum. Ben de modülerleşme, genelleme, kütüphane / dil özellikleri, OOP, vs.'nin kötü şeyler olduğunu söylemiyorum . Gelişimimin çoğunu C, daha sonra C ++ ve son zamanlarda C # ile yapıyordum. Benzer şekilde, C'den önce çoğunlukla montaj kullandım. Ve her adım "daha yüksek" benim dilim gider, daha kısa sürede daha iyi, daha sürdürülebilir, daha sağlam programlar yazıyorum. Bununla birlikte, biraz daha yavaş yürütme eğilimindedirler.


2
Bu bir API sorunu, dil sorunu değil.
Arafangion

1
@Arafangion: Ne dediğini anlıyorum, ama bir nevi noktayı kaçırıyor. Zengin özelliklere sahip kitaplık, zengin özelliklere sahip dil ​​tarafından etkinleştirilir (ve bir şekilde talep edilir). Ve bu sadece kütüphane değil. Kütüphane, dilin yaygın kullanımının sadece bir örneğidir. Herhangi bir dilde tipik uygulama kodu genellikle o dilde tipik olarak kullanılan kitaplıklarla benzerlik gösterir. Gerçekten daha çok dil tarafından teşvik edilen bir zihniyet. Örneğin, OO dilleri genellikle nesneleri ayırmak, inşa etmek, imha etmek ve yeniden yerleştirmek için daha az OOP desteğine sahip dillerden daha fazla zaman harcarlar.
P Daddy

Belirli bir dil seçiminin genellikle belirli bir platform ve kütüphane anlamına geldiğini kabul edeceğim, bu yüzden bu yorumu yaptım (böylece okuyucu daha bilinçli olacaktı), ancak bu, pencerelerde (örneğin) C ++ kullanmanın bir linux C ++ ve Android C ++ ile tekrar farklı çok farklı canavar. Başka bir örnek Python - hepsi çok farklı kütüphaneler kullanan CPython, Jython, PyPy ve IronPython'umuz var.
Arafangion

Ancak, bu Python'lardan herhangi birini kullanarak, geliştiriciler uygulamaları belirli bir şekilde yazma eğilimi gösterecektir. Örneğin, okudukları verilerle yeni nesneler oluşturarak bir metin dosyasını okuyabilir ve yazabilirler. Öte yandan, C, bir geliştirici büyük olasılıkla bir dizi yapının bir kerelik tahsisini yapar ve bu yapıları bir ikili dosyadan okur ve yazar. Bu, elbette, zihniyet hakkında konuşmaya çalıştığım noktayı göstermeye çalışan basit bir örnek .
P Daddy

6

Kimsenin C derleyicilerine, belki de Java hariç, diğer derleyicilere göre çok daha fazla çaba sarf edildiğinden bahsetmediğini sanmıyorum.

C, daha önce belirtilmiş olan birçok nedenden ötürü son derece optimize edilebilir - neredeyse diğer dillerden daha fazla. Dolayısıyla, aynı dil çabası diğer dil derleyicilerine konulursa, C muhtemelen yine de en üstte çıkacaktır.

Çaba ile C'den daha iyi optimize edilebilen en az bir aday dil olduğunu düşünüyorum ve böylece daha hızlı ikili dosyalar üreten uygulamaları görebiliyoruz. Dijital mars D'yi düşünüyorum çünkü içerik oluşturucu potansiyel olarak C'den daha iyi optimize edilebilen bir dil oluşturmaya özen gösterdi. Bu olasılığa sahip başka diller de olabilir. Ancak herhangi bir dilin en iyi C derleyicilerinden yüzde birkaç daha hızlı derleyiciye sahip olacağını hayal edemiyorum. Yanlış olmayı çok isterim.

Bence gerçek "düşük meyveli meyve" insanların optimize etmesi için KOLAY olacak şekilde tasarlanmış dillerde olacak. Yetenekli bir programcı herhangi bir dili daha hızlı hale getirebilir - ancak bazen bunu yapmak için saçma şeyler yapmanız veya doğal olmayan yapılar kullanmanız gerekir. Her zaman çaba sarf etse de, iyi bir dil, programın nasıl yazıldığını tam olarak saplantı haline getirmeden nispeten hızlı kod üretmelidir.

En kötü durum kodunun hızlı olma eğiliminde olması da (en azından benim için) önemlidir. Web'de Java'nın C'den daha hızlı veya daha hızlı olduğuna dair çok sayıda "kanıt" vardır, ancak bu kiraz toplama örneklerine dayanmaktadır. C'nin büyük hayranı değilim, ama C'de yazdığım her şeyin iyi gideceğini biliyorum. Java ile hızın% 15'inde, genellikle% 25'inde "muhtemelen" çalışır, ancak bazı durumlarda çok daha kötü olabilir. Bu kadar hızlı veya birkaç yüzde içinde olan durumlar genellikle çoğu zaman C'nin aşırı derecede optimize edilmiş olan kütüphane kodunda harcanmasından kaynaklanır.


5

Bu aslında biraz süren bir yalan. C programlarının sıklıkla daha hızlı olduğu doğru olsa da, özellikle C programcısı çok iyi değilse bu her zaman geçerli değildir.

İnsanların unutmaya eğilimli olduğu büyük bir göze çarpan delik, programın herhangi bir GUI programında kullanıcı girişi gibi bir çeşit IO için engellemesi gerektiğidir. Bu durumlarda, hangi dili kullandığınız gerçekten önemli değildir, çünkü verilerin ne kadar hızlı işlenebileceğinden ziyade verilerin gelme oranı ile sınırlıdır. Bu durumda, C, Java, C # ve hatta Perl kullanıyorsanız çok önemli değil; verilerin gelebileceğinden daha hızlı gidemezsiniz.

Diğer önemli şey, çöp toplama özelliğini kullanmak ve uygun işaretçiler kullanmamak, sanal makinenin diğer dillerde mevcut olmayan bir dizi optimizasyonu yapmasına izin vermektir. Örneğin, JVM nesneleri birleştirmek için öbek üzerinde nesneleri hareket ettirebilir. Bu, gelecekteki ayırmaları çok daha hızlı hale getirir, çünkü bir sonraki dizin bir tabloya bakmak yerine basitçe kullanılabilir. Modern JVM'lerin aslında hafızayı yeniden yerleştirmesi gerekmez; bunun yerine, canlı nesneleri GC olduklarında hareket ettirirler ve ölü nesnelerden harcanan bellek esas olarak ücretsiz olarak kurtarılır.

Bu ayrıca C hakkında ilginç bir noktaya ve daha da C ++ 'da ortaya çıkar. Bir tasarım felsefesi var: "İhtiyacınız yoksa, ödemezsiniz." Sorun şu ki, eğer isterseniz, bunun için burundan ödeme yaparsınız. Örneğin, Java'daki vtable uygulaması C ++ uygulamalarından çok daha iyi olma eğilimindedir, bu nedenle sanal işlev çağrıları çok daha hızlıdır. Öte yandan, Java'da sanal işlevleri kullanmaktan başka seçeneğiniz yoktur ve hala bir maliyeti vardır, ancak çok fazla sanal işlev kullanan programlarda, düşük maliyet eklenir.


1
"Java'daki vtable uygulaması, C ++ uygulamalarından çok daha iyi olma eğilimindedir, bu nedenle sanal işlev çağrıları çok daha hızlıdır." Nasıl yeryüzünde MOV EAX, [ECX] daha hızlı gidebilirsiniz; ARAYIN [EAX + bir dizin]; ? Bir işlevi aramadan arayamazsanız, bu oldukça uygun görünür.
Frans-Willem

@Frans - bir JIT derleyicisi (Java HotSpot gibi), belirli bir nesnenin her zaman belirli bir türde olduğunu belirlerse vtable aramasını satır içi yapabilir. C ++, aynı bilgileri derleme zamanında da biliyorsa bunu yapacaktır, ancak bu optimizasyonu Java bayt kodu ile yapmak x86 makine talimatlarından daha kolaydır.
Tom

6
@James - "G / Ç performansı daha az önemli hale getirir" demek "C diğer dillerden daha hızlıdır" ifadesini geçersiz kılmaz. Bu göze batan bir delik değil, bu bir strawman argümanı.
Tom

C'nin string işleyişini (ve aynı zamanda standart C kütüphanesini) örnek olarak kullanmak daha iyi olurdu, çünkü bu C'nin zayıf olduğu bir alandır. Diğer birçok dil, basit başlangıç ​​koduyla bile daha iyi sonuç verir.
Donal Fellows

@DonalFellows mem * işlevleri, bazı görevlerde str * işlevlerinden daha hızlı olabilir, ancak dikkat edilmesi durumunda dize kullanımı etkilidir. aklınızda belirli bir kriter var mı?
Jasen

4

Dil, araçlar ve kütüphaneler kadar o kadar da değil. C için mevcut kütüphaneler ve derleyiciler yeni dillerden çok daha eskidir. Bunun onları daha yavaş yapacağını düşünebilirsiniz, ama tam tersi.

Bu kütüphaneler, gücü ve hafızayı işlemenin önemli olduğu bir zamanda yazılmıştır. Çalışabilmek için çok verimli bir şekilde yazılmaları gerekiyordu . C derleyicilerinin geliştiricileri de farklı işlemciler için her türlü akıllı optimizasyonda çalışmak için uzun zamana sahipti. C'nin olgunluğu ve geniş kabulü, aynı yaştaki diğer dillere göre önemli bir avantaj sağlar. Ayrıca C'ye, C'nin sahip olduğu kadar ham performansı vurgulamayan yeni araçlara göre bir hız avantajı sağlar.


4

Soyutlama eksikliği C'yi daha hızlı yapan şeydir. Bir çıktı bildirimi yazarsanız, tam olarak ne olduğunu bilirsiniz. Java'da bir çıktı deyimi yazarsanız, daha sonra bir soyutlama katmanı tanıtan bir sanal makinede çalıştırılan bir sınıf dosyasına derlenir. Dilin bir parçası olarak nesne yönelimli özelliklerin olmaması da daha az kod üretilmesi için hızını artırır. C'yi nesne yönelimli bir dil olarak kullanırsanız, sınıflar, kalıtım, vb. Şeyler için tüm kodlamayı yapıyorsunuz. Bu, daha sonra kod miktarı ve sadece yazmanızı gerektiren performans penisi olan herkes için yeterince genelleştirilmiş bir şey yapmak anlamına gelir. işi yapmak için gerekenler.


4

Eski "C / C ++ Java'dan daha hızlı olmalı çünkü Java yorumlanıyor" efsanesi hala canlı ve tekmeliyor. Orada birkaç yıl geri dönüyor makaleler yanı sıra, daha yeni olanları niçin kavramlar veya ölçümler ile açıklamak, bu basitçe her zaman böyle değildir .

Mevcut sanal makine uygulamaları (ve bu arada sadece JVM değil), çeşitli teknikler kullanarak kodu çalışırken dinamik olarak ayarlamak için program yürütme sırasında toplanan bilgilerden yararlanabilir:

  • makine koduna sık kullanılan yöntemlerin oluşturulması,
  • satır içi küçük yöntemler,
  • kilitleme ayarı

ve kodun gerçekte ne yaptığını bilmeye ve içinde çalıştığı ortamın gerçek özelliklerine bağlı olarak yapılan çeşitli diğer ayarlamalar .


Java'nın son birkaç yılda, ham performans açısından C'ye çok daha yakın hale getiren önemli performans iyileştirmeleri yaptığını kabul ediyorum, ancak bu kadar uzun süre çok yavaş olduğu gerçeğini yaşamak biraz zaman alacak . Ama yine de Java hakkında kim konuşuyordu?
Robert Gamble

Java OP tarafından başvurulan "diğer bir dildir", değil mi?
Robert C. Barth

@Robert: "diğer diller", çoğul, C dışında herhangi bir dilden bahsedilmez. "Java" yı bundan nasıl okursunuz?
Robert Gamble

@Roberd: Soru ile karşılaşmadan önce gönderilen cevapların birçoğu Java (veya uygulaması genellikle tercüman veya VM aracılığıyla olan diğer diller) hakkında konuşuyordu.
joel.neely

3
@Joel - Hedef donanımınızı biliyorsanız, JVM'nin çalışma zamanında yapabileceği çoğu optimizasyon, C veya C ++ ile profil güdümlü optimizasyon kullanılarak da yapılabilir. Bu büyük bir fark yaratır ve genellikle C ve C ++ 'yı liderlik içine iter, çünkü yürütürken "öğrenmek" zorunda kalmazlar.
Tom

4

En hızlı çalışan kod özenle el yapımı makine kodu olacaktır. Assembler neredeyse iyi olacak. Her ikisi de çok düşük seviyededir ve bir şeyler yapmak için çok fazla kod yazmak gerekir. C, montajcının biraz üstündedir. Hala gerçek makinede çok düşük bir seviyede şeyleri kontrol etme yeteneğine sahipsiniz, ancak yazarı montajcıdan daha hızlı ve daha kolay hale getirmek için yeterli soyutlama var. C # ve JAVA gibi diğer diller daha da soyuttur. Assembler ve makine kodu düşük seviyeli diller olarak adlandırılırken, C # ve JAVA (ve diğerleri) yüksek seviyeli diller olarak adlandırılır. C bazen orta düzey dil olarak adlandırılır.


Cevabınızı okurken, tüm paragraftaki sadece iki kelime, metalleri çeken bir mıknatıs gibi gözlerimi onlara doğru çekiyordu. Kelime paragrafta iki kez JAVA. Tüm büyük harflerle yazılmadan önce hiç görmedim ve iyi görünüyor :-)
Sнаđошƒаӽ

3

Kimsenin sözünü tutmayın, kodunuzun herhangi bir performans açısından kritik bölümünde hem C'nin hem de seçtiğiniz dilin sökülmesine bakın. Demonte .Net görmek için sadece Visual Studio'da çalışma zamanında sökme penceresine bakabilirsiniz düşünüyorum. Eğer windbg kullanarak Java için zor olabilir, ancak .Net ile yaparsanız sorunların çoğu aynı olurdu.

İhtiyacım yoksa C'ye yazmaktan hoşlanmıyorum, ancak bu cevaplarda C'den başka dillerin hızını ortaya koyan iddiaların birçoğunun C'deki aynı rutini sökerek bir kenara bırakılabileceğini düşünüyorum. özellikle performans açısından kritik uygulamalarda yaygın olarak kullanılan çok sayıda veri varsa. Fortran, uzmanlık alanında bir istisna olabilir, bilmiyorum. C seviyesinden daha yüksek mi?

İlk kez JITed kod yerel kod ile karşılaştırdı. Net kodu C kodu karşılaştırılabilir çalıştırabilir olsun ve tüm soruları çözdü. Ekstra soyutlama seviyesi ve tüm güvenlik kontrolleri önemli bir maliyetle gelir. Aynı maliyetler büyük olasılıkla Java için de geçerlidir, ancak benim sözüme güvenmeyin, performansın kritik olduğu bir yerde deneyin. (JITed Java hakkında derlenmiş bir yordamı bellekte bulmak için yeterli bilgiye sahip olan var mı? Kesinlikle mümkün olmalı)


2

1) Diğerlerinin söylediği gibi, C sizin için daha az şey yapar. Başlangıç ​​değişkenleri yok, dizi kontrolü yok, bellek yönetimi yok, vb. Diğer dillerdeki bu özellikler C'nin harcamadığı bellek ve CPU döngülerine mal olur.

2) C'nin daha az soyutlandığını ve bu nedenle daha hızlı olduğunu söyleyen cevaplar sadece yarı doğrudur. Teknik olarak konuşursak, X dili için "yeterince gelişmiş bir derleyici" varsa, X dili C hızına yaklaşabilir veya C hızına eşit olabilir. C ile fark çok açık bir şekilde eşleştiği için (bir mimari dersi aldıysanız) ve saf bir derleyicinin bile iyi bir iş yapabileceği doğrudan montaj diline. Python gibi bir şey için, olası nesne türlerini tahmin etmek ve makine kodunu anında oluşturmak için çok gelişmiş bir derleyiciye ihtiyacınız vardır - C'nin anlambilimi, basit bir derleyicinin iyi yapabileceği kadar basittir.


2

İyi günlerde, sadece iki tür dil vardı: derlendi ve yorumlandı.

Derlenmiş diller, dil sözdizimini okumak ve bunu doğrudan CPU'dan daha iyi olabilecek özdeş derleme dil koduna dönüştürmek için bir "derleyici" kullandı. Yorumlanan diller birkaç farklı şema kullandı, ancak temel olarak dil sözdizimi bir ara forma dönüştürüldü ve ardından kodu yürütmek için bir ortam olan bir "yorumlayıcı" içinde çalıştırıldı.

Böylece, bir anlamda, kod ve makine arasında başka bir "katman" - yorumlayıcı - vardı. Ve her zaman olduğu gibi, bir bilgisayarda olduğu gibi, daha fazla kaynak kullanılması anlamına gelir. Tercümanlar daha yavaştı, çünkü daha fazla işlem yapmak zorunda kaldılar.

Daha yakın zamanlarda, Java gibi daha derli toplu diller gördük, bunları çalıştırabilmek için hem derleyici hem de yorumlayıcı kullanıyorduk. Bu karmaşık, ancak bir JVM, eski tercümanlardan daha hızlı, daha sofistike ve çok daha optimize edilmiştir, bu nedenle (zaman içinde) düz derlenmiş koda daha yakın performans gösterme çok daha iyi bir değişime sahiptir. Tabii ki, yeni derleyiciler de daha süslü optimize hilelere sahiptir, böylece eskisinden daha iyi kod üretme eğilimindedirler. Ancak çoğu optimizasyon, çoğu zaman (her zaman olmasa da), her durumda daha hızlı olmayacak şekilde bir tür değiş tokuş yapar. Diğer her şey gibi, hiçbir şey ücretsiz gelmez, bu nedenle optimize ediciler bir yerden övünmelidir (çoğu zaman çalışma zamanı CPU'yu kaydetmek için derleme zamanı CPU kullanarak).

C'ye geri dönmek, oldukça optimize edilmiş bir montajda derlenebilen ve daha sonra doğrudan hedef makinede çalıştırılabilen basit bir dildir. C'de, bir tamsayıyı arttırırsanız, CPU'da yalnızca bir montajcı adımı olması daha olasıdır, ancak Java'da, bundan çok daha fazla olabilir (ve biraz çöp toplama da içerebilir): -) C, makineye çok daha yakın bir soyutlama sunar (montajcı en yakın olanıdır), ancak devam etmek için daha fazla iş yapmak zorunda kalırsınız ve korumalı, kullanımı kolay veya hata dostu değildir. Diğer dillerin çoğu size daha yüksek bir soyutlama sağlar ve sizin için daha fazla temel ayrıntıya dikkat eder, ancak gelişmiş işlevleri karşılığında daha fazla kaynağa ihtiyaç duyarlar. Bazı çözümleri genelleştirirken, daha geniş bir bilgi işlem yelpazesi kullanmanız gerekir,

Paul.


"C'de, bir tamsayıyı artırırsanız, CPU'da yalnızca bir montajcı adımı olması daha olasıdır" Tam olarak doğru değil. Bu tamsayı CPU kaydında değilse, bellekten almak, arttırmak ve tekrar belleğe yazmak için makine koduna sahip olmanız gerekir. Java kodunu çalıştırırken de aynı şekilde gerçekleşmesi beklenir. Ve neden "++ i" nin kendisinin bir GC döngüsünü tetikleyeceği fikrini anlamıyorum.
quant_dev

@quant_dev: "siz .. bellekte almak, artırmak, geri yazmak ... ... var." Belki, belki değil. Örneğin x86, bellekteki veriler üzerinde çalışan talimatlara sahiptir. ++i"ebp - 8], 1 ekle" şeklinde derlenebilir. Getirme, arttırma, mağazanın hala gerçekleşmediğini söylememekle birlikte, bu CPU tarafından halledilir ve Paul'un söylediği gibi sadece bir talimattır.
P Daddy

... performansın POV'sinden hala önemsizdir, çünkü bu sadece bir komut olabilir, ancak yine de verilerin CPU'ya ulaşmasını beklemeyi içerir. Önbellek özlüyor ve tüm bunlar.
quant_dev

Hayır, bunun alakasız olduğunu söyleyemem. Bir CPU komutu genellikle birden fazla CPU komutundan daha az kod baytı kaplar ve kod segmentinde daha iyi önbellek performansı sağlar. Bir CPU talimatı ayrıca CPU'nun boru hattında daha az yer kaplar ve birden fazla adım (getirme, arttırma, depolama) ayrı boru hattı aşamalarıyla - belki de paralel olarak - ele alınabilir. Aslında, bir işlemin bazı bölümleri boru hattındaki diğer işlemlerle eritilebiliyorsa atlanabilir. Örneğin, bir değerin saklanması, aynı değerin müteakip yüklemesi ile eritilebilir.
P Daddy

2

Etkin nokta optimizasyonu , önceden derlenmiş meta algoritmalar ve çeşitli paralellik biçimleri gibi gelişmiş optimizasyon tekniklerini bir kenara bırakarak , bir dilin temel hızı, yaygın olarak kullanılan işlemleri desteklemek için gereken örtülü sahne arkası karmaşıklığı ile güçlü bir şekilde ilişkilidir. iç döngüler içinde belirtilmelidir .

Belki de en belirgin olanı dolaylı bellek referansları üzerinde geçerlilik kontrolüdür - örneğin, işaretçiler için nulldizinleri kontrol etmek ve dizin sınırlarına karşı dizinleri kontrol etmek gibi . Çoğu üst düzey dil bu denetimleri örtük olarak gerçekleştirir, ancak C yapmaz. Bununla birlikte, bu mutlaka bu diğer dillerin temel bir sınırlaması değildir - yeterince zeki bir derleyici, bir döngü-değişmez kod hareketi biçimi aracılığıyla bu kontrolleri bir algoritmanın iç döngülerinden kaldırabilir .

C'nin (ve benzer ölçüde yakından ilişkili C ++) daha temel avantajı, ayırma , yeniden yerleştirme ve erişim için doğal olarak hızlı olan yığın tabanlı bellek tahsisine büyük bir bağımlılıktır . C (ve C ++) 'da birincil çağrı yığını , ilkel, dizi ve agregaların ( struct/ class) tahsisi için kullanılabilir .

C, keyfi boyut ve ömür boyu ('yığın' adı verilen) belleği dinamik olarak tahsis etme olanağı sunarken, varsayılan olarak bu işlemden kaçınılır (bunun yerine yığın kullanılır).

Tantalize ederek, bazen C bellek ayırma stratejisini diğer programlama dillerinin çalışma ortamlarında çoğaltmak mümkündür. Bu, C veya C ++ ile yazılan kodun JavaScript'in bir alt kümesine çevrilmesine ve bir web tarayıcısı ortamında - yerel hıza yakın bir hızda - güvenli bir şekilde çalışmasına izin veren asm.js tarafından gösterilmiştir .


Bir şekilde, C ve C ++ 'nın hız için diğer birçok dili gölgede bıraktığı başka bir alan, yerel makine komut setleri ile sorunsuz bir şekilde entegre olma yeteneğidir. Bunun dikkate değer bir örneği , dilin sağladığı veri ayırma soyutlamalarını kullanmaya devam ederken (neredeyse her yerde bulunan paralel işleme donanımından yararlanan özel algoritmaların oluşturulmasını destekleyen (derleyiciye ve platforma bağlı) SIMD intrinsics'in kullanılabilirliğidir (daha düşük) düzey kayıt tahsisi derleyici tarafından yönetilir).


1
C'nin bu bellek ayırma avantajından bazıları, diğer dillerde de akıllı derleyiciler tarafından çoğaltılabilir ( buraya bakın ). Bununla birlikte, özellikle ilkel olmayan veri türleri için bunun bir şekilde yapısal olarak çok zor olduğu izlenimini edindim. Bu yazı , Java'da bir optimizasyon olarak yığınla ayrılabilen, kaçmayan bir nesne fikrinden bahsediyor .
nobar

2

Neden bazı dillerin daha hızlı ve bazılarının daha yavaş olduğu hakkında bir cevap buldum, umarım bu C veya C ++ 'ın neden diğerlerinden daha hızlı olduğu hakkında daha fazla bilgi verecektir, C'den daha hızlı olan başka diller de var, ancak yapamayız hepsini kullan. Bazı açıklamalar -

Fortran'ın önemli kalmasının en büyük nedenlerinden biri hızlı olmasıdır: Fortran'da yazılan sayı sıkışma rutinleri diğer birçok dilde yazılmış eşdeğer rutinden daha hızlı olma eğilimindedir. Bu alanda Fortran ile rekabet eden diller - C ve C ++ - bu performansla rekabet edebildikleri için kullanılır.

Bu şu soruyu gündeme getiriyor: neden? C ++ ve Fortran hakkında onları hızlı yapan nedir ve neden Java veya Python gibi diğer popüler dillerden daha iyi performans gösteriyorlar?

Derlemeye karşı yorumlama Teşvik ettikleri programlama stiline ve sundukları özelliklere göre programlama dillerini sınıflandırmanın ve tanımlamanın birçok yolu vardır. Performansa bakıldığında, en büyük tek fark yorumlanmış diller ile derlenmiş diller arasındadır.

Bölünmek zor değil; daha ziyade, bir spektrum var. Bir ucunda, geleneksel derlenmiş dillerimiz var, Fortran, C ve C ++ içeren bir grup. Bu dillerde, bir programın kaynak kodunu işlemcinin kullanabileceği yürütülebilir bir forma çeviren ayrı bir derleme aşaması vardır.

Bu derleme işleminin birkaç adımı vardır. Kaynak kodu analiz edilir ve ayrıştırılır. Yazım hataları ve yazım hataları gibi temel kodlama hataları bu noktada tespit edilebilir. Ayrıştırılan kod, hataları algılamak için de kullanılabilen bir bellek içi gösterim oluşturmak için kullanılır - bu kez, var olmayan işlevleri çağırmak veya metin dizelerinde aritmetik işlemler yapmaya çalışmak gibi anlamsal hatalar.

Bu bellek içi gösterim daha sonra çalıştırılabilir kod üreten bölüm olan kod üretecini çalıştırmak için kullanılır. Üretilen kodun performansını artırmak için kod optimizasyonu, bu süreç içinde çeşitli zamanlarda gerçekleştirilir: kod gösterimi üzerinde yüksek seviye optimizasyonları yapılabilir ve kod üretecinin çıktısında daha düşük seviye optimizasyonları kullanılır.

Aslında kodun yürütülmesi daha sonra olur. Tüm derleme işlemi yürütülebilecek bir şey oluşturmak için kullanılır.

Diğer tarafta tercümanlarımız var. Tercümanlar derleyicininkine benzer bir ayrıştırma aşaması içerecektir, ancak bu daha sonra programın hemen çalıştırıldığı doğrudan yürütmeyi sağlamak için kullanılır.

En basit yorumlayıcı, dilin desteklediği çeşitli özelliklere karşılık gelen yürütülebilir koda sahiptir - bu nedenle, belirli bir dilin ne olursa olsun, numara ekleme, dizelere katılma işlevlerine sahip olacaktır. Kodu ayrıştırırken, ilgili işlevi arar ve yürütür. Programda oluşturulan değişkenler, isimlerini verileriyle eşleştiren bir çeşit arama tablosunda tutulacaktır.

Yorumlayıcı stilinin en uç örneği, bir toplu iş dosyası veya kabuk komut dosyası gibi bir şeydir. Bu dillerde, çalıştırılabilir kod genellikle yorumlayıcının kendisinde değil, ayrı ayrı bağımsız programlarda yerleşiktir.

Peki bu neden performansta fark yaratıyor? Genel olarak, her bir dolaylı katman performansı düşürür. Örneğin, iki sayı eklemenin en hızlı yolu, bu sayıların her ikisini de işlemcideki kayıtlarda bulundurmak ve işlemcinin ekleme yönergesini kullanmaktır. Derlenmiş programlar bunu yapabilir; değişkenleri yazmaçlara koyabilir ve işlemci talimatlarından yararlanabilirler. Ancak yorumlanan programlarda, aynı ekleme, eklenecek değerleri almak için bir değişkenler tablosunda iki arama gerektirebilir, ardından ekleme işlemini gerçekleştirmek için bir işlevi çağırabilir. Bu işlev, derlenmiş programın gerçek eklemeyi gerçekleştirmek için kullandığı işlemcinin komutunu çok iyi kullanabilir, ancak talimatın gerçekten kullanılmasından önceki tüm ekstra işler işleri yavaşlatır.

Daha fazla bilgi edinmek istiyorsanız lütfen Kaynağı kontrol edin


1

Bazı C ++ algoritmaları C'den daha hızlıdır ve diğer dillerdeki algoritmaların veya tasarım modellerinin bazı uygulamaları C'den daha hızlı olabilir.

İnsanlar C'nin hızlı olduğunu söyledikten sonra başka bir dil hakkında konuşmaya geçtiklerinde, genellikle C'nin performansını bir kriter olarak kullanıyorlar.


2
"Bazı C ++ algoritmaları C'den daha hızlıdır" mantıklı değil. Herhangi bir "C ++ algoritması" C ile yazılabilir. Algoritmalar dil bilincindedir. C ++ temel olarak C'ye özellikler ekler ve bu yeni özelliklerin hiçbiri daha hızlı algoritmalara yol açmaz (belki de daha kolay yazılırlar).
Joseph Garvin

1
Klasik rebuke std :: sort algoritmasıdır .. std :: sort, C'deki herhangi bir sıralama algoritmasından daha hızlıdır - C'de aynı performansı elde etmenin tek yolu, istediğiniz her yere kodlamak veya makroları kullanmaktır - ve hatta o zaman derleyicinin optimize etmek için daha az bilgisi vardır.
Arafangion

1

Modern optimizasyon derleyicileri ile, saf bir C programının derlenmiş .net kodundan çok daha hızlı olması pek olası değildir. .Net gibi çerçevelerin geliştiriciye sağladığı verimlilik artışı ile, normal C'de haftalar veya aylar süren bir günde bir şeyler yapabilirsiniz. Bir geliştiricinin maaşına kıyasla ucuz donanım maliyeti ile birleştiğinde, sadece YOL yazma daha ucuz üst düzey bir dilde ve herhangi bir yavaşlıkta donanım atmak.

Jeff ve Joel'in C'nin "gerçek programcı" dil olduğu hakkında konuşmasının nedeni, C'de el tutma olmamasıdır. yeni nesne olarak (); Çöp toplama, sınıflar, OOP, varlık çerçeveleri, LINQ, özellikler, öznitelikler, alanlar veya bunun gibi bir şey yoktur. İşaretçi aritmetiği ve bir işaretleyicinin kayıttan çıkarılması gibi şeyleri bilmelisiniz. Ve bu konuda, bir işaretçinin ne olduğunu bilin ve anlayın. Bir yığın çerçevesinin ne olduğunu ve yönerge işaretçisinin ne olduğunu bilmeniz gerekir. Üzerinde çalıştığınız CPU mimarisinin bellek modelini bilmelisiniz. Bir mikrobilgisayar mimarisinin (genelliklemikrobilgisayar) üzerinde çalışıyorsanız), C'de veya C # veya Java gibi bir programda programlama sırasında gerekli olmayan veya gerekli olmayan C programlanırken. Tüm bu bilgiler derleyici (veya VM) programlayıcısına yüklendi.


"Sorunda daha fazla donanım" yalnızca bunun mümkün olduğu ortamlarda çalışır. Gömülü pazar mükemmel bir karşı örnek (ve bu büyük bir pazar).
Bob Somers

Jeff ve Joel, gömülü sistemler değil, yalnızca iş sistemleri hakkında blog yazarlar, bu yüzden bu sorunun sorulduğu bağlam olduğunu varsaymak mantıklıdır.
Robert C. Barth

1) .net kodu C kodu kadar hızlı çalışıyor? Hiç C programı yazdınız mı? 2) "Soruna daha fazla donanım atma" anlayışımız, 1.3GHz çift çekirdekli 2GB makinemin neden Windows XP ile güçlük çekerken 800MHz 512MB'lık makinem Ubuntu'nun en son sürümüyle uçuyor.
Robert Gamble

Evet, C yazdım. İnsanlar bunu yapmak kadar görkemli değil. Ve projeler çok pahalı. Bu basit bir ekonomi örneğidir. Win2k'i yıllarca 768MB RAM ile Pentium Pro 180MHz'de posta ve web sunucusu olarak çalıştırdım. Sadece iyi koştu. Anekdot kanıt hiçbir şey ifade etmiyor.
Robert C. Barth

C "görkemli" değil ama hızlı, ben aynı görevi yerine getirirken hemen hemen her zaman C # daha hızlı bilmek için yeterli C ve C # kodu yazdım. Bazı görevler için üst düzey dillerde geliştirilmesi daha uzun sürer, ancak hepsi iş için doğru aracı kullanmakla ilgilidir ve bazen C'dir.
Robert Gamble

1

Otomatik ve manuel arasındaki fark, daha üst düzey diller otomatikleştirilen soyutlamalardır. C / C ++ manuel olarak kontrol edilir ve işlenir, hata kontrol kodu bile bazen manuel bir iştir.

C ve C ++ da derlenmiş dillerdir, bu da her yerde iş yapanların hiçbiri olmadığı anlamına gelir, bu diller üzerinde çalıştığınız donanım için ince ayar yapılması gerekir, böylece ekstra bir gotcha katmanı eklenir. Her ne kadar C / C ++ derleyicileri tüm platformlarda daha yaygın hale geldikçe bu biraz yavaşlıyor. Platformlar arasında çapraz derlemeler yapabilirsiniz. Bu hala her yerde koşmak bir durum değil, temelde A derleyicisi B aynı kod farklı mimarisine karşı derlemek için talimat.

Alt satırdaki C dillerinin anlaşılması ya da gerekçelendirilmesi kolay değildir, bu nedenle bu dillere sistem dilleri denir. Bütün bu üst düzey soyutlama saçmalıklarından önce ortaya çıktılar. Bu yüzden ön uç web programlama için kullanılmazlar. Sadece göreve uygun değiller, geleneksel dil araçlarıyla çözülemeyen karmaşık sorunları çözmek için ortalamaları.

Bu yüzden (mikro mimariler, sürücüler, kuantum fiziği, AAA Oyunları, işletim sistemleri) gibi çılgın şeyler elde edersiniz C ve C ++ için çok uygun olan şeyler vardır. Hız ve sayı çatırdaması başlıca bölgelerdir.



1

Aşağıdakiler dahil birçok neden vardır:

  • Montaj diline derlenir.
  • Statik olarak yazılmıştır.
  • Çöp toplama yok.
  • Hata işleme yok.
  • Birçok programlama dili yeni özellikler ekler. C felsefesinin bir parçası, daha fazla özellik eklemek yerine işleri basit tutmaktır.

Nesne orionlu olmadığı için neden daha hızlı olmalı?
sb27

A) nesne yönelimli programlama çöp toplama ihtiyacı yaratır, B) nesne yönelimli programlama gibi büyük özellikler derleyiciye karmaşıklık katar,
Sapphire_Brick

A) Hayır. Bkz. C ++ veya Rust. B) Evet, ama aynı zamanda Derleyiciye yeni optimizasyon fırsatları da sunuyor.
sb27

A) Rust derleme zamanı çöp toplama vardır ve c ++ sınıflar için çöp toplama vardır, bu yüzden yıkıcılar vardır ,, B) optimize karmaşıklık hala karmaşıklık
Sapphire_Brick

A) Çöp toplama değildir, programınızı montaj B) Hayır yapsanız bile bellek yönetimi yapılmalıdır. Daha Fazla Soyutlama, iyileştiricinin daha iyi varsayımlar yapmasını sağlar.
sb27
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.