tutorial programación programacion objective lenguaje introduccion historia español entre diferencias c++ iphone objective-c performance optimization

c++ - programación - objective-c tutorial



¿Recibirá mi aplicación de iPhone un golpe de rendimiento si uso Objective-C para código de bajo nivel? (8)

Al programar una aplicación intensiva de CPU o intensiva de GPU en el iPhone u otro hardware portátil, debe tomar decisiones algorítmicas acertadas para acelerar el código.

Pero incluso las mejores opciones de algoritmo pueden ser lentas si el idioma que está utilizando tiene un rendimiento inferior al de otro.

¿Hay datos concretos que comparen Objective-C con C ++, específicamente en el iPhone, pero tal vez solo en el escritorio de Mac, para el desempeño de varios aspectos de lenguaje similares? Estoy muy familiarizado con este artículo que compara C y Objective-C , pero esta es una pregunta más amplia de comparar dos lenguajes orientados a objetos entre sí.

Por ejemplo, ¿es una búsqueda de C ++ vtable realmente más rápida que un mensaje de Obj-C? ¿Cuanto más rápido? Enhebrado, polimorfismo, clasificación, etc. Antes de ir a una misión para construir un proyecto con modelos de objetos duplicados y varios códigos de prueba, quiero saber si alguien ya lo ha hecho y cuáles fueron los resultados. Este tipo de prueba y comparación es un proyecto en sí mismo y puede llevar una cantidad considerable de tiempo. Tal vez este no es un proyecto, pero dos y solo los resultados se pueden comparar.

Estoy buscando datos duros , no evangelismo. Como muchos de ustedes, amo y odio ambos idiomas por varias razones. Además, si hay alguien buscando activamente lo mismo, sería interesante lanzar un código para ver los resultados finales, y estoy seguro de que otros también ayudarían. Supongo que ambos tienen puntos fuertes y débiles, mi objetivo es descubrir qué son exactamente para evitarlos / explotarlos en escenarios del mundo real.


Es muy difícil recopilar "datos duros" para esto que no es un error.

El mayor problema al hacer una comparación de característica a característica como usted sugiere es que los dos idiomas fomentan estilos de codificación muy diferentes. Objective-C es un lenguaje dinámico con tipado de pato, donde el uso típico de C ++ es estático. El mismo problema de arquitectura orientada a objetos probablemente tendría soluciones ideales muy diferentes usando C ++ u Objective-C.

Mi sensación (ya que he programado mucho en ambos idiomas, principalmente en grandes proyectos): para maximizar el rendimiento de Objective-C, tiene que escribirse muy cerca de C. Considerando que con C ++, es posible hacer un uso mucho mayor del idioma sin cualquier penalización de rendimiento en comparación con C.

¿Cuál es mejor? No lo sé. Para un rendimiento puro, C ++ siempre tendrá la ventaja. Pero el estilo OOP de Objective-C definitivamente tiene sus méritos. Definitivamente creo que es más fácil mantener una arquitectura sensata con él.


Esto realmente no es algo que pueda responderse en general, ya que realmente depende de cómo use las características del lenguaje. Ambos idiomas tendrán cosas en las que son rápidos, cosas en las que son lentos y cosas que a veces son rápidas y, a veces, lentas. Realmente depende de lo que uses y cómo lo uses. La única manera de estar seguro es perfilar su código.

En Objective C también puede escribir código c ++, por lo que podría ser más fácil codificar en el objetivo C en su mayor parte, y si encuentra algo que no funciona bien en él, puede probar una versión de c ++ de ello y ver si eso ayuda (C ++ tiende a optimizar mejor en tiempo de compilación). El objetivo C será más fácil de usar si las API con las que está interactuando también están escritas en él, además, puede encontrar que su estilo de OOP es más fácil o más flexible.

Al final, debe ir con lo que sabe que puede escribir un código seguro y sólido y si encuentra un área que necesita atención especial del otro idioma, puede cambiar a eso. X-Code le permite compilar ambos en el mismo proyecto.


Mike Ash tiene algunos números duros para la ejecución de varias llamadas al método Objective-C versus C y C ++ en su publicación "Comparaciones de rendimiento de operaciones comunes" . Además, esta publicación de Savoy Software es una lectura interesante cuando se trata de ajustar el rendimiento de una aplicación de iPhone utilizando Objective-C ++.

Tiendo a preferir la sintaxis descriptiva y limpia de Objective-C sobre Objective-C ++, y no he encontrado que el lenguaje en sí sea la fuente de mis cuellos de botella de rendimiento. Incluso tiendo a hacer cosas que sé sacrificar un poco de rendimiento si hacen que mi código sea mucho más fácil de mantener.


No tengo datos duros para Objective C, pero sí tengo un buen lugar para buscar C ++.

C ++ comenzó como C con Clases según Bjarne Stroustroup en su reflexión sobre los primeros años de C ++ ( http://www2.research.att.com/~bs/hopl2.pdf ), por lo que se puede pensar en C ++ (como Objective C ) como empujando C a sus límites para la orientación del objeto.

¿Cuáles son esos límites? En el período de 1994-1997, muchos investigadores descubrieron que la orientación a objetos tenía un costo debido a la vinculación dinámica, por ejemplo, cuando las funciones de C ++ se marcan como virtuales y pueden existir / no clases de niños que anulen estas funciones. (En Java y C #, todas las funciones esperan que los ctors sean intrínsecamente virtuales, y no hay mucho que pueda hacer al respecto). En "Un estudio de las técnicas de virtualización para un compilador Just-In-Time de Java" de investigadores de IBM Research Tokyo, contrastan las técnicas usadas para lidiar con esto, incluyendo uno de Urz Hölzle y Gerald Aigner. Urz Hölzle, en un artículo separado con Karel Driesen, había demostrado que, en promedio, el 5,7% del tiempo en programas C ++ (y hasta ~ 50%) se gastó en llamadas a funciones virtuales (por ejemplo, vtables + thunks). Más tarde trabajó con algunos resecachers de Smalltalk en lo que terminó como Java HotSpot VM para resolver estos problemas en OO. Algunas de estas características se están transfiriendo a C ++ (por ejemplo, ''protegido'' y manejo de excepciones).

Como mencioné, C ++ está tipeado estático donde Objective C es pato tipado. La diferencia de rendimiento en la ejecución (pero no en las líneas de código) probablemente sea el resultado de esta diferencia.


Sí, bien escrito C ++ es considerablemente más rápido. Si está escribiendo programas de rendimiento crítico y su C ++ no es tan rápido como C (o dentro de un pequeño porcentaje), algo anda mal. Si su implementación de ObjC es tan rápida como C, entonces algo suele ser incorrecto, es decir, es probable que el programa sea un mal ejemplo de ObjC OOD porque probablemente usa algunos trucos "sucios" para pasar debajo de la capa de abstracción dentro de la cual opera, como ivar accede.

La ''comparación'' de Mike Ash es muy engañosa: nunca recomendaría el enfoque para comparar los tiempos de ejecución de los programas que ha escrito, ni lo recomendaría para comparar C vs C ++ versus ObjC. Los resultados presentados se proporcionan a partir de una prueba con optimizaciones del compilador deshabilitadas . Un programa compilado con optimizaciones desactivadas rara vez es relevante cuando se miden los tiempos de ejecución. Para verlo como un punto de referencia que compara C ++ contra Objective-C es defectuoso. La prueba también compara las características individuales, en lugar de implementaciones enteras optimizadas en el mundo real: las características individuales se combinan de maneras muy diferentes en ambos idiomas. Esto dista mucho de ser un punto de referencia de rendimiento realista para implementaciones optimizadas. Ejemplos: con las optimizaciones habilitadas , la memoria caché IMP es tan lenta como las llamadas a funciones virtuales. El despacho estático (a diferencia del despacho dinámico, por ejemplo, el uso de virtual ) y las llamadas a tipos conocidos de C ++ (donde se puede eludir el despacho dinámico) pueden optimizarse de manera agresiva. Este proceso se denomina desvirtualización, y cuando se usa, una función miembro que se declara virtual puede estar incluso en inline d. En el caso de la prueba de Mike Ash donde se realizan muchas llamadas a funciones miembro que se han declarado virtual y tienen cuerpos vacíos: estas llamadas se optimizan completamente cuando se conoce el tipo porque el compilador ve la implementación y es capaz de determinar el despacho dinámico es innecesario El compilador también puede eliminar llamadas a malloc en compilaciones optimizadas (favoreciendo el almacenamiento de la pila). Por lo tanto, habilitar las optimizaciones del compilador en cualquiera de C, C ++ o Objective-C puede producir diferencias dramáticas en los tiempos de ejecución.

Eso no quiere decir que los resultados presentados sean completamente inútiles. Puede obtener información útil sobre API externas si desea determinar si existen diferencias medibles entre los tiempos que pasan en pthread_create o +[NSObject alloc] en una plataforma o arquitectura frente a otra. Por supuesto, estos dos ejemplos utilizarán implementaciones optimizadas en su prueba (a menos que las desarrolle). Pero para comparar un idioma con otro en los programas que compila ... los resultados presentados son inútiles con las optimizaciones desactivadas.

Creación de Objetos

Considere también la creación de objetos en ObjC: cada objeto se asigna dinámicamente (por ejemplo, en el montón). Con C ++, los objetos se pueden crear en la pila (por ejemplo, aproximadamente tan rápido como crear una estructura C y llamar a una función simple en muchos casos), en el montón, o como elementos de tipos de datos abstractos. Cada vez que asigna y libera (por ejemplo, a través de malloc / free), puede introducir un bloqueo. Cuando crea una estructura C o un objeto C ++ en la pila, no se requiere bloqueo (aunque los miembros del interior pueden usar asignaciones de pila) y a menudo cuesta solo unas pocas instrucciones o unas pocas instrucciones además de una llamada a función.

Además, los objetos ObjC son instancias contadas de referencia. La necesidad real de que un objeto sea std::shared_ptr en C ++ crítico para el rendimiento es muy rara. No es necesario ni deseable en C ++ hacer que cada instancia sea una instancia compartida de referencia contada. Usted tiene mucho más control sobre la propiedad y la duración con C ++.

Arrays y colecciones

Las matrices y muchas colecciones en C y C ++ también usan contenedores fuertemente tipados y memoria contigua. Dado que a menudo se conoce la dirección de los miembros del siguiente elemento, el optimizador puede hacer mucho más, y usted tiene una gran ubicación de caché y memoria. Con ObjC, eso está lejos de la realidad para los objetos estándar (por ejemplo, NSObject ).

Envío

En cuanto a los métodos, muchas implementaciones de C ++ utilizan pocas llamadas virtuales / dinámicas, particularmente en programas altamente optimizados. Estas son llamadas a métodos estáticos y forraje para los optimizadores.

Con los métodos ObjC, cada llamada a método (envío de mensaje objc) es dinámica y, en consecuencia, es un cortafuegos para el optimizador. En última instancia, eso genera muchas restricciones o inconvenientes con respecto a lo que puede y no puede hacer para mantener el rendimiento al mínimo al escribir ObjC de rendimiento crítico. Esto puede resultar en métodos más grandes, el almacenamiento en caché de IMP, el uso frecuente de C.

Algunas aplicaciones en tiempo real no pueden usar ningún mensaje ObjC en sus rutas de procesamiento. Ninguno - la reproducción de audio es un buen ejemplo de esto. El envío de ObjC simplemente no está diseñado para propósitos de tiempo real; Las asignaciones y bloqueos pueden ocurrir detrás de las escenas cuando se envían mensajes a los objetos, lo que hace que la complejidad / tiempo de la mensajería objc sea lo suficientemente impredecible para que la reproducción de audio pueda perder su fecha límite.

Otras características

C ++ también proporciona implementaciones de genéricos / plantillas para muchas de sus bibliotecas. Estos se optimizan muy bien. Son seguros, y se pueden realizar muchas optimizaciones y optimizaciones con plantillas (considérenlo polimorfismo, optimización y especialización que se lleva a cabo en la compilación). C ++ agrega varias características que simplemente no están disponibles o son comparables en ObjC estricto. Tratar de comparar directamente langs, objetos y bibliotecas que son muy diferentes no es tan útil; es un subconjunto muy pequeño de realizaciones reales. Es mejor expandir la pregunta a una biblioteca / marco o programa real, considerando muchos aspectos de diseño e implementación.

Otros puntos

Los símbolos C y C ++ pueden eliminarse y optimizarse más fácilmente en varias etapas de la compilación (eliminación, eliminación de código muerto, alineación inicial y inicial, así como Optimización de tiempo de enlace). Los beneficios de esto incluyen tamaños binarios reducidos, tiempos de lanzamiento / carga reducidos, consumo de memoria reducido, etc. Para una sola aplicación, eso puede no ser tan importante; pero si reutiliza una gran cantidad de código, y debería hacerlo, entonces sus bibliotecas compartidas podrían agregar mucho peso innecesario al programa, si se implementa ObjC, a menos que esté preparado para pasar por alto algunos aros llameantes. Por lo tanto, la escalabilidad y la reutilización también son factores en proyectos medianos y grandes, y en grupos donde la reutilización es alta.

Bibliotecas incluidas

Los implementadores de la biblioteca ObjC también optimizan para el entorno, por lo que los implementadores de la biblioteca pueden hacer uso de algunas características del idioma y del entorno para ofrecer implementaciones optimizadas. Aunque existen algunas restricciones bastante importantes al escribir un programa optimizado en ObjC puro, existen algunas implementaciones altamente optimizadas en Cocoa. Este es uno de los puntos fuertes de Cocoa, aunque la biblioteca estándar de C ++ (lo que algunas personas llaman STL) tampoco se queda atrás. Cocoa opera a un nivel de abstracción mucho más alto que C ++: si no sabes muy bien lo que estás haciendo (o debería estar haciendo), operar más cerca del metal realmente te puede costar . Volver a una buena implementación de la biblioteca si no eres un experto en algún dominio es algo bueno, a menos que estés realmente preparado para aprender. Además, los ambientes de Cocoa son limitados; puede encontrar implementaciones / optimizaciones que hacen un mejor uso del sistema operativo.

Si está escribiendo programas optimizados y tiene experiencia haciéndolo tanto en C ++ como en ObjC, las implementaciones limpias de C ++ a menudo serán dos veces más rápidas o más rápidas que ObjC limpio (sí, puede compararlo con Cocoa). Si sabe cómo optimizar, a menudo puede hacerlo mejor que las abstracciones de propósito general de mayor nivel. Aunque algunas implementaciones optimizadas de C ++ serán tan rápidas o más lentas que las de Cocoa (por ejemplo, mi intento inicial de E / S de archivos fue más lento que el de Cocoa, principalmente porque la implementación de C ++ inicializa su memoria).

Mucho se reduce a las características del idioma con las que está familiarizado. Yo uso ambos langs, ambos tienen diferentes fortalezas y modelos / patrones. Se complementan bastante bien, y hay grandes bibliotecas para ambos. Si está implementando un programa complejo y crítico para el rendimiento, el uso correcto de las características y bibliotecas de C ++ le dará mucho más control y ventajas significativas para la optimización, de modo que en las manos correctas, "varias veces más rápido" es una buena expectativa predeterminada ( no espere ganar siempre, o sin algún trabajo, sin embargo). Recuerde, lleva años entender C ++ lo suficientemente bien como para llegar realmente a ese punto.

Mantengo la mayoría de mis rutas críticas de rendimiento como C ++, pero también reconozco que ObjC también es una muy buena solución para algunos problemas, y que hay algunas bibliotecas muy buenas disponibles.


Tengo un par de pruebas que hice en un iPhone 3G hace casi 2 años, no había documentación ni números duros en esos días. No estoy seguro de cuán válidos siguen siendo, pero el código fuente está publicado y adjunto.

Esta no es una prueba muy extensa, estaba principalmente interesado en NSArray vs C Array para iterar una gran cantidad de objetos.

http://memo.tv/nsarray_vs_c_array_performance_comparison

http://memo.tv/nsarray_vs_c_array_performance_comparison_part_ii_makeobjectsperformselector

Puedes ver que C Array es mucho más rápido en iteraciones altas. Desde entonces me he dado cuenta de que el cuello de botella probablemente no sea la iteración del NSArray sino el envío del mensaje. Quería probar methodForSelector y llamar los métodos directamente para ver qué tan grande sería la diferencia, pero nunca me di cuenta. Según los puntos de referencia de Mike Ash, es un poco más de 5 veces más rápido.


sí. c ++ reina suprema en rendimiento / expresividad / compensación de recursos.

"Estoy buscando datos duros, no evangelismo". Google es tu mejor amigo.

  1. obj-c nsstring se intercambia con c ++ por los desarrolladores de Apple para el rendimiento. en dispositivos con recursos limitados, solo c ++ lo corta como un MAINSTREAM oop language. NSString stringWithFormat es lento

  2. obj-c oop abstraction se deconstruye en estructuras-c basadas en procedimientos para el rendimiento, de lo contrario, ¡una orden MAGNITUDE más lenta que java! el autor también conoce el almacenamiento en caché de mensajes, pero no pasa. así que modelar muchos objetos pequeños de jugadores / enemigos se hace en oop con c ++ o bien, muchas estructuras procedurales con un envoltorio OOP simple a su alrededor con obj-c. puede haber un paradigma que iguale la programación procedimental + orientada a objetos = obj-c. http://ejourneyman.wordpress.com/2008/04/23/writing-a-ray-tracer-for-cocoa-objective-c/


Este estudio dice que para obtener realmente el rendimiento en un juego intensivo de CPU, debe usar C. El artículo vinculado se completa con un proyecto de XCode que puede ejecutar.

Creo que la conclusión es: Use Objective-C donde debe interactuar con las funciones del iPhone (después de todo, poner trampolines en todas partes no puede ser bueno para nadie ), pero cuando se trata de bucles, cosas como clases de objetos vectoriales, o intensivas Array Access, se adhiere a C ++ STL o C arrays para obtener un buen rendimiento.

Quiero decir que sería totalmente tonto ver position = [[Vector3 alloc] init] ; . Solo pides un golpe de rendimiento si usas recuentos de referencias en objetos básicos como un vector de posición.