objective-c performance

Mecanismo de envío de mensajes de Objective C



objective-c performance (2)

Solo estoy mirando para jugar con Objective C (escribir aplicaciones de juguetes de iPhone) y tengo curiosidad sobre el mecanismo subyacente utilizado para enviar mensajes. Tengo una buena comprensión de cómo las funciones virtuales en C ++ se implementan generalmente y cuáles son los costos relativos a una llamada al método estático o no virtual, pero no tengo ningún fondo con Obj-C para saber cómo se envían los mensajes. Buscando alrededor Encontré this punto de referencia flexible y menciona que los mensajes en caché IMP son más rápidos que las llamadas a funciones virtuales, que a su vez son más rápidos que un mensaje de envío estándar.

No estoy tratando de optimizar nada, solo obtener una comprensión más profunda de cómo exactamente se envían los mensajes.

  • ¿Cómo se envían los mensajes de Obj-C?
  • ¿Cómo se almacenan los caché en los punteros de los métodos de instancia y puede (en general) decir leyendo el código si un mensaje se almacenará en caché?
  • ¿Los métodos de clase son esencialmente los mismos que una función C (o método de clase estático en C ++) o hay algo más para ellos?

Sé que algunas de estas preguntas pueden ser ''dependientes de la implementación'', pero solo hay una implementación que realmente cuenta.



¿Cómo se envían los mensajes de Obj-C?

Los mensajes de Objective-C se envían utilizando la función objc_msgSend() del tiempo de ejecución. Se muestra en los documentos de Apple , la función tiene al menos 2 argumentos:

  1. El objeto receptor
  2. El selector del mensaje
  3. [Una lista de variables de argumentos para el mensaje que se envía]

Las instancias de una clase tienen un puntero isa , que es un puntero a su objeto de clase. Los selectores de métodos en cada objeto se almacenan en una "tabla" en el objeto de clase, y la función objc_msgSend() sigue el puntero isa al objeto de clase, al buscar esta tabla, y verifica si el método está en la tabla para la clase. Si no puede encontrarlo, busca el método en la tabla de la superclase de la clase. Si no se encuentra, continúa hasta el árbol de objetos, hasta que encuentra el método o llega al objeto raíz ( NSObject ). En este punto, se lanza una excepción.

¿Cómo se almacenan los caché en los punteros de los métodos de instancia y puede (en general) decir leyendo el código si un mensaje se almacenará en caché?

De la guía de tiempo de ejecución Objective-C de Apple sobre Messaging :

Para acelerar el proceso de mensajería, el sistema de tiempo de ejecución almacena en caché los selectores y las direcciones de los métodos a medida que se utilizan. Hay una memoria caché separada para cada clase, y puede contener selectores para los métodos heredados, así como para los métodos definidos en la clase. Antes de buscar en las tablas de envío, la rutina de mensajes primero verifica la memoria caché de la clase del objeto receptor (bajo la teoría de que un método que se usó una vez probablemente se vuelva a utilizar). Si el selector de métodos está en la memoria caché, la mensajería es solo un poco más lenta que una llamada a función. Una vez que un programa ha estado funcionando lo suficiente como para "calentar" sus cachés, casi todos los mensajes que envía encuentran un método en caché. Los cachés crecen dinámicamente para acomodar nuevos mensajes a medida que se ejecuta el programa.

Como se indicó, el almacenamiento en caché comienza a ocurrir una vez que el programa se está ejecutando, y después de que el programa haya estado funcionando lo suficiente, la mayoría de las llamadas a métodos se ejecutarán a través del método almacenado en caché. Como también dice, el almacenamiento en caché ocurre cuando se usan los métodos, por lo que un mensaje solo se almacena en caché cuando se usa.

¿Los métodos de clase son esencialmente los mismos que una función C (o método de clase estático en C ++) o hay algo más para ellos?

Los objetos de clase manejan el envío de métodos de una manera similar a la de instancias de clases. Cada objeto de clase tiene un objeto que almacena sus propios métodos de clase , en un objeto llamado metaclass . El objeto de clase tiene su propio puntero isa a su objeto de metaclase, que a su vez tiene objetos de súper metaclase, de los que puede heredar objetos de clase. El envío del método a los métodos de clase es así:

  1. El sistema de envío sigue el puntero isa del objeto de clase al objeto metaclase
  2. La tabla de métodos del objeto metaclase se busca para el método de clase.
  3. Si no se encuentra, la búsqueda continúa a la superclase del objeto de metaclase, donde continúa la búsqueda.
  4. Este proceso se repite hasta que se encuentra el método, o hasta que llega a la metaclase raíz, y se lanza una excepción.