Будет ли приложение для iPhone использовать производительность, если я использую Objective-C для кода низкого уровня?

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

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

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

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

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

Ответ 1

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

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

Ответ 2

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

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

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

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

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

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

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

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

Отправка

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

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

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

Другие функции

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

Другие точки

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

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

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

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

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

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

Ответ 3

Очень сложно собрать "жесткие данные" для этого, чтобы не вводить в заблуждение.

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

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

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

Ответ 6

У меня есть пара тестов, которые я сделал на 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, а отправкой сообщения. Я хотел попробовать методForSelector и сразу вызвать методы, чтобы увидеть, насколько велика разница, но никогда не обходилась. Согласно показателям Майка Эша это чуть более чем в 5 раз быстрее.

Ответ 7

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

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

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

Ответ 8

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

"Я ищу жесткие данные, а не евангелизм". google - ваш лучший друг.

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

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