Удастся ли моему приложению iPhone снизить производительность, если я использую Objective-C для низкоуровневого кода? - PullRequest
68 голосов
/ 29 мая 2009

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

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

Существуют ли какие-либо достоверные данные, сравнивающие Objective-C с C ++, в частности, на iPhone, но, возможно, только на рабочем столе Mac, для оценки производительности в различных аспектах языка? Я очень знаком с этой статьей, сравнивающей C и Objective-C , но это более сложный вопрос сравнения двух объектно-ориентированных языков друг с другом.

Например, действительно ли поиск в V ++ в C ++ быстрее, чем в Obj-C сообщении? Насколько быстрее? Потоки, полиморфизм, сортировка и т. Д. Прежде чем приступить к поиску создания проекта с дублированными объектными моделями и различным тестовым кодом, я хочу знать, сделал ли кто-нибудь это и каковы были результаты. Этот тип тестирования и сравнения сам по себе является проектом и может занять значительное время. Возможно, это не один проект, а два и только результаты можно сравнить.

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

Ответы [ 8 ]

57 голосов
/ 30 мая 2009

У Майка Эша есть некоторые жесткие цифры для выполнения различных вызовов методов Objective-C по сравнению с C и C ++ в его посте "Сравнение производительности общих операций" . Также этот пост Savoy Software - интересное чтение, когда речь заходит о настройке производительности приложения для iPhone с помощью Objective-C ++.

Я склонен предпочесть чистый, описательный синтаксис Objective-C, а не Objective-C ++, и я не обнаружил, что сам язык является источником моих узких мест в производительности. Я даже склоняюсь к тому, чтобы делать вещи, которые, как я знаю, приносят в жертву небольшую производительность, если они делают мой код более понятным.

55 голосов
/ 11 апреля 2012

Да, хорошо написанный C ++ значительно быстрее. Если вы пишете программы, критичные к производительности, и ваш C ++ не так быстр, как C (или в пределах нескольких процентов), то что-то не так. Если ваша реализация ObjC работает так же быстро, как C, то что-то обычно неправильно - то есть программа, вероятно, плохой пример ObjC OOD, потому что она, вероятно, использует некоторые «грязные» трюки, чтобы подняться ниже уровня абстракции. работающих внутри, таких как прямой доступ к ивару.

Сравнение Майка Эша очень вводит в заблуждение - я никогда не рекомендовал бы подход для сравнения времени выполнения написанных вами программ или рекомендовал бы сравнивать C с C ++ и ObjC. Представленные результаты получены из теста с оптимизацией компилятора отключен . Программа, скомпилированная с отключенными оптимизациями, редко используется при измерении времени выполнения. Рассматривать его как эталон, сравнивающий C ++ с Objective-C, некорректно. В тесте также сравниваются отдельные функции, а не целые, оптимизированные для реального мира реализации - отдельные функции в обоих языках комбинируются по-разному. Это далеко от реалистичного эталона производительности для оптимизированных реализаций. Примеры: При оптимизации , включенной , кэш IMP работает так же медленно, как и вызовы виртуальных функций. Статическая диспетчеризация (в отличие от динамической диспетчеризации, например, с использованием virtual) и вызовы известных типов C ++ (где динамическая диспетчеризация может быть обойдена) могут быть агрессивно оптимизированы. Этот процесс называется девиртуализацией, и при его использовании функция-член, которая объявляется virtual, может даже быть inline d. В случае теста Майка Эша, когда много вызовов выполняются для функций-членов, которые были объявлены virtual и имеют пустые тела: эти вызовы оптимизируются на полностью , когда тип известен, потому что компилятор видит реализация и в состоянии определить динамическую диспетчеризацию не требуется. Компилятор также может исключать вызовы malloc в оптимизированных сборках (в пользу стекового хранилища). Таким образом, включение оптимизации компилятора в любом из C, C ++ или Objective-C может привести к значительным различиям во времени выполнения.

Это не значит, что представленные результаты совершенно бесполезны. Вы можете получить некоторую полезную информацию о внешних API, если вы хотите определить, существуют ли измеримые различия между временем, которое они проводят в pthread_create или +[NSObject alloc] на одной платформе или архитектуре по сравнению с другой. Конечно, эти два примера будут использовать оптимизированные реализации в вашем тесте (если только вы не разрабатываете их). Но для сравнения одного языка с другим в программах, которые вы компилируете ... представленные результаты бесполезны с отключенной оптимизацией.

Создание объекта

Рассмотрим также создание объектов в ObjC - каждый объект размещается динамически (например, в куче). В C ++ объекты могут создаваться в стеке (например, примерно так же быстро, как создание структуры C и во многих случаях вызывать простую функцию), в куче или в качестве элементов абстрактных типов данных. Каждый раз, когда вы выделяете и освобождаете (например, через malloc / free), вы можете ввести блокировку. Когда вы создаете структуру C или C ++ в стеке, блокировка не требуется (хотя внутренние элементы могут использовать выделения кучи), и она часто стоит всего несколько инструкций или несколько инструкций плюс вызов функции.

Кроме того, объекты ObjC являются экземплярами с подсчетом ссылок. Фактическая потребность в объекте, который должен быть std::shared_ptr в критичном к производительности C ++, встречается очень редко. В C ++ нет необходимости или нежелательности делать каждый экземпляр общим экземпляром с подсчетом ссылок. У вас гораздо больше контроля над владением и временем жизни с C ++.

Массивы и коллекции

Массивы и многие коллекции в C и C ++ также используют строго типизированные контейнеры и непрерывную память. Поскольку адрес членов следующего элемента часто известен, оптимизатор может сделать гораздо больше, и у вас есть отличная локальность кеша и памяти. С ObjC это далеко от реальности для стандартных объектов (например, NSObject).

Отправка товара

Что касается методов, многие реализации C ++ используют мало виртуальных / динамических вызовов, особенно в высокооптимизированных программах. Это статические вызовы методов и корм для оптимизаторов.

В методах ObjC каждый вызов метода (отправка сообщения objc) является динамическим и, следовательно, является брандмауэром для оптимизатора. В конечном итоге это приводит ко многим ограничениям или неудобствам в отношении того, что вы можете и не можете делать, чтобы поддерживать производительность на минимуме при написании критически важного для производительности ObjC. Это может привести к более крупным методам, кешированию IMP, частому использованию C.

Некоторые приложения реального времени не могут использовать любые сообщения ObjC в своих путях рендеринга. None - аудио рендеринг является хорошим примером этого. ObjC рассылка просто не предназначена для целей реального времени; Распределение и блокировки могут происходить за кулисами при обмене сообщениями объектов, что делает сложность / время обмена сообщениями objc настолько непредсказуемым, что при воспроизведении аудио может быть превышен его срок.

Другие особенности

C ++ также предоставляет реализации обобщений / шаблонов для многих своих библиотек. Они очень хорошо оптимизируют. Они безопасны для типов, и много шаблонов и оптимизаций могут быть сделаны с помощью шаблонов (считайте, что это полиморфизм, оптимизация и специализация, которая имеет место при компиляции). C ++ добавляет несколько функций, которые просто не доступны или не сравнимы в строгом ObjC. Попытки напрямую сравнивать языки, объекты и библиотеки, которые сильно отличаются друг от друга, не так полезны - это очень небольшое подмножество реальных реализаций. Лучше расширить вопрос до библиотеки / фреймворка или реальной программы, учитывая многие аспекты проектирования и реализации.

Другие очки

Символы C и C ++ могут быть легко удалены и оптимизированы на различных этапах сборки (разбор, удаление мертвого кода, встраивание и раннее встраивание, а также оптимизация времени соединения). Преимущества этого включают уменьшение размера двоичных файлов, сокращение времени запуска / загрузки, снижение потребления памяти и т. Д. Для одного приложения это может быть не таким уж большим делом; но если вы повторно используете много кода, и вы должны это сделать, то ваши совместно используемые библиотеки могут добавить много ненужного веса программе, если реализован ObjC - если вы не готовы перепрыгнуть через некоторые пламенные обручи. Поэтому масштабируемость и повторное использование также являются факторами в средних / крупных проектах и ​​в группах, где повторное использование является высоким.

Включенные библиотеки

Разработчики библиотеки ObjC также оптимизируют среду, поэтому разработчики библиотеки могут использовать некоторые функции языка и среды, чтобы предлагать оптимизированные реализации. Хотя при написании оптимизированной программы в чистом ObjC существуют некоторые довольно существенные ограничения, в Какао существуют некоторые высокооптимизированные реализации. Это одна из сильных сторон Cocoa, хотя стандартная библиотека C ++ (то, что некоторые люди называют STL) тоже не лишена. Какао работает на гораздо более высоком уровне абстракции, чем C ++ - если вы плохо знаете, что делаете (или должны делать), работа ближе к металлу может стоить вам . Обратиться к хорошей реализации библиотеки, если вы не являетесь экспертом в какой-либо области, это хорошая вещь, если вы действительно не готовы учиться. Кроме того, среда какао ограничена; Вы можете найти реализации / оптимизации, которые лучше используют ОС.

Если вы пишете оптимизированные программы и имеете опыт работы в C ++ и ObjC, реализации clean C ++ часто будут в два раза быстрее или быстрее, чем clean ObjC (да, Вы можете сравнить с какао). Если вы знаете, как оптимизировать, вы часто можете делать абстракции общего назначения более высокого уровня. Хотя некоторые оптимизированные реализации C ++ будут такими же быстрыми или медленными, как у Cocoa (например, моя первоначальная попытка ввода-вывода файлов была медленнее, чем у Cocoa - главным образом потому, что реализация C ++ инициализирует свою память).

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

Большинство моих критических для производительности путей я сохраняю как C ++, но также признаю, что ObjC также является очень хорошим решением для некоторых проблем и что есть несколько очень хороших доступных библиотек.

31 голосов
/ 29 мая 2009

Очень сложно собрать «точные данные», чтобы не вводить их в заблуждение.

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

Мое чувство (так как я много программировал на обоих языках, в основном для больших проектов): чтобы максимизировать производительность Objective-C, он должен быть написан очень близко к C. В то время как с C ++ можно гораздо больше использовать язык без потери производительности по сравнению с C.

Какой из них лучше? Я не знаю. Для чистой производительности C ++ всегда будет иметь преимущество. Но стиль ООП Objective-C определенно имеет свои достоинства. Я определенно думаю, что с ним легче поддерживать разумную архитектуру.

7 голосов
/ 25 ноября 2010

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

В Objective C вы также можете писать код на C ++, так что в большинстве случаев будет проще кодировать в Objective C, и если вы найдете что-то неэффективное, то вы можете начать писать его версия на c ++ и проверка того, помогает ли это (C ++ имеет тенденцию к лучшей оптимизации во время компиляции). Цель C будет проще в использовании, если в ней также написаны интерфейсы API, с которыми вы взаимодействуете, плюс вам может показаться, что стиль ООП проще или более гибок.

В конце концов, вам следует использовать то, что вы знаете, вы можете написать безопасный и надежный код, и если вы найдете область, которая требует особого внимания со стороны другого языка, то вы можете переключиться на это. X-Code позволяет компилировать оба в одном проекте.

3 голосов
/ 06 февраля 2011

У меня есть пара тестов, которые я провел на iPhone 3G почти 2 года назад, в те дни не было никаких документов или жестких цифр. Не уверен, насколько они действительны, но исходный код опубликован и прикреплен.

Это не очень обширный тест, меня больше всего интересовал NSArray vs C Array для итерации большого количества объектов.

http://memo.tv/nsarray_vs_c_array_performance_comparison

http://memo.tv/nsarray_vs_c_array_performance_comparison_part_ii_makeobjectsperformselector

Вы можете видеть, что массив C намного быстрее на высоких итерациях. С тех пор я понял, что узким местом, вероятно, является не итерация NSArray, а отправка сообщения. Я хотел попробовать methodForSelector и вызвать методы напрямую, чтобы увидеть, насколько велика будет разница, но так и не нашел ее. По оценкам Майка Эша, он чуть более чем в 5 раз быстрее.

3 голосов
/ 08 января 2010

У меня нет точных данных для Objective C, но у меня есть хорошее место для поиска C ++.

C ++ начинался как C с Classes согласно Бьярну Страуструпу в его размышлениях о ранних годах C ++ (http://www2.research.att.com/~bs/hopl2.pdf),), так что C ++ можно рассматривать (как Objective C) как подталкивание C к своим пределам для ориентации объекта.

Каковы эти ограничения? В период 1994-1997 годов многие исследователи выяснили, что объектная ориентация обходится дорого из-за динамического связывания, например, когда функции C ++ помечены как виртуальные и могут / не могут быть дочерние классы, которые переопределяют эти функции. (В Java и C # все функции предполагают, что ctors по своей сути являются виртуальными, и с этим мало что можно поделать.) В статье «Изучение методов девиртуализации для компилятора Java Just-in-Time», проведенной исследователями из IBM Research Tokyo, они контрастируют с методами, используемыми для решения этой проблемы, в том числе от Урца Хольцле и Джеральда Айгнера. Urz Hölzle, в отдельной статье с Karel Driesen, показал, что в среднем 5,7% времени в программах на C ++ (и до ~ 50%) тратится на вызов виртуальных функций (например, vtables + thunks). Позже он работал с некоторыми исследователями Smalltalk в том, что привело к созданию виртуальной машины Java HotSpot для решения этих проблем в ОО. Некоторые из этих функций перенесены в C ++ (например, «защищены» и обработка исключений).

Как я уже говорил, C ++ имеет статическую типизацию, а Objective C - типизированная по типу утки. Разница в производительности при выполнении (но не в строках кода), вероятно, является результатом этой разницы.

1 голос
/ 07 сентября 2012

В этом исследовании говорится, что для того, чтобы действительно добиться производительности в игре с интенсивным использованием ЦП, вы должны использовать C. Связанная статья содержит проект XCode, который вы можете запустить.

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

Я имею в виду, было бы совершенно глупо видеть position = [[Vector3 alloc] init] ;. Вы просто запрашиваете снижение производительности, если используете счетчик ссылок на базовые объекты, такие как вектор позиции.

0 голосов
/ 09 июня 2013

да. C ++ господствует в производительности / выразительности / компромиссе ресурсов.

«Я ищу точные данные, а не евангелизацию». Google - твой лучший друг.

  1. obj-c nsstring заменяется на c ++ инженерами Apple для повышения производительности. в устройствах с ограниченными ресурсами только c ++ обрезает его как основной язык MAINSTREAM. NSString stringWithFormat медленно

  2. obj-c oop абстракция деконструируется в процедурные c-структуры для производительности, в противном случае порядок MAGNITUDE медленнее, чем в Java! автору также известно о кешировании сообщений - пока нет. так что моделирование множества маленьких объектов игроков / врагов выполняется в oop с помощью c ++ или других, множество процедурных структур с простой оболочкой OOP вокруг него с помощью obj-c. может быть одна парадигма, которая приравнивает процедурное + объектно-ориентированное программирование = obj-c. http://ejourneyman.wordpress.com/2008/04/23/writing-a-ray-tracer-for-cocoa-objective-c/

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