Molte di queste risposte forniscono validi motivi per cui C è o non è più veloce (in generale o in scenari specifici). È innegabile che:
- Molte altre lingue forniscono funzionalità automatiche che diamo per scontate. Il controllo dei limiti, il controllo del tipo di runtime e la gestione automatica della memoria, ad esempio, non sono gratuiti. Ce ne sono almeno alcuni costi associati a queste funzionalità, alle quali potremmo non pensare, o addirittura realizzare, durante la scrittura di codice che utilizza queste funzionalità.
- Il passaggio dall'origine alla macchina spesso non è diretto in altre lingue come in C.
- OTOH, dire che il codice C compilato viene eseguito più velocemente di altri codici scritti in altre lingue è una generalizzazione che non è sempre vera. I contro-esempi sono facili da trovare (o escogitare).
Ciò nonostante, c'è qualcos'altro che ho notato che, penso, influenza le prestazioni comparative della C rispetto a molte altre lingue più di qualsiasi altro fattore. Per dire:
Altre lingue spesso semplificano la scrittura di codice che viene eseguito più lentamente. Spesso è persino incoraggiato dalle filosofie progettuali del linguaggio. Corollario: un programmatore C ha maggiori probabilità di scrivere codice che non esegue operazioni non necessarie.
Ad esempio, considera un semplice programma Windows in cui viene creata una singola finestra principale. La versione AC popolerebbe una WNDCLASS[EX]
struttura a cui verrebbe passato RegisterClass[Ex]
, quindi chiamerebbe CreateWindow[Ex]
ed entrava in un ciclo di messaggi. Segue un codice altamente semplificato e abbreviato:
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);
}
Un programma equivalente in C # potrebbe essere solo una riga di codice:
Application.Run(new Form());
Questa riga di codice fornisce tutte le funzionalità di quasi 20 righe di codice C e aggiunge alcune cose che abbiamo lasciato fuori, come il controllo degli errori. La libreria più ricca e più completa (rispetto a quelle utilizzate in un tipico progetto C) ha fatto molto lavoro per noi, liberando il nostro tempo per scrivere molti più frammenti di codice che ci sembrano brevi ma comportano molti passaggi dietro le quinte.
Ma una ricca libreria che consente di gonfiare il codice in modo semplice e rapido non è proprio il mio punto di vista. Il mio punto è più evidente quando inizi a esaminare cosa succede effettivamente quando il nostro piccolo one-liner esegue effettivamente. Per un po 'di divertimento, abilita l'accesso ai sorgenti .NET in Visual Studio 2008 o versioni successive e passa alla semplice riga precedente sopra. Una delle piccole gemme divertenti che incontrerai è questo commento nel getter per 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();
}
Dieci volte . Le informazioni all'incirca equivalenti alla somma di ciò che è archiviato in una WNDCLASSEX
struttura e ciò a cui CreateWindowEx
viene passato viene recuperato dalla Control
classe dieci volte prima di essere archiviato in una WNDCLASSEX
struttura e trasmesso a RegisterClassEx
eCreateWindowEx
.
Tutto sommato, il numero di istruzioni eseguite per eseguire questo compito di base è di 2-3 ordini di grandezza in più in C # che in C. Parte di ciò è dovuta all'uso di una libreria ricca di funzionalità, che è necessariamente generalizzata, contro il nostro semplice codice C che fa esattamente ciò di cui abbiamo bisogno e niente di più. Ma in parte è dovuto al fatto che la natura modulare e orientata agli oggetti del framework .NET si presta a molte ripetizioni di esecuzione che spesso vengono evitate da un approccio procedurale.
Non sto cercando di scegliere C # o .NET Framework. Né sto dicendo che la modularizzazione, la generalizzazione, le funzionalità di libreria / linguaggio, OOP, ecc. Siano cose cattive . Ero solito fare la maggior parte del mio sviluppo in C, in seguito in C ++ e ultimamente in C #. Allo stesso modo, prima di C, ho usato principalmente il montaggio. E ad ogni passo "più alto" la mia lingua va, scrivo programmi migliori, più gestibili, più robusti in meno tempo. Tendono, tuttavia, a eseguire un po 'più lentamente.