¿Cómo puede Swift ser mucho más rápido que Objective-C en estas comparaciones?

115

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:

ingrese la descripción de la imagen aquí

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:

  1. ¿Cómo puede un nuevo lenguaje de programación ser mucho más rápido?
  2. ¿Los resultados de Objective-C son causados ​​por un mal compilador o hay algo menos eficiente en Objective-C que Swift?
  3. ¿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?
Amarillo
fuente
13
@MathewFoscarini Obj-C va al ensamblador, pero tiene un costoso mecanismo de envío de mensajes de objeto. Para la mayoría de los trabajos de GUI eso no importa, pero para ordenarlo importa mucho.
Donal Fellows
17
La comparación con Python es el verdadero rascador de cabeza aquí.
asthasr
99
@syrion marketing, y el lenguaje parece tomar prestado de la sintaxis de Python (al igual que Golang). Están tratando de decir "oye, desarrolladores de Python, puedes escribir algo no demasiado extraño en la Mac y hacer que sea MUCHO más rápido, incluso más rápido que el Objetivo C del que nunca te
44
@MichaelT Lo entiendo, pero sigue siendo extraño. Cualquiera que sepa algo sobre lenguajes se dará cuenta de que Python, como lenguaje interpretado, simplemente no va a estar en el mismo estadio que Objective-C u otros lenguajes compilados (para la mayoría de las tareas). Usarlo como punto de referencia es extraño.
asthasr
77
Probablemente significan el tiempo que lleva escribir el código ...
Lukas Eder

Respuestas:

62

Primero, (IMO) comparar con Python es casi sin sentido. Solo la comparación con Objective-C es significativa.

  • ¿Cómo puede un nuevo lenguaje de programación ser mucho más rápido?

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 ...

  • ¿El Objective-C resulta de un mal compilador o hay algo menos eficiente en Objective-C que Swift?

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.

  • ¿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?

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_unretainedy en Swift, (aunque todavía no está claro para mí) unownedcosas. 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í.

Eonil
fuente
44
La recolección de basura, especialmente generacional, suele ser significativamente más rápida que el recuento de referencia.
Jan Hudec
99
@ JanHudec Su significativamente más rápido simplemente no tiene sentido en el campo de gráficos en tiempo real. Es por eso que menciono que se requiere un gran salto en GC. El GC generacional ni siquiera está cerca de estar libre de picos, tanto en teoría como en la práctica.
Eonil
55
Más rápido y sin picos son categorías completamente ortogonales. Los recolectores de basura generacionales son más rápidos . Están no pico libre.
Jan Hudec
44
Lo que estás hablando es el rendimiento . Más rápido siempre ha sido un término vago, y puede significar cualquier cosa por el contexto. Si desea discutir sobre el significado de los términos, debe usar un término más preciso en lugar de más rápido, especialmente teniendo en cuenta el contexto actual: gráficos en tiempo real.
Eonil
11
@ JanHudec: en dispositivos móviles, o cualquier dispositivo con recursos limitados, GC no es significativamente más rápido y, de hecho, es una parte importante del problema.
Mason Wheeler
72

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.

Jan Hudec
fuente
13
No entiendo bien el punto de esta respuesta. ¿Estás respondiendo "cómo es rápido más rápido" al decir "los puntos de referencia son defectuosos"? ¿Es ese el punto que estás haciendo? No veo cómo eso responde a lo que se preguntaba.
Bryan Oakley
15
@BryanOakley: No creo que los puntos de referencia tengan fallas, pero la posibilidad de que eligieron el punto de referencia donde Swift fue más rápido ciertamente debe considerarse.
Jan Hudec
23
Es posible que la respuesta a "¿Cómo es más rápido Swift?" podría ser "No es, en realidad", @BryanOakley; esa es la esencia que obtengo de la respuesta de Jan. "Mentiras, malditas mentiras y estadísticas", después de todo.
Josh Caswell
44
Hace un tiempo, comparamos Codename One con iOS y nuestra implementación de Java fue mucho más rápida que Objective-C codenameone.com/blog/… Jan es correcto, el despacho dinámico es realmente lento, si los mejoraron incluso un poco, algunos puntos de referencia lo harán Muestra una gran mejora. Si mejoran ARC incluso por una fracción (gracias a un mejor análisis de código) pueden deshacerse de una cantidad ridícula de complejidad. Cuanto más restringido sea el idioma, más puede hacer el compilador para optimizar (ver Java) y Swift agrega restricciones.
Shai Almog
77
La respuesta de Jan es una respuesta perfecta a la Q1 y probablemente a la Q2. Cuando vi los puntos de referencia en un evento de marketing como la nota clave, pensé: "Guau, solo 1,3 veces en el mejor de los casos seleccionados. ¿Cuál será el resultado promedio? ¿0.3x?"
Amin Negm-Awad
5

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 comparebúsqueda del método fuera del sortciclo. 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).

Jerry101
fuente
3

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é.

greg.casamento
fuente
2
esto se lee más como un comentario desvergonzado, vea Cómo responder
mosquito
2
¿Esta mejor ahora? :)
greg.casamento
0

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).

Negro pintado
fuente
13
Hacer un punto de referencia de "clasificación de objetos complejos" sería un poco difícil en un lenguaje como C que no tiene una implementación nativa de objetos. Dado que la audiencia para esta charla probablemente era 100% programadores de Objective-C, compararlo con un lenguaje como C ++ tampoco tiene mucho sentido. El punto de rapidez no es "¡hey, este es el mejor lenguaje de todos!" sino más bien "oye, esto es más rápido que el lenguaje que estás usando ahora para el desarrollo de OSX / iOS".
Bryan Oakley
10
C tiene un perfectamente fino qsortque permitirá la clasificación de objetos complejos; solo usa una devolución de llamada que comprende los objetos disponibles. Sospecho que falta C ++ porque std::sortavergonzaría a Swift. (Dado que es una plantilla, un compilador de C ++ puede optimizarlo en gran medida, hasta desenrollar el bucle.)
MSalters
@MSalters: Estoy totalmente de acuerdo con usted. Tanto C como C ++ tienen capacidades para superar a Swift. ¿Sería posible obtener la prueba ejecutada? Estoy más que dispuesto a ejecutar el mismo punto de referencia con Swift, Objective-C, C ++ y C.
Painted Black
@BryanOakley también, "¡Este lenguaje requiere menos corchetes!"
Nick Bedford
1
Esta respuesta no retiene agua y es terriblemente engañosa. OO no es realmente lento, de hecho, los sistemas más rápidos que encontrará serán C ++, Java y C # y el estilo de programación (muy OO o no) tendrá muy poco que ver con las velocidades resultantes a menos que realmente tenga código malo
Bill K