Estoy comparando dos tecnologías para llegar a una recomendación sobre cuál debería ser utilizada por una empresa. El código de la tecnología A se interpreta mientras que el código de la tecnología B se compila en código máquina. En mi comparación, afirmo que la tecnología B en general tendría un mejor rendimiento ya que no tiene la sobrecarga adicional del proceso de interpretación. También afirmo que, dado que un programa podría escribirse de muchas maneras, todavía es posible que un programa escrito en tecnología A supere a uno escrito en tecnología B.
Cuando presenté este informe para su revisión, el revisor declaró que no ofrecí una razón clara por la que, en general, la sobrecarga del proceso de interpretación sería lo suficientemente grande como para poder concluir que el rendimiento de la tecnología B sería mejor.
Entonces, mi pregunta es ¿podemos decir algo sobre el rendimiento de las tecnologías compiladas / interpretadas? Si podemos decir que compilado es generalmente más rápido que interpretado, ¿cómo podría convencer al revisor de mi punto?
Respuestas:
No.
En general, el desempeño de una implementación de lenguaje depende principalmente de la cantidad de dinero, recursos, mano de obra, investigación, ingeniería y desarrollo gastados en él.
Y específicamente, el rendimiento de un programa en particular depende principalmente de la cantidad de pensamiento puesto en sus algoritmos.
Hay algunos intérpretes muy rápidos y compiladores que generan código muy lento .
Por ejemplo, una de las razones por las que Forth sigue siendo popular es porque, en muchos casos, un programa Forth interpretado es más rápido que el programa C compilado equivalente, mientras que, al mismo tiempo, el programa de usuario escrito en Forth más el intérprete Forth escrito en C es más pequeño que el programa de usuario escrito en C.
fuente
Las generalizaciones y los escenarios específicos son literalmente opuestos.
Parece que te estás contradiciendo a ti mismo. Por un lado, desea hacer una declaración general sobre los idiomas interpretados y compilados. Pero, por otro lado, desea aplicar esa declaración general a un escenario concreto que involucra Tecnología A y Tecnología B.
Una vez que aplica algo a un escenario concreto, ya no se generaliza . Entonces, incluso si puede argumentar que los idiomas interpretados son más lentos en general , aún no está haciendo su punto. A tu revisor no le importan las generalizaciones. Estás haciendo un análisis de dos tecnologías muy específicas. Eso es literalmente lo contrario de generalizar.
fuente
Como regla general, un programa interpretado es aproximadamente 2x – 10x más lento que escribir el programa en el idioma anfitrión del intérprete, y los intérpretes para lenguajes más dinámicos son más lentos. Esto se debe a que el programa interpretado tiene que hacer todo el trabajo real, pero además tiene la sobrecarga de interpretación.
Dependiendo de la estructura del intérprete, puede haber diferencias muy significativas. Hay dos escuelas contradictorias de diseño de intérpretes: uno dice que los códigos de operación deben ser lo más pequeños posible para que puedan optimizarse más fácilmente, el otro dice que los códigos de operación deben ser lo más grandes posible para que podamos trabajar más dentro del intérprete. Cuando la estructura de su programa coincide con la filosofía del intérprete, los gastos generales se vuelven insignificantes.
Por ejemplo, Perl es un lenguaje interpretado orientado hacia la manipulación de texto. Un programa de Perl idiomático que realiza la manipulación de texto no será mucho más lento que un programa de C, e incluso puede superar el programa de C en algunos casos (posible porque Perl usa una representación de cadena diferente y tiene incorporadas varias optimizaciones relacionadas con texto e IO). Sin embargo, hacer cálculos numéricos en Perl será insoportablemente lento. Un incremento
++x
es una sola instrucción de ensamblaje, pero involucra múltiples recorridos y ramas de puntero para el intérprete de Perl. Recientemente porté un script Perl vinculado a la CPU a C ++, y obtuve una aceleración de 7x a 20x, dependiendo del nivel de optimización del compilador.Aquí es importante hablar de optimizaciones, ya que un intérprete optimizado y pulido puede superar razonablemente a un compilador ingenuo no optimizador. Como crear un compilador de optimización es difícil y requiere mucho esfuerzo, es poco probable que su "tecnología B" tenga este nivel de madurez.
(Nota: el sitio del juego Computer Language Benchmarks tiene una estructura confusa, pero una vez que llegue a la tabla de tiempos para un problema, notará que el rendimiento de varios idiomas está por todas partes; a menudo, no hay un límite de rendimiento claro entre soluciones compiladas e interpretadas. La parte más importante del sitio no son los resultados de los puntos de referencia, sino las discusiones sobre cuán difíciles son los puntos de referencia significativos).
Al elegir una tecnología, el rendimiento de un lenguaje en tiempo de ejecución en sí mismo es completamente irrelevante. Es más probable que sea importante que la tecnología cumpla con algunas restricciones de línea de base (nuestro presupuesto es $ x, debemos poder entregar antes de aaaa-mm-dd, debemos satisfacer varios requisitos no funcionales), y que tiene un menor costo total de propiedad (factorizando la productividad del desarrollador, costos de hardware, costos de oportunidad de negocio, riesgo de errores y limitaciones inesperadas en la tecnología, costos de mantenimiento, costos de capacitación y contratación, ...). Por ejemplo, en una industria donde el tiempo de comercialización es el factor más importante, la tecnología con la mejor productividad del desarrollador sería la mejor opción. Para una organización grande, la mantenibilidad y los costos a largo plazo pueden ser más interesantes.
fuente
Absolutamente puede decir algo sobre el rendimiento de las tecnologías compiladas / interpretadas. Pero primero, debe definir "rendimiento". Si está construyendo un sistema embebido computacionalmente simple, entonces el "rendimiento" probablemente se inclinará hacia el lado del uso de memoria de las cosas. Mientras que un sistema computacionalmente complejo que opera en grandes conjuntos de datos se encontraría definiendo "rendimiento" en el número de cálculos por unidad de tiempo, ya que la sobrecarga de memoria de JVM o .NET sería insignificante.
Una vez que decida qué es el "rendimiento", puede decir algo como "tendremos 50 mil millones de objetos en memoria en cualquier momento dado y techA interpretado agrega 8 bytes adicionales a cada objeto para la administración interna, lo que equivale a una sobrecarga de memoria de 400 GB" en comparación con techB que no agrega estos datos "
fuente
Esta es una pregunta técnica y ya obtuvo muchas buenas respuestas técnicas, pero me gustaría señalar un aspecto ligeramente diferente de su situación: el hecho de que no puede basar una decisión como "tecnología A o tecnología B" puramente por razones técnicas y / o de rendimiento.
Los aspectos técnicos de algo como esto son solo una pequeña parte de la decisión entre A y B. Hay docenas de otros factores a tener en cuenta:
Como puede ver, hay MUCHAS cosas a tener en cuenta al tomar tal decisión.
Sé que esto no responde específicamente a su pregunta, pero creo que brinda una visión más amplia de su situación y los detalles de tal decisión.
fuente
La evaluación parcial es un marco conceptual relevante para relacionar intérpretes y compiladores.
Los lenguajes de programación son especificaciones (escritas en algún informe, como R5RS o n1570 ). Son no el software, por lo que ni siquiera tiene sentido hablar de rendimiento . Pero algunos lenguajes de programación pueden tener varias implementaciones, incluidos intérpretes y compiladores .
Incluso en lenguajes compilados tradicionalmente (es decir, lenguajes cuyas implementaciones suelen ser compiladores) como C, algunas partes a menudo se interpretan. Por ejemplo, la cadena de control de formato de printf (definido en la norma C) es a menudo "interpretarse" (por la biblioteca estándar C , que tiene una
printf
función usando técnicas de argumentos variables) pero algunos compiladores (incluyendo GCC ) son capaces -en limitada específica casos- para optimizarlo y "compilarlo" en llamadas de nivel inferior.Y algunas implementaciones, incluso dentro de "intérpretes", están utilizando técnicas de compilación JIT (así que genere código de máquina en tiempo de ejecución ). Un buen ejemplo es luajit . Otras implementaciones (por ejemplo, Python, Ocaml, Java, Parrot, Lua) están traduciendo el código fuente en un código de bytes que luego se interpreta.
SBCL es un "compilador" de Common Lisp que traduce dinámicamente cada interacción REPL (y llamadas a
eval
etc.) en código de máquina. Entonces sientes que es un intérprete. La mayoría de las implementaciones de JavaScript en los navegadores (por ejemplo, v8 ) utilizan técnicas de compilación JIT.En otras palabras, la diferencia entre intérpretes y compiladores es muy difusa (en realidad hay un continuo entre ambos), y prácticamente hablando, la mayoría de las implementaciones de lenguaje de programación a menudo tienen una faceta de intérprete y compilador (al menos para el código de bytes).
Una implementación puede ser rápida o lenta independientemente del uso de la mayoría de las técnicas similares a "compilador" o "intérprete".
Algunos rasgos del lenguaje favorecen un enfoque de interpretación (y solo pueden compilarse eficientemente a través del análisis completo del programa ).
Para algunos tipos de problemas, vale la pena diseñar el software con algunos enfoques de metaprogramación y proporciona importantes aceleraciones. Podría imaginarse que, dada alguna entrada específica, su programa genera dinámicamente código especializado para procesarlo. Esto incluso es posible con C o C ++ (ya sea usando alguna biblioteca JIT o generando algún código C, compilándolo como un complemento que se carga dinámicamente).
Vea también esta pregunta relacionada sobre Python, y que
fuente
Para código como
A = A + B
, que puede compilar hasta una o dos instrucciones de máquina, cada una de las cuales toma un cierto número de ciclos. Ningún intérprete puede hacer lo mismo en ese número de ciclos por una simple razón.El intérprete también ejecuta un conjunto de instrucciones propio (llámelos códigos de bytes, códigos p, lenguaje intermedio, lo que sea). Cada vez que ve un código de bytes como ADD, tiene que buscarlo de alguna manera y bifurcarse al código que hace la adición.
La próxima vez que lo vea, tiene que repetir esa búsqueda, a menos que tenga una forma de recordar la búsqueda anterior. Si tiene una manera de recordar la búsqueda previa, ya no es lo que llamamos un "intérprete", sino más bien un compilador justo a tiempo, o JITter.
Por otra parte...
Para códigos como
callSomeFunction( ... some args ...)
, ¿cuántos ciclos se gastan entre ingresar ese código y abandonarlo? Todo depende de lo que ocurra adentrocallSomeFunction
. Podría ser unos pocos, y podría ser billones, incluso sicallSomeFunction
se compila en sí mismo. Si es mucho, no tiene sentido debatir el costo de interpretación de esa línea de código: el dinero está en otra parte.Recuerde que los idiomas interpretados tienen un valor propio, como no es necesario compilarlos. (La "compilación" de la sintaxis de superficie a los códigos de bytes lleva un tiempo trivial. Tome R o MATLAB, por ejemplo).
Además, se necesita flexibilidad para niveles inteligentes de programación. En Minsky's Society of Mind , Capítulo 6.4 B -Brains, hay programas A que tratan con el mundo, y hay programas B que tratan con programas A, y puede haber más niveles. Los programas que escriben y administran otros programas se pueden hacer más fácilmente en sistemas interpretativos.
En Lisp, puede escribir
(+ A B)
para agregar A y B, pero una vez que está escrito solo tiene la opción de ejecutarlo o no. También puede escribir(eval (list '+ 'A 'B))
qué construye el programa y luego lo ejecuta. Podría construir algo diferente.El tema del programa es otro programa . Esto es más fácil de escribir en un lenguaje interpretado (aunque, como señala Jörg, las versiones más nuevas de Lisp, mientras que tienen
eval
, compilan sobre la marcha, por lo que no tienen la penalización de velocidad de interpretación).fuente
eval
yapply
funciones, que son intérpretes.eval
no se interpreta. Y tampoco lo esapply
. Ciertamente hay implementaciones que contienen intérpretes, pero SBCL no.eval
que no se interprete ed . Es una interpretan er .Más o menos, depende, pero como regla general, el entorno compilado, ya sea a través de JIT o estáticamente compilado, será más rápido para muchas tareas intensivas en cómputo, suponiendo simplicidad en el mismo lenguaje.
Parte de la razón es que los idiomas interpretados necesitan tener un bucle de intérprete, que lee una instrucción, selecciona la acción apropiada para ejecutarla y la ejecuta. En el mejor de los casos, como interpretar el código de bytes de Python o Java (como lo hacía la antigua JVM), tenía una sobrecarga de pocas instrucciones y causaba estragos con el predictor de rama; sin el último, puede esperar grandes penalidades debido a predicciones erróneas. Incluso un JIT muy tonto debería acelerar esto significativamente.
Dicho esto, el lenguaje interpretado puede engañar. Por ejemplo, Matlab tiene rutinas optimizadas para la multiplicación de matrices y, con pocos cambios, puede ejecutar el código en la GPU (descargo de responsabilidad: trabajo para nVidia; cualquier opinión expresada aquí es mía y no representa la opinión de mi empleador). De esa manera, puede escribir código breve y potente de alto nivel sin preocuparse por los detalles: alguien se ocupó de ello y dedicó tiempo y recursos a optimizarlo en un lenguaje de bajo nivel. No hay nada heredado al respecto y no impide, por ejemplo, que Matlab JIT el código, pero a menudo no hay ninguna razón, ya que la sobrecarga de llamar a la rutina de alto nivel es mínima en comparación con el tiempo dedicado a las de bajo nivel.
TL; DR: los programas compilados tienen enormes beneficios de rendimiento sobre los interpretados (para comparar manzanas con manzanas, consulte PyPy Speed ). Sin embargo, la velocidad del ejecutable es solo una parte del problema y puede no contribuir mucho a la velocidad general (si el tiempo se pasa principalmente en las bibliotecas). También la implementación importa.
fuente
Su suposición está bien fundada, aunque es una suposición.
No voy a repasar las razones por las cuales el código compilado debería ser más rápido que el código interpretado: si sabe cómo funcionan las computadoras, eso será obvio. La diferencia puede ser de órdenes de magnitud para ciertos tipos de problemas. Si su revisor cuestiona seriamente ese caso general, no sabe de qué está hablando.
Sin embargo, donde pueden tener un punto es si la diferencia es significativa en el tipo de aplicación que está desarrollando. Si se trata principalmente de E / S o está llamando principalmente a bibliotecas compiladas y no tiene muchos cálculos, la sobrecarga del proceso de interpretación puede ser insignificante.
Pero el punto de mi publicación es este: como experto en TI, a menudo se le llamará para tomar decisiones rápidas basadas en un conocimiento general de cómo deberían funcionar las cosas. Hacer una prueba específica puede obtener una respuesta más precisa, pero costará mucho más y no lo hará llegar primero.
Pero de vez en cuando te atrapan. Me ha pasado a mi. Hace una buena suposición y luego descubre que no tuvo en cuenta la estupidez del mundo.
Pero no puedo explicar tan bien como mi dibujo animado favorito de Dilbert de todos los tiempos. Nada muestra mejor que esto los peligros de ser un asno inteligente.
TL; DR: deberías tener razón, pero revisa el mundo real por si acaso.
fuente
A menos que use algo un tanto exótico, su problema no será sobre el rendimiento de un lenguaje A interpretado y un lenguaje B compilado.
Porque si usted / su equipo conoce A y no B y escribe un código mucho mejor en A que en B, puede terminar teniendo un rendimiento mucho mejor en A que en B. Si tiene personas con experiencia en un idioma y el idioma / las bibliotecas pueden trabajo que necesita, manténgalo.
Aquí hay un enlace sobre expresiones regulares en varios idiomas; verá que las expresiones regulares se implementan mejor en algún idioma, incluso si se compilan o no: http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=regexdna
fuente
Creo que no es una buena idea hablar sobre el rendimiento de dos tecnologías solo por el hecho de que una se compila y la otra se interpreta. Como se indicó en otras respuestas, puede depender del área de aplicación (algunos lenguajes pueden estar optimizados para realizar algunas operaciones muy rápidamente y hacer otras cosas más lentamente), así como de la experiencia de las personas que están a punto de usar esa tecnología.
No creo que sea razonable esperar que obtendrá un aumento en el rendimiento si toma algunos codificadores de lenguaje interpretados excelentes y les da algo de tecnología con la que no están familiarizados; tal vez en teoría, este último PUEDE resultar en un mejor rendimiento, pero en realidad, sin las habilidades y experiencia necesarias, no utilizará todas las oportunidades de optimización.
De uno de los conocidos empleados de la compañía de Silicon Valley, también escuché que prefieren el lenguaje que es más simple de usar, ya que es más costoso y problemático pagar a algunos desarrolladores expertos para mantener un código complicado pero altamente optimizado que simplemente compre más plataformas para hacer frente a la implementación menos eficiente, de modo que también debe considerarse al elegir la tecnología.
fuente
Una vez tuve que hacer una declaración radical similar para justificar una gran decisión.
Primero, es posible que no quieran creerle a un ingeniero humilde, así que encontré algunas pruebas comparativas comparables y las cité. Hay muchos de ellos, de personas como Microsoft o de universidades de renombre. Y dirán cosas como: El método A es entre 3 y 10 veces más rápido que el método B, dependiendo de las variables X e Y.
En segundo lugar, es posible que desee ejecutar un punto de referencia propio, tal vez utilizando un fragmento representativo del código en cuestión o algo similar que ya tenga. Ejecútelo 1000 veces durante la noche para que realmente haya una diferencia apreciable.
En este punto, la diferencia (o falta de ella) entre A y B debe ser tan clara que solo tiene que presentarla. Por lo tanto, formatee los resultados claramente, con diagramas si es posible, indicando todos los supuestos y definiendo todos los datos utilizados.
fuente
Yo diría que cualquier lenguaje dinámico tiene una ventaja sobre los compilados estáticamente: "Optimizaciones de tiempo de ejecución"
Esa es una de las razones por las que Java puede ser más rápido que C ++
Sí, cargar un idioma escrito dinámicamente siempre tendrá el costo de la traducción y estará en desventaja. Pero una vez que se está ejecutando, el intérprete puede perfilar y mejorar las rutas de código frecuentes con información de tiempo de ejecución que los lenguajes estáticos nunca tendrán
NOTA: Bueno, Java es un lenguaje interpretado, no dinámico. Pero es un gran ejemplo de lo que puede acelerar con la información de tiempo de ejecución
fuente
Este sería mi enfoque:
En general, los intérpretes se compilan, por lo que cada tecnología interpretada no es más que una tecnología compilada si se mira en un nivel bajo. Por lo tanto, las tecnologías compiladas son más y con más posibilidades, nunca puede empeorar si es inteligente (que en general lo es). Depende de cuánta información hay disponible en el momento de la compilación y cuánta información disponible solo en tiempo de ejecución y de lo buenos que son los compiladores e intérpretes, pero en teoría siempre debería ser posible al menos igualar el rendimiento de cualquier intérprete con un compilador adecuado, solo porque los intérpretes son fabricados por compiladores. Sin embargo, que sea posible, no significa que sea el caso de sus técnicos A y B.
En la práctica, solo dígale al revisor sobre todos los puntos de referencia disponibles donde se comparan los sistemas compilados e interpretados. Luego, pídale que le sugiera un intérprete que supere su algoritmo optimizado de código de ensamblaje optimizado.
Tal vez debería agregarse, que cualquier declaración general de este tipo no ayuda en absoluto al comparar dos técnicos específicos A y B. Allí, la elección de A y B importa mucho, mucho más, que si se interpretan o compilan.
fuente