Apple представила свой новый язык программирования Swift на WWDC14 . В презентации они провели сравнение производительности Objective-C и Python. Ниже приведено изображение одного из их слайдов, сравнение этих трех языков, выполняющих некоторую сложную сортировку объектов:
Был еще более невероятный график сравнения производительности с использованием алгоритма шифрования RC4 .
Очевидно, что это маркетинговый разговор, и они не вдавались в подробности о том, как это было реализовано в каждом из них. Я оставляю меня интересно, хотя:
- Как новый язык программирования может быть намного быстрее?
- Результаты Objective-C вызваны плохим компилятором или есть что-то менее эффективное в Objective-C, чем Swift?
- Как бы вы объяснили увеличение производительности на 40%? Я понимаю, что сборка мусора / автоматизированное управление ссылками может привести к дополнительным издержкам, но это много?
Ответы:
Во-первых, (IMO) сравнивать с Python практически бессмысленно. Только сравнение с Objective-C имеет смысл.
Objective-C - медленный язык. (Только партия C быстрая, но это потому, что это C) Она никогда не была очень быстрой. Это было достаточно быстро для их (Apple) цели и быстрее, чем их старые версии. И это было медленно, потому что ...
Objective-C гарантирует, что каждый метод будет динамически отправлен. Нет статической отправки вообще. Это сделало невозможным дальнейшую оптимизацию программы Objective-C. Ну, может быть, технология JIT может помочь, но AFAIK, Apple действительно ненавидит непредсказуемые характеристики производительности и срок службы объекта. Я не думаю, что они приняли какие-либо вещи JIT. Swift не имеет такой гарантии динамической отправки, если вы не добавили какой-либо специальный атрибут для совместимости с Objective-C.
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, и вы можете продолжать там бороться.
источник
Будучи в 3,9 раза быстрее, чем Python, язык, который последовательно теряет большинство тестов со значительным отрывом (хорошо, это наравне с Perl, Ruby и PHP; но он проигрывает чему-либо статически типизированному), это не то, чем можно похвастаться.
Игра тестов показывает программы на C ++, которые в большинстве случаев более чем на порядок быстрее, чем программы на Python. Это не намного лучше по сравнению с Java, C # (на Mono), OCaml, Haskell и даже Clojure, который не является статически типизированным.
Таким образом, реальный вопрос заключается в том, как Objective-C только в 2,8 раза быстрее, чем Python. Видимо, они тщательно выбрали эталон, где медленная, полностью динамичная отправка ObjC сильно мешает. Любой статически типизированный язык должен уметь работать лучше. При сортировке сложных объектов существует много вызовов методов для сравнения объектов, и фактическое сравнение, вероятно, само по себе не было очень сложным. Таким образом, если Swift использует хотя бы какое-то преимущество информации о типе, он может легко справляться с вызовами методов, а других операций недостаточно для выполнения ObjC.
Конечно, как ясно показывает тестовая игра , относительная производительность при выполнении различных задач сильно варьируется, поэтому один тест не является действительно репрезентативным. Если бы у них был бенчмарк, в котором он имел большее преимущество, они бы показали нам этот, вместо этого, поэтому в других задачах он, вероятно, не лучше или не так уж много.
источник
Objective-C динамически отправляет каждый вызов метода.
Гипотеза: тест использует статическую типизацию, позволяющую компилятору Swift выводить
compare
поиск метода изsort
цикла. Это требует узкого ограничения типа, которое допускает только сложные объекты в массиве, но не подклассы сложных.(В Objective-C вы можете поднять поиск метода вручную, если вы действительно этого хотите, вызвав поддержку языка времени выполнения для поиска указателя метода. Вам лучше быть уверенным, что все экземпляры в массиве принадлежат одному и тому же классу .)
Гипотеза: Swift оптимизирует вызовы подсчета ссылок вне цикла.
Гипотеза: в тесте Swift вместо объекта Objective-C используется структура Complex, поэтому для сравнения сортировки не нужны динамические отправки метода (поскольку он не может быть разделен на подклассы) или работа по подсчету ссылок (так как это тип значения).
(В Objective-C вы можете вернуться к C / C ++ для повышения производительности, если он не включает объекты Objective-C, например, сортирует массив структур C).
источник
Честно говоря, если они не предоставят исходный код для тестов, которые они используют, я бы не стал доверять тому, что Apple скажет по этому вопросу. Помните, что это компания, которая перешла от PPC к Intel из-за проблем с электропитанием, когда 6 месяцами ранее они говорили, что Intel высосала и фактически подожгла кролика Intel в рекламе. Я хотел бы видеть твердое неопровержимое доказательство того, что Swift быстрее, чем ObjC, в большем количестве категорий, чем просто сортировка.
Кроме того, вы должны подвергать сомнению любые статистические данные, которые публикуются на WWDC, так как они имеют запах маркетинга во всем.
Все это говорит о том, что я не проводил никаких тестов между swift и ObjC, но, насколько я знаю, у swift есть свои собственные расширения LLVM IR, и возможно, что во время компиляции выполняется больше оптимизации, чем в ObjC.
Полное раскрытие: я пишу компилятор Swift с открытым исходным кодом, расположенный по адресу https://ind.ie/phoenix/
Если кто-то захочет помочь убедиться, что Swift не доступен только на оборудовании Apple, дайте мне знать, и я был бы рад включить вас.
источник
Я боролся с собой через учебник по Swift, и мне кажется, что Swift более приземлён (заставляет меня думать о Visual Basic) с меньшим количеством «объект-индикации», чем Objective-C. Если бы они приняли во внимание C или C ++, я полагаю, что последний выиграл бы, так как они даже больше времени компиляции.
В этом случае я предполагаю, что Objective-C является жертвой своей объектно-ориентированной чистоты (и издержек).
источник
qsort
что позволит сортировать сложные объекты; он просто использует обратный вызов, который понимает объекты под рукой. Я подозреваю, что C ++ отсутствует, потомуstd::sort
что смутит Swift. (Поскольку это шаблон, компилятор C ++ может его сильно оптимизировать, вплоть до развертывания цикла.)