Muchas de estas respuestas dan razones válidas de por qué C es, o no es, más rápido (ya sea en general o en escenarios específicos). Es innegable que:
- Muchos otros idiomas proporcionan funciones automáticas que damos por sentado. La verificación de límites, la verificación de tipos en tiempo de ejecución y la administración automática de memoria, por ejemplo, no son gratuitas. Hay al menos algún costo asociado con estas características, que quizás no pensemos, ni siquiera comprendamos, al escribir código que use estas funciones.
- El paso de la fuente a la máquina a menudo no es tan directo en otros idiomas como lo es en C.
- OTOH, decir que el código C compilado se ejecuta más rápido que otro código escrito en otros lenguajes es una generalización que no siempre es cierta. Los contraejemplos son fáciles de encontrar (o inventar).
A pesar de todo esto, hay algo más que he notado que, creo, afecta el rendimiento comparativo de C frente a muchos otros lenguajes más que cualquier otro factor. Esto es:
Otros idiomas a menudo facilitan la escritura de código que se ejecuta más lentamente. A menudo, incluso es alentado por las filosofías de diseño del lenguaje. Corolario: es más probable que un programador en C escriba código que no realice operaciones innecesarias.
Como ejemplo, considere un programa simple de Windows en el que se crea una sola ventana principal. La versión AC llenaría una WNDCLASS[EX]
estructura a la que se pasaría RegisterClass[Ex]
, luego llamaría CreateWindow[Ex]
e ingresaría un bucle de mensajes. El código altamente simplificado y abreviado sigue:
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 programa equivalente en C # podría ser solo una línea de código:
Application.Run(new Form());
Esta línea de código proporciona toda la funcionalidad que hicieron casi 20 líneas de código C y agrega algunas cosas que omitimos, como la verificación de errores. La biblioteca más rica y completa (en comparación con las que se usan en un proyecto típico de C) hizo mucho trabajo por nosotros, liberando nuestro tiempo para escribir muchos fragmentos más de código que nos parecen cortos pero implican muchos pasos detrás de escena.
Pero una biblioteca rica que permita una expansión de código fácil y rápida no es realmente mi punto. Mi punto es más evidente cuando comienzas a examinar lo que realmente sucede cuando nuestro pequeño one-liner realmente se ejecuta. Para divertirse en algún momento, habilite el acceso a la fuente .NET en Visual Studio 2008 o superior, y pase a la línea simple de arriba. Una de las pequeñas gemas divertidas que encontrarás es este comentario en el captador de 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();
}
Diez veces . La información más o menos equivalente a la suma de lo que está almacenado en una WNDCLASSEX
estructura y lo que se pasa CreateWindowEx
se recupera de la Control
clase diez veces antes de almacenarse en una WNDCLASSEX
estructura y se pasa a RegisterClassEx
y CreateWindowEx
.
En general, el número de instrucciones ejecutadas para realizar esta tarea tan básica es de 2 a 3 órdenes de magnitud más en C # que en C. Parte de esto se debe al uso de una biblioteca rica en características, que necesariamente está generalizada, en comparación con nuestro código C simple que hace exactamente lo que necesitamos y nada más. Pero parte de esto se debe al hecho de que la naturaleza modular y orientada a objetos de .NET framework se presta a una gran cantidad de repeticiones de ejecución que a menudo se evita mediante un enfoque de procedimiento.
No estoy tratando de elegir C # o el marco .NET. Tampoco estoy diciendo que la modularización, la generalización, las funciones de biblioteca / lenguaje, OOP, etc. son cosas malas . Solía hacer la mayor parte de mi desarrollo en C, más tarde en C ++, y más recientemente en C #. Del mismo modo, antes de C, usé principalmente ensamblaje. Y con cada paso "más alto" mi lenguaje va, escribo mejores, más mantenibles, programas más robustos en menos tiempo. Sin embargo, tienden a ejecutarse un poco más lentamente.