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:
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:
- Como uma nova linguagem de programação pode ser muito mais rápida?
- Os resultados do Objective-C são causados por um compilador incorreto ou há algo menos eficiente no Objective-C que o Swift?
- 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?
objective-c
comparison
apple
swift-language
Amarelo
fonte
fonte
Respostas:
Primeiro, a comparação (IMO) com o Python é quase sem sentido. Somente a comparação com o Objective-C é significativa.
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 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.
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_unretained
e no Swift (embora ainda não esteja claro para mim)unowned
coisas. 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á.
fonte
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.
fonte
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
compare
pesquisa de método fora dosort
loop. 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.)
fonte
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.
fonte
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).
fonte
qsort
que 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, porquestd::sort
iria envergonhar Swift. (Uma vez que é um modelo, um compilador C ++ pode fortemente optimizá-lo, até desdobramento de loop.)