Lenguajes de programación
Los lenguajes de programación son los que nos permiten describir programas mediante estructuras de datos y algoritmos. Hay una gran cantidad de lenguajes de programación, cada uno enfocado a un objetivo y con sus pros y contras.
Aunque podemos agruparlos de muchas maneras, se clasifican principalmente en tres paradigmas:
- Imperativos. Describen mediante instrucciones cómo realizar una tarea. Los más conocidos son C y Fortran.
- Declarativos. Describen el problema declarando condiciones, proposiciones y restricciones. Aquí tenemos a Prolog y LISP.
- Orientados a objetos. Utiliza clases y objetos que interaccionan entre sí para diseñar aplicaciones. C++, Java y Python son algunos de ellos.
Los primeros son los más clásicos, empezando por el ensamblador, el de más bajo nivel, del que nos abstraen otros lenguajes de alto nivel; son muy eficientes. La programación declarativa no describe la solución, sino el problema; es más expresiva y será el programa intérprete el que se dedicará a encontrar la solución.
Por último, los lenguajes orientados a objetos, representados por Smalltalk, se han popularizado en los últimos años y, combinando la orientación a objetos con programación imperativa, podemos lograr un buen equilibrio entre eficiencia y abstracción.
Mis lenguajes orientados a objetos favoritos
C++
Descendiente directo de C. Rápido y estándar, de uso muy común, multiplataforma (incluyendo microcontroladores como Arduino) y con gran cantidad de bibliotecas. Es totalmente compilado: generamos un ejecutable para un procesador y un sistema operativo concreto.
Lo utilizo como el lenguaje de más bajo nivel orientado a objetos, a menudo con la biblioteca Qt o con llamadas al sistema de Linux. También es muy adecuado para programación paralela.
Java
Es un lenguaje orientado a objetos más puro. Originalmente creado para programar microcontroladores, su uso se ha extendido últimamente —demasiado en mi opinión—. Es el lenguaje de facto en programación para Android y el soporte de los applets de Internet.
Es semicompilado a bytecode y se compila en tiempo de ejecución (JIT, Just-In-Time), lo que debe prometer completa portabilidad, mayor eficiencia al generarse código en el momento preciso y ya enfocado a un procesador concreto, y más seguridad, a cambio de ejecutarse dentro de una máquina virtual (el famoso Java HotSpot) y consumir muchos más recursos.
C#
Este lenguaje es propio de Microsoft, orientado a la programación para Windows y el lenguaje por excelencia de la plataforma .NET Framework. Deriva de C++ y toma muchas características de Java (realmente se diseñó para hacer competencia a Java), y su punto fuerte es su gran optimización en Windows, además de su extensa biblioteca (.NET).
Al igual que Java, cuando generamos el programa obtenemos un lenguaje intermedio (MSIL, Microsoft Intermediate Language) similar al bytecode de Java. Microsoft también provee compiladores de C++ para MSIL, lo que permite compenetrar código C++ y C#.
Python
Un gran lenguaje, interpretado, no compilado. Por supuesto más lento en ejecución, pero mucho más rápido de escribir. Es muy útil para pequeñas aplicaciones en las que la velocidad no es un punto crítico: ¿Cuánto importa un segundo más ejecutando, si tardamos una hora menos en escribir el programa?
Tiene una sintaxis muy cómoda y una biblioteca bastante completa. Nos evita por completo preocuparnos de los tipos de datos, la gestión de memoria o los rangos —podemos sumar números de cientos de cifras sin problema—.
Comparamos los lenguajes
Para hacer esto escribí el problema de las N reinas con satisfacción de restricciones en estos cuatro lenguajes. En C++ tenemos clases plantilla, pero necesitamos gestionar la memoria de arrays a mano. Java y C# tienen una dificultad similar: más ágiles que C++. En cambio con Python no es necesario preocuparse de las clases plantilla ni de la declaración de tipos, tardé muy poco tiempo en transcribirlo.
Podéis descargar las implementaciones aquí (ejecutables para Windows y código fuente), junto a la tabla de resultados y un programa aparte en Python para que lo probéis por vuestra cuenta:
Podéis descargar las implementaciones aquí (ejecutables para Windows y código fuente), junto a la tabla de resultados y un programa aparte en Python para que lo probéis por vuestra cuenta:
>> Descargar queens_csp.zip <<
Este tipo de problemas, al ser de búsqueda con heurísticas, no siguen un orden de eficiencia en la práctica (aunque sabemos que es N! en el peor caso), por tanto, para cada implementación ejecuté el programa con tamaño 10, 20, 30...1000 y un tiempo límite de 60 segundos. Hemos calculado la eficiencia como el cociente del número de pasos entre el tiempo de ejecución (cada paso es un intento de asignación en el backtracking), con los siguientes resultados:
Eficiencia obtenida en un Core i7 @ 2,2 GHz con Windows 8. |
El número de pasos para resolver un problema depende del orden en que escojamos las variables —en nuestro caso, el mínimo de valores restantes— y el orden de asignación —se escoge arbitrariamente—. La eficiencia de C++ es más que aceptable: hablamos de que resolvió 49 ejecuciones en un total de 79 segundos, con casi un millón y medio de asignaciones. Java resolvió 58 problemas con más de 2 millones de asignaciones, pero tardó casi el cuádruple.
C# logró resultados muy parecidos a C++ pero sólo tardó un minuto. En el caso de Python, encontró 43 soluciones, pero cada paso fue más costoso para él. Por ello recalcamos que Python no es adecuado para problemas de computación intensiva, pero sí lo es para pequeñas aplicaciones y utilidades que requieran poco procesamiento.
Y entre C# y Java, podemos ver en la gráfica el salto que hay pese a la igualdad de tecnología (código intermedio y compilación JIT). Con lo cual creo que C# es mucho más conveniente si queremos desarrollar una aplicación sólo para Windows. Para otras plataformas existe el Proyecto Mono, pero de momento es mucho más lento que Java en Linux.
En el lado del uso de memoria, C# y Python consiguen un equilibrio muy bueno con unos pocos MB de RAM, mientras que Java puede disparar el uso de memoria a cientos de MB. C++ es el más liviano: un programa pequeño no pasa de algunos KB.
En el lado del uso de memoria, C# y Python consiguen un equilibrio muy bueno con unos pocos MB de RAM, mientras que Java puede disparar el uso de memoria a cientos de MB. C++ es el más liviano: un programa pequeño no pasa de algunos KB.
Java ofrece un buen equilibrio entre sencillez, velocidad y portabilidad, pero su potencia queda limitada respecto a otros competidores. No creo que sea la plataforma ideal en todos los casos sólo porque gestione automáticamente la memoria. A todo esto hay que sumar los fallos de seguridad que están viendo la luz en Java y el problema de que sea un lenguaje gratuito pero no libre.
Buenas Vikman!
ResponderEliminarEn primer lugar felicitarte por el blog. No se suele ver este tipo de gusto en los ETSIANOS (me siento como un profesor,no merezco vivir xD).
Y segundo quería hacerte un pequeño apunte y es que creo que a tu prueba le falta un detalle para estar totalmente completa. Creo que deberías añadir algunas lineas acerca de las condiciones de la prueba, como algún detalle de la maquina usada y de las versiones de los paquetes software usados, por si alguien quiere replicar la prueba eliminar posibles factores que puedan afectar a los resultados.
Tienes toda la razón, me dejo lo más importante :D He actualizado el ZIP con la tabla de datos y especificaciones de mi ordenador. También he puesto el programa que genera las tablas.
ResponderEliminar¡Gracias por tu comentario!