Como o Swift pode ser muito mais rápido que o Objective-C nessas comparações?


115

A Apple lançou sua nova linguagem de programação Swift na WWDC14 . Na apresentação, eles fizeram algumas comparações de desempenho entre Objective-C e Python. A seguir, é apresentada uma figura de um de seus slides, uma comparação dessas três linguagens executando algum tipo de objeto complexo:

insira a descrição da imagem aqui

Havia um gráfico ainda mais incrível sobre uma comparação de desempenho usando o algoritmo de criptografia RC4 .

Obviamente, esta é uma palestra de marketing, e eles não entraram em detalhes sobre como isso foi implementado em cada uma. Mas eu me pergunto:

  1. Como uma nova linguagem de programação pode ser muito mais rápida?
  2. Os resultados do Objective-C são causados ​​por um compilador incorreto ou há algo menos eficiente no Objective-C que o Swift?
  3. Como você explicaria um aumento de 40% no desempenho? Eu entendo que a coleta de lixo / controle de referência automatizado pode produzir alguma sobrecarga adicional, mas isso?

13
O @MathewFoscarini Obj-C vai para o montador, mas possui um mecanismo de envio de mensagem de objeto caro. Para a maioria dos trabalhos de GUI, isso não importa, mas para classificar isso importa muito.
Donal Fellows

17
A comparação com o Python é o verdadeiro arranhão de cabeça aqui.
asthasr

9
@syrion marketing, e a linguagem parece emprestar da sintaxe do python (bem como o golang). Eles estão tentando dizer "hey, desenvolvedores de Python, você pode escrever algo não muito estrangeira no mac e que ele seja muito mais rápido, mais rápido do que Objective C que você nunca realmente tem o jeito"

4
@ MichaelT Eu entendo isso, mas ainda é estranho. Qualquer pessoa que saiba alguma coisa sobre idiomas perceberá que o Python, como linguagem interpretada, simplesmente não estará no mesmo estádio que o Objective-C ou outras linguagens compiladas (para a maioria das tarefas). Usá-lo como referência é estranho.
asthasr

7
Eles provavelmente significa que o tempo que leva para escrever o código ...
Lukas Eder

Respostas:


62

Primeiro, a comparação (IMO) com o Python é quase sem sentido. Somente a comparação com o Objective-C é significativa.

  • Como uma nova linguagem de programação pode ser muito mais rápida?

Objective-C é uma linguagem lenta. (Apenas a parte C é rápida, mas é porque é C) Nunca foi extremamente rápida. Foi rápido o suficiente para o objetivo (da Apple) e mais rápido que as versões mais antigas. E foi lento porque ...

  • O Objective-C resulta de um compilador incorreto ou há algo menos eficiente no Objective-C que o Swift?

O Objective-C garantiu que todo método fosse enviado dinamicamente. Nenhum despacho estático. Isso tornou impossível otimizar ainda mais o programa Objective-C. Bem, talvez a tecnologia JIT possa ajudar, mas AFAIK, a Apple realmente odeia características de desempenho imprevisíveis e vida útil do objeto. Eu não acho que eles adotaram qualquer coisa do JIT. O Swift não tem essa garantia de despacho dinâmico, a menos que você coloque algum atributo especial para a compatibilidade do Objective-C.

  • Como você explicaria um aumento de 40% no desempenho? Eu entendo que a coleta de lixo / controle de referência automatizado pode produzir alguma sobrecarga adicional, mas isso?

GC ou RC não importa aqui. Swift também está empregando RC principalmente. Nenhum GC existe, e também não existirá, a menos que haja um grande salto arquitetônico na tecnologia do GC. (IMO, é para sempre) Eu acredito que o Swift tem muito mais espaço para otimização estática. Algoritmos de criptografia especialmente de baixo nível, como eles geralmente se baseiam em cálculos numéricos enormes, e essa é uma grande vitória para linguagens de despacho estaticamente.

Na verdade, fiquei surpreso porque 40% parece muito pequeno. Eu esperava muito mais. De qualquer forma, este é o lançamento inicial e acho que a otimização não era a principal preocupação. O Swift nem está completo! Eles vão melhorar.

Atualizar

Alguns continuam me incomodando para argumentar que a tecnologia GC é superior. Embora as coisas abaixo possam ser discutíveis, e apenas minha opinião muito tendenciosa, mas acho que tenho que dizer para evitar esse argumento desnecessário.

Eu sei o que são GCs conservadores / de rastreamento / geracionais / incrementais / paralelos / em tempo real e como são diferentes. Eu acho que a maioria dos leitores também já sabe disso. Também concordo que o GC é muito bom em alguns campos e também mostra alto rendimento em alguns casos.

De qualquer forma, suspeito que a alegação de taxa de transferência do GC seja sempre melhor que a RC. A maior parte da sobrecarga do RC vem da operação e bloqueio de ref-counting para proteger a variável do número de ref-count. E a implementação de RC geralmente fornece uma maneira de evitar a contagem de operações. No Objective-C, há __unsafe_unretainede no Swift (embora ainda não esteja claro para mim) unownedcoisas. Se o custo da operação de ref-counting não for aceitável, você pode tentar desativá-los seletivamente usando a mecânica. Teoricamente, podemos simular um cenário de propriedade quase exclusiva usando referências que não retêm muito agressivamente para evitar sobrecarga de RC. Também espero que o compilador possa eliminar automaticamente algumas operações desnecessárias óbvias de RC.

Ao contrário do sistema RC, o AFAIK, a exclusão parcial de tipos de referência não é uma opção no sistema GC.

Eu sei que existem muitos gráficos e jogos lançados que usam sistema baseado em GC e também sei que a maioria deles está sofrendo por falta de determinismo. Não apenas pela característica de desempenho, mas também pelo gerenciamento da vida útil do objeto. O Unity é principalmente escrito em C ++, mas a pequena parte do C # causa todos os problemas estranhos de desempenho. Aplicativos híbridos HTML e ainda sofrendo picos imprevisíveis em qualquer sistema. Usado amplamente não significa que seja superior. Apenas significa que é fácil e popular para pessoas que não têm muitas opções.

Atualização 2

Novamente, para evitar discussões ou discussões desnecessárias, adiciono mais alguns detalhes.

A @Asik forneceu uma opinião interessante sobre os picos de GC. É isso que podemos considerar a abordagem do tipo de valor em qualquer lugar como uma maneira de optar pela exclusão do material do GC. Isso é bastante atraente e até factível em alguns sistemas (abordagem puramente funcional, por exemplo). Concordo que isso é legal em teoria. Mas, na prática, tem vários problemas. O maior problema é que a aplicação parcial desse truque não fornece características verdadeiras sem pico.

Porque o problema de latência é sempre um problema de tudo ou nada . Se você tiver um pico de quadro por 10 segundos (= 600 quadros), obviamente, todo o sistema está falhando. Não se trata de quão melhor ou pior. É apenas passar ou falhar. (ou menos de 0,0001%) Então, onde está a fonte do pico do GC? Essa é uma má distribuição da carga do GC. E isso porque o GC é fundamentalmente indeterminista. Se você fizer algum lixo, ele ativará o GC e o pico ocorrerá eventualmente. Obviamente, no mundo ideal onde a carga do GC será sempre ideal, isso não acontecerá, mas estou vivendo no mundo real, em vez do mundo ideal imaginário.

Então, se você quiser evitar picos, precisará remover todos os tipos de ref de todo o sistema. Mas é difícil, insano e até impossível devido a partes irremovíveis, como o sistema principal e a biblioteca .NET. Apenas o uso de sistemas que não sejam GC é muito mais fácil .

Ao contrário do GC, o RC é fundamentalmente determinístico, e você não precisa usar essa otimização insana (apenas do tipo de valor puramente) apenas para evitar picos. O que você precisa fazer é rastrear e otimizar a peça que causa o pico. Nos sistemas RC, o pico é uma questão de algoritmo local, mas nos sistemas de GC, os pontos sempre são um problema global do sistema.

Eu acho que minha resposta está fora do tópico e principalmente apenas repetição de discussões existentes. Se você realmente deseja reivindicar alguma superioridade / inferioridade / alternativa ou qualquer outra coisa relacionada ao GC / RC, há muitas discussões existentes neste site e no StackOverflow, e você pode continuar lutando lá.


4
A coleta de lixo, especialmente geracional, geralmente é significativamente mais rápida que a contagem de referência.
Jan Hudec

9
@JanHudec Seu significativamente mais rápido é simplesmente sem sentido no campo de gráficos em tempo real. É por isso que mencionei um grande salto no GC. O GC geracional não está nem perto de ficar livre de picos, tanto na teoria quanto na prática.
Eonil

5
Mais rápido e livre de picos são categorias completamente ortogonais. Os coletores de lixo geracionais são mais rápidos . Eles não são livres de spike.
Jan Hudec

4
O que você está falando é taxa de transferência . Mais rápido sempre foi um termo vago e pode significar qualquer coisa pelo contexto. Se você quiser discutir sobre o significado dos termos, use termos mais precisos e não mais rápidos, especialmente considerando o contexto atual - gráficos em tempo real.
Eonil

11
@JanHudec: em dispositivos móveis ou em qualquer dispositivo com recursos limitados, o GC não é significativamente mais rápido e, de fato, é uma parte importante do problema.
Mason Wheeler

72

Sendo 3,9 vezes mais rápido que o python, a linguagem que perde consistentemente a maioria dos benchmarks por uma margem considerável (ok, é parecida com Perl, Ruby e PHP; mas perde para qualquer coisa digitada estaticamente), não é nada do que se vangloriar.

O jogo de benchmarks mostra programas C ++ que são mais do que ordem de magnitude mais rápidos que os programas python na maioria dos casos. Não é muito melhor quando comparado com Java, C # (no Mono), OCaml, Haskell e até Clojure, que não é estaticamente digitado.

Portanto, a verdadeira questão é como o Objective-C é apenas 2,8 vezes mais rápido que o python. Aparentemente, eles escolheram cuidadosamente o benchmark, onde o lento envio totalmente dinâmico da ObjC dói muito. Qualquer linguagem de tipo estaticamente deve ser capaz de fazer melhor. Na classificação de objetos complexos, existem muitas chamadas de métodos para comparar os objetos e a comparação real provavelmente não era muito complexa. Portanto, se o Swift tira pelo menos alguma vantagem das informações de tipo, ele pode facilmente se sair melhor nas chamadas de método e não há outras operações suficientes nas quais o ObjC poderia ser melhor.

Obviamente, como o jogo de benchmarks demonstra claramente, o desempenho relativo em diferentes tarefas varia bastante, portanto, um benchmark não é realmente representativo. Se eles tivessem um ponto de referência onde houvesse uma vantagem maior, teriam nos mostrado esse, em outras tarefas, provavelmente não é melhor ou nem tanto.


13
Não entendo bem o objetivo dessa resposta. Você está respondendo "como é rápido, mais rápido", dizendo "os parâmetros de referência são falhos"? É esse o ponto que você está fazendo? Não vejo como isso responde ao que estava sendo perguntado.
Bryan Oakley

15
@BryanOakley: Eu não acho que os benchmarks são falhos, mas a possibilidade de escolherem o único benchmark em que o Swift foi mais rápido certamente deve ser considerada.
Jan Janec

23
É possível que a resposta para "Como o Swift seja mais rápido?" pode ser "Na verdade não é", @BryanOakley; essa é a essência que recebo da resposta de Jan. "Mentiras, malditas mentiras e estatísticas", afinal.
Josh Caswell

4
Há algum tempo atrás, comparamos o Codename One em execução no iOS e nossa implementação em Java foi muito mais rápida que o Objective-C codenameone.com/blog/… Jan está correto, o envio dinâmico é realmente lento, se eles melhoraram um pouco, então alguns benchmarks serão mostrar uma enorme melhoria. Se eles melhorarem o ARC, mesmo que por uma fração (graças a uma melhor análise de código), poderão se livrar de uma quantidade ridícula de complexidade. Quanto mais restrita a linguagem, mais o compilador pode fazer para otimizar (consulte Java) e o Swift adiciona restrições.
Shai Almog

7
A resposta de Jan é uma resposta perfeita ao Q1 e provavelmente ao Q2. Quando vi as referências de um evento de marketing como a palestra principal, pensei: "Uau, apenas 1,3x no melhor caso selecionado. Qual será o resultado médio? 0,3x?"
Amin Negm-Awad

5

O Objective-C envia dinamicamente todas as chamadas de métodos.

Hipótese: O benchmark usa digitação estática para permitir que o compilador Swift eleve a comparepesquisa de método fora do sortloop. Isso requer uma restrição de tipo restrito que permite apenas objetos Complexos na matriz, não subclasses de Complex.

(No Objective-C, você pode elevar a pesquisa do método manualmente, se realmente desejar, chamando o suporte ao tempo de execução da linguagem para procurar o ponteiro do método. É melhor ter certeza de que todas as instâncias da matriz são da mesma classe .)

Hipótese: Swift otimiza chamadas de contagem de referência fora do loop.

Hipótese: O benchmark Swift usa uma estrutura Complexa no lugar de um objeto Objective-C, portanto, as comparações de classificação não precisam de despachos de métodos dinâmicos (já que não podem ser subclassificados) ou trabalho de contagem de referência (já que é um tipo de valor).

(No Objective-C, você pode recorrer ao C / C ++ para desempenho, desde que não envolva objetos Objective-C, por exemplo, classifique uma matriz C de estruturas.)


3

Honestamente, a menos que eles liberem a fonte para os testes que estão usando, eu não confiaria em nada que a Apple tenha a dizer sobre o assunto. Lembre-se, esta é a empresa que mudou do PPC para a Intel com base em questões de energia quando, seis meses antes, eles estavam dizendo que a Intel era péssima e realmente incendiou o coelho da Intel em um comercial. Eu gostaria de ver provas irrefutáveis ​​de que o Swift é mais rápido que o ObjC em mais categorias do que apenas classificação.

Além disso, você deve questionar as estatísticas lançadas na WWDC, pois elas têm o cheiro de marketing por toda parte.

Dito tudo isso, eu não realizei nenhum teste entre o swift e o ObjC, mas pelo que sei o swift tem suas próprias extensões de IR LLVM e é possível que mais otimização esteja sendo feita em tempo de compilação do que no ObjC.

Divulgação completa: Estou escrevendo um compilador Swift de código aberto localizado em https://ind.ie/phoenix/

Se alguém quiser ajudar a garantir que o Swift não esteja disponível apenas no hardware da Apple, entre em contato e ficarei feliz em incluí-lo.


2
este lê mais como um comentário ranty, consulte Como responder
mosquito

2
É melhor agora? :)
greg.casamento

0

Eu me esforcei no tutorial do Swift, e me parece que o Swift é mais realista (me faz pensar no Visual Basic) com menos 'especificação de objeto' do que o Objective-C. Se eles tivessem levado em conta C ou C ++, presumo que os últimos teriam vencido, pois são ainda mais em tempo de compilação.

Nesse caso, presumo que o Objective-C seja vítima de sua pureza orientada a objetos (e sobrecarga).


13
Fazer um benchmark de "classificação complexa de objetos" seria um pouco difícil em uma linguagem como C que não possui uma implementação nativa de objetos. Dado que o público desta palestra era provavelmente 100% programadores de Objective-C, comparar com uma linguagem como C ++ também não faz muito sentido. A questão do rápido não é "ei, essa é a melhor linguagem de todos os tempos!" mas sim "ei, isso é mais rápido que o idioma que você está usando agora para o desenvolvimento OSX / iOS".
Bryan Oakley

10
C tem uma perfeitamente fina qsortque permitirá a classificação complexa de objetos; ele apenas usa um retorno de chamada que entende os objetos em questão. Eu suspeito que C ++ está faltando, porque std::sortiria envergonhar Swift. (Uma vez que é um modelo, um compilador C ++ pode fortemente optimizá-lo, até desdobramento de loop.)
MSalters

@MSalters: Concordo plenamente com você. C e C ++ têm capacidade para superar o Swift. Seria possível obter o teste executado. Eu estou mais do que disposto a executar o mesmo benchmark com Swift, Objective-C, C ++ e C.
Painted Black

@BryanOakley também: "Este idioma requer menos colchetes!"
Nick Bedford

1
Esta resposta não retém a água e é terrivelmente enganosa. OOO não é realmente lento, na verdade, os sistemas mais rápidos que você encontrará serão C ++, Java e C # e o estilo (OO pesado ou não) de programação terá muito pouco a ver com as velocidades resultantes, a menos que você tenha realmente código incorreto.
Bill K
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.