Программирование касания какао. KVO / KVC во внутренней петле очень медленный. Как мне ускорить процесс? - PullRequest
2 голосов
/ 20 июля 2009

Я стал большим поклонником KVO / KVC. Мне нравится, как она поддерживает мою архитектуру MVC в чистоте. Однако я не влюблен в огромный удар по производительности, который я испытываю, когда использую KVO во внутреннем цикле рендеринга приложения 3D-рендеринга, которое я разрабатываю, где сообщения будут запускаться с частотой 60 раз в секунду для каждого наблюдаемого объекта - возможно, сотен.

Какие советы и рекомендации по ускорению КВО? В частности, я наблюдаю скалярное значение - не объект - поэтому, возможно, завершение / развертывание убивает меня. Я также настраиваю и срываю наблюдение

[foo addObserver:bar forKeyPath:@"fooKey" options:0 context:NULL];
[foo removeObserver:bar forKeyPath:@"fooKey"];

во внутренней петле. Возможно, я беру за это удар.

Я действительно хочу сохранить огромную гибкость, которую предоставляет мне КВО. Кто-нибудь может помешать скорости?

Ура, Дуг

1 Ответ

4 голосов
/ 21 июля 2009

Диспетчеризация сообщений Objective-C и другие функции настроены и довольно быстро для того, что они предоставляют, но они все еще не приближаются к потенциалу настроенного C для вычислительных задач:

NSNumber *a = [NSNumber numberWithIntegerValue:(b.integerValue + c.integerValue)];

намного медленнее, чем:

NSInteger a = b + c;

и никто не делает математику для объектов в Objective-C по этой причине (хорошо, и синтаксис ужасен).

Сила Objective-C заключается в том, что у вас есть хорошая выразительная объектная система, основанная на сообщениях, где вы можете выбрасывать дорогие биты и использовать чистый C, когда вам это нужно. КВО - одна из самых дорогих вещей. Я люблю КВО, я использую его все время. Это вычислительно дорого, особенно если у вас много наблюдаемых объектов.

Внутренний цикл - это маленький кусочек кода, который вы запускаете снова и снова, и все, что там делается, будет выполняться снова и снова. Это место, где вы должны исключать функции ООП, если это необходимо, где вы не должны выделять память, где вы должны подумать о замене вызовов методов статическими встроенными функциями. Даже если вам каким-то образом удастся получить приемлемую производительность в цикле рендеринга, производительность будет намного ниже, чем если бы вы получили всю эту дорогостоящую логику уведомлений и рассылки.

Если вы действительно хотите продолжить работу с KVO, вот несколько вещей, которые вы можете попробовать сделать быстрее:

  1. Переключение с автоматического на ручной КВО на ваших объектах. Это может позволить вам уменьшить ложные уведомления
  2. Совокупные обновления: если ваши промежуточные значения за некоторый промежуток времени не релевантны, и вы можете отложить на некоторое время (например, следующий кадр анимации) не публиковать изменение, отметьте, что изменение необходимо опубликовать, и подождите чтобы отключить соответствующий таймер, вы можете избежать нескольких кратковременных промежуточных обновлений. Вы также можете использовать какой-нибудь прокси для агрегирования связанных изменений между несколькими объектами.
  3. Объединение наблюдаемых свойств: если у вас есть большое количество свойств в одном типе объектов, которые могут измениться, вам может быть лучше сделать одно свойство hasChanges для наблюдения и запросить у наблюдателя свойства.
...