Apple lanzó su nuevo lenguaje de programación Swift en WWDC14 . En la presentación, hicieron algunas comparaciones de rendimiento entre Objective-C y Python. La siguiente es una imagen de una de sus diapositivas, de una comparación de esos tres idiomas que realizan algún tipo de objeto complejo:
Hubo un gráfico aún más increíble sobre una comparación de rendimiento utilizando el algoritmo de cifrado RC4 .
Obviamente, esta es una charla de marketing, y no entraron en detalles sobre cómo se implementó esto en cada uno. Sin embargo, me dejo pensando:
- ¿Cómo puede un nuevo lenguaje de programación ser mucho más rápido?
- ¿Los resultados de Objective-C son causados por un mal compilador o hay algo menos eficiente en Objective-C que Swift?
- ¿Cómo explicaría un aumento del rendimiento del 40%? Entiendo que la recolección de basura / control de referencia automatizado puede producir una sobrecarga adicional, pero ¿tanto?
objective-c
comparison
apple
swift-language
Amarillo
fuente
fuente
Respuestas:
Primero, (IMO) comparar con Python es casi sin sentido. Solo la comparación con Objective-C es significativa.
Objective-C es un lenguaje lento. (Solo la parte C es rápida, pero eso se debe a que es C) Nunca ha sido extremadamente rápida. Fue lo suficientemente rápido para su propósito (el de Apple), y más rápido que sus versiones anteriores. Y fue lento porque ...
Objective-C garantiza que todos los métodos se envíen dinámicamente. No hay envío estático en absoluto. Eso hizo imposible optimizar aún más un programa Objective-C. Bueno, tal vez la tecnología JIT pueda ser de ayuda, pero AFAIK, Apple realmente odia las características de rendimiento impredecibles y la vida útil de los objetos. No creo que hayan adoptado nada de JIT. Swift no tiene esa garantía de envío dinámico a menos que coloque algún atributo especial para la compatibilidad de Objective-C.
GC o RC no importa aquí. Swift también está empleando RC principalmente. No hay GC, y tampoco lo hará a menos que haya un gran salto arquitectónico en la tecnología GC. (OMI, es para siempre) Creo que Swift tiene mucho más espacio para la optimización estática. Especialmente algoritmos de cifrado de bajo nivel, ya que generalmente se basan en grandes cálculos numéricos, y esta es una gran victoria para los idiomas de envío estático.
En realidad me sorprendió porque el 40% parece demasiado pequeño. Esperaba mucho más. De todos modos, esta es la versión inicial, y creo que la optimización no era la principal preocupación. ¡Swift ni siquiera tiene características completas! Lo harán mejor.
Actualizar
Algunos me siguen molestando para argumentar que la tecnología GC es superior. Aunque las cosas a continuación pueden ser discutibles, y solo mi opinión muy parcial, pero creo que tengo que decir para evitar este argumento innecesario.
Sé qué son los GC conservadores / de rastreo / generacionales / incrementales / paralelos / en tiempo real y cómo son diferentes. Creo que la mayoría de los lectores también lo saben. También estoy de acuerdo en que GC es muy bueno en algún campo, y también muestra un alto rendimiento en algunos casos.
De todos modos, sospecho que la afirmación del rendimiento de GC siempre es mejor que RC. La mayor parte de la sobrecarga de RC proviene de la operación de recuento de ref y bloqueo para proteger la variable de número de recuento de ref. Y la implementación de RC generalmente proporciona una forma de evitar las operaciones de conteo. En Objective-C, hay
__unsafe_unretained
y en Swift, (aunque todavía no está claro para mí)unowned
cosas. Si el costo de la operación de recuento de refutación no es aceptable, puede intentar excluirlos selectivamente utilizando la mecánica. Teóricamente, podemos simular un escenario de propiedad casi única mediante el uso de referencias no retenidas de manera muy agresiva para evitar la sobrecarga de RC. También espero que el compilador pueda eliminar automáticamente algunas operaciones obvias innecesarias de RC.A diferencia del sistema RC, AFAIK, la exclusión parcial de los tipos de referencia no es una opción en el sistema GC.
Sé que hay muchos gráficos y juegos lanzados que usan un sistema basado en GC, y también sé que la mayoría de ellos sufren por falta de determinismo. No solo por las características de rendimiento, sino también por la gestión de la vida útil del objeto. La unidad está escrita principalmente en C ++, pero la pequeña parte de C # causa todos los problemas de rendimiento extraños. Aplicaciones híbridas HTML y todavía sufren picos impredecibles en cualquier sistema. Usado ampliamente no significa que sea superior. Simplemente significa que es fácil y popular para las personas que no tienen muchas opciones.
Actualización 2
Nuevamente para evitar discusiones o discusiones innecesarias, agrego algunos detalles más.
@Asik proporcionó una opinión interesante sobre los picos de GC. Es por eso que podemos considerar el enfoque del tipo de valor en todas partes como una forma de optar por la exclusión de material de GC. Esto es bastante atractivo e incluso factible en algunos sistemas (enfoque puramente funcional, por ejemplo). Estoy de acuerdo en que esto es bueno en teoría. Pero en la práctica tiene varios problemas. El mayor problema es que la aplicación parcial de este truco no proporciona verdaderas características libres de picos.
Porque el problema de la latencia es siempre un problema de todo o nada . Si tiene un pico de cuadro durante 10 segundos (= 600 cuadros), obviamente todo el sistema está fallando. No se trata de qué tan bueno o peor. Es solo pasar o fallar. (o menos de 0.0001%) Entonces, ¿dónde está la fuente del pico de GC? Esa es una mala distribución de la carga del GC. Y eso se debe a que el GC es fundamentalmente indeterminista. Si hace basura, activará el GC y eventualmente se producirá un pico. Por supuesto, en el mundo ideal donde la carga de GC siempre será ideal, esto no sucederá, pero estoy viviendo en el mundo real en lugar del mundo ideal imaginario.
Luego, si desea evitar el pico, debe eliminar todos los tipos de referencia de todo el sistema. Pero es difícil, demente e incluso imposible debido a una parte inamovible como el sistema y la biblioteca .NET core. Solo usar un sistema que no sea GC es mucho más fácil .
A diferencia de GC, RC es fundamentalmente determinista, y no tiene que usar esta optimización loca (solo de tipo de valor puro) solo para evitar el pico. Lo que tiene que hacer es rastrear y optimizar la parte que causa el pico. En los sistemas RC, el pico es un problema de algoritmo local, pero en los sistemas GC, los picos son siempre un problema del sistema global.
Creo que mi respuesta se ha ido demasiado fuera de tema, y sobre todo solo la repetición de las discusiones existentes. Si realmente desea reclamar alguna superioridad / inferioridad / alternativa o cualquier otra cosa de GC / RC, hay muchas discusiones existentes en este sitio y StackOverflow, y puede continuar luchando allí.
fuente
Siendo 3.9 veces más rápido que Python, el lenguaje que constantemente pierde la mayoría de los puntos de referencia por un margen considerable (bueno, está a la par con Perl, Ruby y PHP; pero pierde con cualquier cosa estáticamente escrita), no hay nada de lo que uno deba jactarse.
El juego de puntos de referencia muestra programas de C ++ que son más de un orden de magnitud más rápido que los programas de Python en la mayoría de los casos. No es mucho mejor cuando se compara con Java, C # (en Mono), OCaml, Haskell e incluso Clojure, que no está estáticamente tipado.
Entonces, la verdadera pregunta es cómo es Objective-C solo 2.8 veces más rápido que python. Aparentemente, eligieron cuidadosamente el punto de referencia donde el despacho lento y completamente dinámico de ObjC duele mucho. Cualquier lenguaje escrito estáticamente debería poder hacerlo mejor. En la clasificación de objetos complejos hay muchas llamadas a métodos para comparar los objetos y la comparación real probablemente no fue muy compleja en sí misma. Entonces, si Swift aprovecha al menos algo de la información de tipo, puede mejorar fácilmente en las llamadas al método y no hay suficientes otras operaciones en las que ObjC podría ser mejor.
Por supuesto, como lo demuestra claramente el juego de puntos de referencia , el rendimiento relativo en diferentes tareas varía enormemente, por lo que un punto de referencia no es realmente representativo. Si tuvieran un punto de referencia donde tuviera una mayor ventaja, nos lo hubieran mostrado, por lo que en otras tareas probablemente no sea mejor o no tanto.
fuente
Objective-C despacha dinámicamente todas las llamadas a métodos.
Hipótesis: el punto de referencia utiliza la escritura estática para permitir que el compilador Swift levante la
compare
búsqueda del método fuera delsort
ciclo. Esto requiere una restricción de tipo estrecho que solo permite objetos complejos en la matriz, no subclases de complejo.(En Objective-C puede izar la búsqueda de métodos manualmente si realmente lo desea, llamando al soporte de tiempo de ejecución del lenguaje para buscar el puntero del método. Es mejor asegurarse de que todas las instancias en la matriz sean de la misma clase .)
Hipótesis: Swift optimiza las llamadas de conteo de referencias fuera del ciclo.
Hipótesis: el punto de referencia Swift utiliza una estructura compleja en lugar de un objeto Objective-C, por lo que las comparaciones de clasificación no necesitan despachos de métodos dinámicos (ya que no se pueden subclasificar) o trabajos de conteo de referencias (ya que es un tipo de valor).
(En Objective-C puede recurrir a C / C ++ para el rendimiento siempre que no implique objetos Objective-C, por ejemplo, ordenar una matriz C de estructuras).
fuente
Honestamente, a menos que publiquen la fuente para las pruebas que están utilizando, no confiaría en nada de lo que Apple tenga que decir sobre el tema. Recuerde, esta es la compañía que cambió de PPC a Intel debido a problemas de energía cuando 6 meses antes decían que Intel apestaba y en realidad incendiaba el conejito Intel en un comercial. Me gustaría ver pruebas irrefutables de que Swift es más rápido que ObjC en más categorías que solo ordenar.
Además, debe cuestionar las estadísticas que se publican en WWDC ya que tienen el olor del marketing por todas partes.
Dicho todo esto, no he realizado ninguna prueba entre swift y ObjC, pero por lo que sé, swift tiene sus propias extensiones IR LLVM y es posible que se realice una mayor optimización en tiempo de compilación que en ObjC.
Divulgación completa: estoy escribiendo un compilador Swift de código abierto ubicado en https://ind.ie/phoenix/
Si a alguien le gustaría ayudar a asegurarse de que Swift no solo esté disponible en el hardware de Apple, avíseme y con gusto lo incluiré.
fuente
Me he esforzado mucho a través del tutorial de Swift, y me parece que Swift es más realista (me hace pensar en Visual Basic) con menos 'objetivación' que Objective-C. Si hubieran tenido en cuenta C o C ++, supongo que este último habría ganado, ya que son aún más tiempo de compilación.
En este caso, supongo que Objective-C es víctima de su pureza orientada a objetos (y sobrecarga).
fuente
qsort
que permitirá la clasificación de objetos complejos; solo usa una devolución de llamada que comprende los objetos disponibles. Sospecho que falta C ++ porquestd::sort
avergonzaría a Swift. (Dado que es una plantilla, un compilador de C ++ puede optimizarlo en gran medida, hasta desenrollar el bucle.)