Objective C механизм отправки сообщений - PullRequest
59 голосов
/ 11 июня 2009

Я только начинаю играть с Objective C (написание игрушечных приложений для iPhone), и мне любопытно, какой механизм используется для отправки сообщений. Я хорошо понимаю, как виртуальные функции в C ++ обычно реализуются и каковы затраты по сравнению со статическим или не виртуальным вызовом метода, но я не знаю, как Obj-C знать, как отправляются сообщения. Просматривая все вокруг, я обнаружил этот потерянный эталонный тест, в котором упоминается, что кэшированные в IMP сообщения быстрее, чем вызовы виртуальных функций, что, в свою очередь, быстрее, чем отправка стандартного сообщения.

Я не пытаюсь что-то оптимизировать, просто получаю более глубокое понимание того, как именно отправляются сообщения.

  • Как отправляются сообщения Obj-C?
  • Как указатели на метод экземпляра кэшируются, и вы можете (в общем) узнать, прочитав код, будет ли кэшировано сообщение?
  • Методы класса по существу такие же, как функция C (или метод статического класса в C ++), или есть что-то еще для них?

Я знаю, что некоторые из этих вопросов могут быть «зависимыми от реализации», но есть только одна реализация, которая действительно имеет значение.

Ответы [ 2 ]

90 голосов
/ 11 июня 2009

Как отправляются сообщения Obj-C?

Сообщения Objective C отправляются с использованием функции objc_msgSend() среды выполнения. Показанная в Apple docs , функция принимает как минимум 2 аргумента:

  1. Принимающий объект
  2. Селектор сообщения
  3. [Переменный список аргументов отправляемого сообщения.]

Экземпляры класса имеют указатель isa, который является указателем на их объект класса. Селекторы методов в каждом объекте хранятся в «таблице» в объекте класса, а функция objc_msgSend() следует за указателем isa на объект класса, чтобы найти эту таблицу, и проверяет, находится ли метод в стол для класса. Если он не может его найти, он ищет метод в таблице суперкласса класса. Если он не найден, он продолжает подниматься по дереву объектов, пока не найдет метод или не достигнет корневого объекта (NSObject). В этот момент выдается исключение.

Каким образом указатели на метод экземпляра кэшируются, и вы можете (в общем) узнать, прочитав код, будет ли кэшировано сообщение?

Из руководства по времени выполнения Apple Objective-C для Сообщения :

Для ускорения процесса обмена сообщениями система времени выполнения кэширует селекторы и адреса методов по мере их использования. Для каждого класса имеется отдельный кэш, и он может содержать селекторы для унаследованных методов, а также для методов, определенных в классе. Перед поиском в таблицах диспетчеризации подпрограмма обмена сообщениями сначала проверяет кэш класса принимающего объекта (согласно теории, что метод, который использовался один раз, может быть использован снова). Если селектор метода находится в кеше, обмен сообщениями только немного медленнее, чем вызов функции. Когда программа работает достаточно долго, чтобы «разогреть» свои кеши, почти все отправляемые ею сообщения находят кешированный метод. Кэши динамически растут для размещения новых сообщений во время работы программы.

Как уже говорилось, кэширование начинает происходить после запуска программы, и после того, как программа проработала достаточно долго, большинство вызовов метода будет проходить через кэшированный метод. Как также говорится, кэширование происходит при использовании методов, поэтому сообщение кэшируется только при его использовании.

Методы класса по сути такие же, как функция C (или метод статического класса в C ++), или есть что-то еще для них?

Объекты класса обрабатывают отправку метода аналогично экземплярам классов. Каждый объект класса имеет объект, который хранит свои собственные методы class в объекте с именем metaclass. Объект класса имеет собственный указатель isa на свой объект метакласса, который в свою очередь имеет объекты суперметакласса, от которых он может наследовать объекты класса. Отправка метода в методы класса выглядит так:

  1. Система диспетчеризации следует за указателем isa объекта класса на объект метакласса
  2. В таблице методов объекта метакласса ищется метод класса.
  3. Если не найден, поиск продолжается до суперкласса объекта метакласса, где поиск продолжается.
  4. Этот процесс повторяется до тех пор, пока метод не будет найден или пока он не попадет в корневой метакласс, и не будет выдано исключение.
19 голосов
/ 13 марта 2010

Я также написал инструкцию по инструкции objc_msgSend () на x86_64 в своем блоге, если кто-то хочет углубиться:

http://www.friday.com/bbum/2009/12/18/objc_msgsend-part-1-the-road-map/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...