Как Swift может быть намного быстрее, чем Objective-C в этих сравнениях?

115

Apple представила свой новый язык программирования Swift на WWDC14 . В презентации они провели сравнение производительности Objective-C и Python. Ниже приведено изображение одного из их слайдов, сравнение этих трех языков, выполняющих некоторую сложную сортировку объектов:

введите описание изображения здесь

Был еще более невероятный график сравнения производительности с использованием алгоритма шифрования RC4 .

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

  1. Как новый язык программирования может быть намного быстрее?
  2. Результаты Objective-C вызваны плохим компилятором или есть что-то менее эффективное в Objective-C, чем Swift?
  3. Как бы вы объяснили увеличение производительности на 40%? Я понимаю, что сборка мусора / автоматизированное управление ссылками может привести к дополнительным издержкам, но это много?
желтый
источник
13
@MathewFoscarini Obj-C идет на ассемблер, но у него есть дорогой механизм отправки объектных сообщений. Для большинства графических интерфейсов это не имеет значения, но для сортировки это очень важно.
Donal Fellows
17
Сравнение с Python - это настоящий головокружительный удар.
asthasr
9
@Syrion маркетинг, и язык, кажется, заимствует из синтаксиса Python (так же, как Голанг). Они пытаются сказать: «Привет, разработчики Python, вы можете написать что-то не слишком постороннее для Mac, и сделать это НАСТОЛЬКО быстрее, даже быстрее, чем Objective C, с которым вы никогда не
4
@MichaelT Я понимаю, но это все еще странно. Любой, кто знает что-либо о языках, поймет, что Python, как интерпретируемый язык, просто не будет находиться в той же области, что и Objective-C или другие скомпилированные языки (для большинства задач). Использование его в качестве эталона странно.
asthasr
7
Они, вероятно, имеют в виду время, которое требуется для написания кода ...
Лукас Эдер

Ответы:

62

Во-первых, (IMO) сравнивать с Python практически бессмысленно. Только сравнение с Objective-C имеет смысл.

  • Как новый язык программирования может быть намного быстрее?

Objective-C - медленный язык. (Только партия C быстрая, но это потому, что это C) Она никогда не была очень быстрой. Это было достаточно быстро для их (Apple) цели и быстрее, чем их старые версии. И это было медленно, потому что ...

  • Является ли Objective-C результатом плохого компилятора или есть что-то менее эффективное в Objective-C, чем Swift?

Objective-C гарантирует, что каждый метод будет динамически отправлен. Нет статической отправки вообще. Это сделало невозможным дальнейшую оптимизацию программы Objective-C. Ну, может быть, технология JIT может помочь, но AFAIK, Apple действительно ненавидит непредсказуемые характеристики производительности и срок службы объекта. Я не думаю, что они приняли какие-либо вещи JIT. Swift не имеет такой гарантии динамической отправки, если вы не добавили какой-либо специальный атрибут для совместимости с Objective-C.

  • Как бы вы объяснили увеличение производительности на 40%? Я понимаю, что сборка мусора / автоматизированное управление ссылками может привести к дополнительным издержкам, но это много?

GC или RC здесь не имеют значения. Свифт также использует RC в первую очередь. GC не существует, и не будет, если не произойдет какого-то огромного архитектурного скачка в технологии GC. (IMO, это навсегда) Я считаю, что у Swift гораздо больше возможностей для статической оптимизации. Особенно низкоуровневые алгоритмы шифрования, так как они обычно основаны на огромных числовых вычислениях, и это огромный выигрыш для статически распределенных языков.

На самом деле я был удивлен, потому что 40% кажется слишком маленьким. Я ожидал гораздо большего. Во всяком случае, это первоначальный выпуск, и я думаю, что оптимизация не была главной задачей. Swift даже не полнофункциональный! Они сделают это лучше.

Обновить

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

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

Во всяком случае, я подозреваю, что заявка на пропускную способность GC всегда лучше, чем RC. Большая часть служебных данных RC связана с операцией пересчета и блокировкой для защиты переменной числа подсчета. И реализация RC обычно обеспечивает способ избежать подсчета операций. В Objective-C есть __unsafe_unretainedи в Swift, (хотя мне все еще неясно) unownedвещи. Если стоимость операции пересчета не приемлема, вы можете попытаться отказаться от нее выборочно, используя механику. Теоретически, мы можем смоделировать сценарий почти уникального владения, используя агрессивные ссылки без сохранения, чтобы избежать издержек RC. Также я ожидаю, что компилятор может устранить некоторые очевидные ненужные операции RC автоматически.

В отличие от системы RC, AFAIK, частичный отказ от ссылочных типов не является опцией в системе GC.

Я знаю, что есть много выпущенной графики и игр, которые используют систему на основе GC, а также знаю, что большинство из них страдают от отсутствия детерминизма. Не только для характеристики производительности, но и управления сроком службы объекта. Unity в основном написан на C ++, но крошечная часть C # вызывает все странные проблемы с производительностью. HTML-гибридные приложения и до сих пор страдают от непредсказуемых скачков в любой системе. Широкое использование не означает, что это лучше. Это просто означает, что это легко и популярно для людей, у которых не так много вариантов.

Обновление 2

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

@Asik предоставил интересное мнение о шипах GC. То есть мы можем рассматривать подход value-type -where как способ отказаться от GC. Это довольно привлекательно и даже выполнимо в некоторых системах (например, чисто функциональный подход). Я согласен, что это хорошо в теории. Но на практике это имеет несколько проблем. Самая большая проблема заключается в частичном применении этого трюка, который не дает истинных характеристик без спайков.

Потому что проблема с задержкой - это проблема все или ничего . Если у вас есть один пик кадра в течение 10 секунд (= 600 кадров), то вся система явно выходит из строя. Это не о том, как лучше или хуже. Это просто пройти или потерпеть неудачу. (или менее 0,0001%). Где же источник всплеска ГХ? Это плохое распределение нагрузки GC. И это потому, что GC является фундаментально неопределенным. Если вы сделаете мусор, то он активирует GC, и в конечном итоге произойдет всплеск. Конечно, в идеальном мире, где нагрузка ГХ всегда будет идеальной, этого не произойдет, но я живу в реальном мире, а не в воображаемом идеальном мире.

Затем, если вы хотите избежать скачка, вы должны удалить все типы ссылок из всей системы. Но это сложно, безумно и даже невозможно из-за неустранимой части, такой как ядро ​​системы .NET и библиотека. Просто использовать систему без GC намного проще .

В отличие от GC, RC является в основном детерминированным, и вам не нужно использовать эту безумную оптимизацию (только по типу значения) только для того, чтобы избежать скачка. Что вам нужно сделать, так это отследить и оптимизировать часть, вызывающую всплеск. В системах RC скачок является локальной проблемой алгоритма, но в системах GC скачки всегда являются глобальной проблемой системы.

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

Eonil
источник
4
Сборка мусора, особенно генерация, обычно значительно быстрее, чем подсчет ссылок.
Ян Худек
9
@JanHudec Вы значительно быстрее просто бессмысленно в графическом поле в реальном времени. Вот почему я упоминаю, что на GC требуется огромный скачок . Поколение GC даже близко не может быть без шипов как теоретически, так и практически.
Эонил
5
Быстрее и без шипов совершенно ортогональные категории. Поколение сборщиков мусора быстрее . Они не свободны от шипов.
Ян Худек
4
То, что вы говорите, это пропускная способность . Быстрее всегда был неопределенный термин, и может означать что угодно в контексте. Если вы хотите поспорить о значении терминов, вам следует использовать более точный термин, а не быстрее, особенно с учетом текущего контекста - графики в реальном времени.
Эонил
11
@JanHudec: На мобильных устройствах или любых устройствах с ограниченными ресурсами GC не является значительно более быстрым и фактически является основной частью проблемы.
Мейсон Уилер
72

Будучи в 3,9 раза быстрее, чем Python, язык, который последовательно теряет большинство тестов со значительным отрывом (хорошо, это наравне с Perl, Ruby и PHP; но он проигрывает чему-либо статически типизированному), это не то, чем можно похвастаться.

Игра тестов показывает программы на C ++, которые в большинстве случаев более чем на порядок быстрее, чем программы на Python. Это не намного лучше по сравнению с Java, C # (на Mono), OCaml, Haskell и даже Clojure, который не является статически типизированным.

Таким образом, реальный вопрос заключается в том, как Objective-C только в 2,8 раза быстрее, чем Python. Видимо, они тщательно выбрали эталон, где медленная, полностью динамичная отправка ObjC сильно мешает. Любой статически типизированный язык должен уметь работать лучше. При сортировке сложных объектов существует много вызовов методов для сравнения объектов, и фактическое сравнение, вероятно, само по себе не было очень сложным. Таким образом, если Swift использует хотя бы какое-то преимущество информации о типе, он может легко справляться с вызовами методов, а других операций недостаточно для выполнения ObjC.

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

Ян Худек
источник
13
Я не совсем понимаю смысл этого ответа. Вы отвечаете «как быстро быстрее», говоря «тесты ошибочны»? Это то, что вы делаете? Я не вижу, как это отвечает на то, что спрашивали.
Брайан Оукли
15
@BryanOakley: я не думаю, что эталонные тесты ошибочны, но возможность того, что они выбрали тот эталон, где Swift был быстрее, безусловно, следует учитывать.
Ян Худек
23
Возможно, что ответ на вопрос «Как быстрее Swift?» может быть "Это на самом деле не так", @BryanOakley; это суть, которую я получаю из ответа Яна. «Ложь, проклятая ложь и статистика», в конце концов.
Джош Касвелл
4
Некоторое время назад мы протестировали Codename One, работающий на iOS, и наша реализация Java была намного быстрее, чем Objective-C codenameone.com/blog/… Ян прав, динамическая диспетчеризация действительно медленная, если они хоть немного их улучшат, то некоторые тесты будут показать огромное улучшение. Если они улучшат ARC хотя бы на долю (благодаря лучшему анализу кода), они могут избавиться от нелепой сложности. Чем более ограничен язык, тем больше компилятор может оптимизировать (см. Java), и Swift добавляет ограничения.
Шай Алмог
7
Ответ Яна - идеальный ответ на Q1 и, вероятно, Q2. Когда в качестве основного замечания я увидел критерии маркетингового события, я подумал: «Ничего себе, только в 1,3 раза в выбранном лучшем случае. Какой будет средний результат? 0,3x?»
Амин Негм-Авад
5

Objective-C динамически отправляет каждый вызов метода.

Гипотеза: тест использует статическую типизацию, позволяющую компилятору Swift выводить compareпоиск метода из sortцикла. Это требует узкого ограничения типа, которое допускает только сложные объекты в массиве, но не подклассы сложных.

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

Гипотеза: Swift оптимизирует вызовы подсчета ссылок вне цикла.

Гипотеза: в тесте Swift вместо объекта Objective-C используется структура Complex, поэтому для сравнения сортировки не нужны динамические отправки метода (поскольку он не может быть разделен на подклассы) или работа по подсчету ссылок (так как это тип значения).

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

Jerry101
источник
3

Честно говоря, если они не предоставят исходный код для тестов, которые они используют, я бы не стал доверять тому, что Apple скажет по этому вопросу. Помните, что это компания, которая перешла от PPC к Intel из-за проблем с электропитанием, когда 6 месяцами ранее они говорили, что Intel высосала и фактически подожгла кролика Intel в рекламе. Я хотел бы видеть твердое неопровержимое доказательство того, что Swift быстрее, чем ObjC, в большем количестве категорий, чем просто сортировка.

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

Все это говорит о том, что я не проводил никаких тестов между swift и ObjC, но, насколько я знаю, у swift есть свои собственные расширения LLVM IR, и возможно, что во время компиляции выполняется больше оптимизации, чем в ObjC.

Полное раскрытие: я пишу компилятор Swift с открытым исходным кодом, расположенный по адресу https://ind.ie/phoenix/

Если кто-то захочет помочь убедиться, что Swift не доступен только на оборудовании Apple, дайте мне знать, и я был бы рад включить вас.

greg.casamento
источник
2
это больше похоже на случайный комментарий, см. Как ответить
Гнат
2
Теперь лучше? :)
greg.casamento
0

Я боролся с собой через учебник по Swift, и мне кажется, что Swift более приземлён (заставляет меня думать о Visual Basic) с меньшим количеством «объект-индикации», чем Objective-C. Если бы они приняли во внимание C или C ++, я полагаю, что последний выиграл бы, так как они даже больше времени компиляции.

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

Покрашенный черный
источник
13
Выполнение теста «сортировка сложных объектов» было бы немного сложным в языке, таком как C, в котором нет нативной реализации объектов. Принимая во внимание, что аудитория для этого разговора, скорее всего, была на 100% программистами Objective-C, сравнивать с таким языком, как C ++, тоже не имеет особого смысла. Суть быстроты не в том, «эй, это самый великий язык!» скорее, «эй, это быстрее, чем язык, который вы используете сейчас для разработки OSX / iOS».
Брайан Оукли
10
C имеет прекрасно, qsortчто позволит сортировать сложные объекты; он просто использует обратный вызов, который понимает объекты под рукой. Я подозреваю, что C ++ отсутствует, потому std::sortчто смутит Swift. (Поскольку это шаблон, компилятор C ++ может его сильно оптимизировать, вплоть до развертывания цикла.)
MSalters
@MSalters: я полностью с тобой согласен. И C, и C ++ имеют возможности опережать Swift. Можно ли получить выполненный тест? Я более чем готов выполнить такой же тест с помощью Swift, Objective-C, C ++ и C.
Окрашенный черный
@BryanOakley также: «Этот язык требует меньше квадратных скобок!»
Ник Бедфорд
1
Этот ответ не держит воды вообще и вводит в заблуждение. OO не очень медленный, на самом деле самые быстрые системы, которые вы найдете, будут C ++, Java и C #, и стиль программирования (в значительной степени OO или нет) будет иметь очень мало общего с результирующими скоростями, если у вас нет плохой код
Билл К