¿Qué tipos de aplicaciones funcionarían mejor con lenguajes interpretados, qué tipos con lenguajes compilados y qué tipos deberían estar en el bare metal?

Los idiomas interpretados funcionan mejor cuando el cuello de botella no es la CPU. Un buen ejemplo de esto solía ser el desarrollo del lado del servidor antes de pasar a hipervisores y contenedores. Cuando eras el único proceso en la caja, y la caja pasaba la mayor parte del tiempo esperando solicitudes o llamando a la base de datos, realmente no importaba si el rendimiento de la CPU era subóptimo.

Los hipervisores rompieron esto porque ahora necesitamos compartir la CPU entre múltiples máquinas virtuales que se ejecutan en la misma máquina. Los idiomas ineficientes limitan la cantidad de máquinas virtuales que puede tener, pero también proporcionan un buen mecanismo para aprovechar múltiples núcleos en el hardware del servidor moderno … algo en lo que los idiomas con concurrencia de Global Interpreter Lock (python / ruby) son realmente malos.

Otro nicho donde brillan los lenguajes interpretados es donde el foco está en los ciclos de retroalimentación ajustados para el desarrollador, y no en el rendimiento. O donde es más importante poder configurar rápidamente módulos compilados en algo más coherente. La ciencia de datos es un buen ejemplo de esto, donde R y Python gobiernan el mundo. Además, las secuencias de comandos del juego donde Lua se usa muy fuertemente.

Los lenguajes compilados son excelentes cuando el rendimiento de la CPU es crítico. Los videojuegos AAA son el ejemplo canónico, pero los servicios web de alto rendimiento también tienden a compilarse. Facebook incluso llegó a compilar PHP para mejorar su rendimiento. Incluso la ciencia de datos tiende a ser una colección de módulos compilados junto con un lenguaje de script.

El ensamblaje / Metal desnudo es donde se necesita hasta la última onza de rendimiento de la CPU o donde el consumo de memoria debe mantenerse al mínimo absoluto y donde la capacidad de usar el código en múltiples arquitecturas no importa. Las primeras consolas de juegos se codificaban frecuentemente en conjunto, para que cada último ciclo funcionara de la manera más eficiente. De manera similar, la mayoría de los sistemas operativos tienen ciclos cerrados en los programadores que a menudo se optimizan manualmente para cada arquitectura.

Los intérpretes funcionan bien cuando utilizan grandes porciones de código compilado (bibliotecas C / C ++) y cuando el código está cambiando rápidamente (transmitido, auto modificable o editado), o en plataformas donde los compiladores no encajan – los intérpretes a menudo usan pseudocódigo que es más denso que (por ejemplo) el código de máquina RISC. El código más denso también puede hacer que los programas grandes se ejecuten tan rápido en un intérprete ya que hay menos espacio para moverse entre el almacén de respaldo y el caché de la CPU.

Javascript funciona bien en su entorno porque los navegadores web suelen estar vinculados a IO en lugar de estar vinculados a cómputo, aunque conozco personas que lo usan para todo. Python, R, Perl, etc. generalmente tienen bibliotecas C / C ++ haciendo su trabajo pesado.

Los lenguajes compilados generalmente tienen mejores optimizadores y le darán el código más rápido, y no tienen la sobrecarga de decodificación del núcleo del intérprete.

Los intérpretes también suelen usar la recolección de basura para administrar la memoria que hace que el comportamiento sea impredecible en aplicaciones en tiempo real y sin formato.

En estos días es más complicado ya que las máquinas son mucho más grandes y pueden adaptarse a los compiladores e intérpretes al mismo tiempo, por lo que la gente usa la compilación JiT en fragmentos de código para obtener la respuesta rápida de los intérpretes con la velocidad del código compilado. En ese entorno, los lenguajes que coinciden con el funcionamiento de la máquina subyacente son mejores, generalmente C (para X86, ARM, etc.), pero C es difícil de usar en FPGA y GPU, por lo que existe la oportunidad de construir un mejor intérprete / compilador para aquellos .

Comenzando al revés …

El metal desnudo (ensamblador o lenguaje de máquina) solo debe usarse cuando necesite extraer hasta el último rendimiento del hardware. Esto rara vez se necesita en estos días, ya que se pueden escribir compiladores de optimización que realizan la mayoría de las mismas optimizaciones para usted. En algunos casos, es posible que desee optimizar el software para que se ajuste a la memoria disponible en lugar de la velocidad, pero este es solo un aspecto diferente del mismo problema. Entonces, para obtener el código más rápido posible o el más estricto posible, apunte a Assembler.

Las TEND de código interpretado son más lentas que el código compilado, ya que necesitan realizar los mismos pasos que el compilador y el tiempo de ejecución. El código interpretado permite una fácil modificación y, en algunos casos, puede compilarse en un paso intermedio o incluso directamente en un ejecutable que puede mejorar el rendimiento posterior del tiempo de ejecución.

El código compilado se puede optimizar en gran medida durante la etapa de compilación. Básicamente, esto mueve la interpretación del archivo de programa a un paso separado distinto.

Me doy cuenta de que no he respondido su pregunta directamente hasta ahora, pero eso se debe a que el lenguaje en sí y la cadena de herramientas utilizada podrían ser más importantes que cómo funciona esa cadena de herramientas.

Los diferentes compiladores de C pueden producir código radicalmente diferente con diferentes atributos de rendimiento del mismo código fuente. Incluso el mismo compilador puede producir diferentes códigos dependiendo de las opciones.

Fortran es mucho más fácil escribir cálculos claros que C, por ejemplo, pero el código resultante generalmente será un poco más lento. Ambos son idiomas compilados, pero los idiomas tienen objetivos diferentes.

Un programa compilado estáticamente vinculado será más portátil en hardware diferente, pero similar. Un programa vinculado dinámicamente será más pequeño pero podría tomar más tiempo (o incluso no ejecutarse) dependiendo de qué tan bien escrito esté configurado el cargador de enlace dinámico.

Personalmente, tiendo a usar código interpretado para algo que debe escribirse rápidamente y que no me importa demasiado el rendimiento. El código compilado es para programas más grandes o de mejor rendimiento. Nunca necesito Assembler para nada de lo que estoy haciendo.

Entonces, ésta es la cuestión. En realidad no existe el lenguaje compilado o el lenguaje interpretado. Puede escribir un compilador o un intérprete para cualquier idioma. Ahora, es cierto que algunos idiomas están diseñados de tal manera que son más adecuados para ser utilizados con intérpretes en lugar de compiladores. En cuanto a qué tipo de aplicaciones son adecuadas para compilar vs interpretar, todo depende de compensaciones. Si algo tiene que implementarse rápidamente sin preocuparse mucho por la velocidad de ejecución, los idiomas que generalmente se usan con intérpretes son más útiles (ya que la codificación suele ser más rápida con estos idiomas). Si la velocidad de ejecución es importante, los idiomas que normalmente se compilan son más adecuados.