Ember.js: Perda de desempenho entre as versões 2.X e 3.X

Criado em 14 mai. 2020  ·  28Comentários  ·  Fonte: emberjs/ember.js

Há uma perda de desempenho de 60% entre as versões 2.X e 3.X. Veja os logs de tempo de renderização nos fiddles abaixo em diferentes versões. Exemplos simplificados para demonstrar o desempenho de renderização pura sem qualquer estilo e cálculos.

2,18 tempo de renderização do
3,18 tempo de renderização do

Bug Regression Rendering

Comentários muito úteis

Só queria dar uma atualização rápida sobre isso:

Executamos um teste TracerBench semelhante ao que @runspired configurou com emberobserver.com , que é um de nossos aplicativos de teste usuais, para ver se havia alguma fervura do sapo ocorrida (por exemplo, pequenas alterações de desempenho que eram insignificantes da versão para versão, mas resumiu-se a uma grande mudança). Aqui estão os resultados desse teste:

ember-observer-2.18-3.18.pdf

Podemos ver a partir desses resultados que existem dois saltos bastante definitivos:

  1. Ember 3.0 a Ember 3.1
  2. Ember 3.16 a Ember 3.17

A regressão no 3.17 é devido à atualização do Glimmer VM, e atualmente estamos nos concentrando em reduzir isso, uma vez que é bastante recente e provavelmente começará a afetar os aplicativos que estão sendo atualizados no ciclo LTS em breve.

A regressão no 3.1 era realmente conhecida na época, após discussão com a equipe principal. Isso foi causado, em parte, pela ativação de getters nativos e pelo uso de Object.defineProperty . Foi considerada uma regressão aceitável para permitir que a estrutura avance com recursos de navegador mais recentes.

Em geral, o cenário {{each}} que foi levantado no início desta edição parece ter regredido mais e de maneiras diferentes do que emberobserver.com. Depois de nos aprofundarmos na regressão 3.17, nos concentraremos na otimização de {{each}} para ver o que pode ser melhorado em geral.

Obrigado a todos pela paciência!

Todos 28 comentários

Depois de algumas execuções no Chrome 81 em minha máquina, obtive:

2,18 melhor tempo: 283ms
3,18 melhor tempo: 471ms

Isso era executá-lo com o DevTools fechado.

Então eu converti o twiddle 3.18 para Ember Octane por:

  • Usando classes nativas para componentes e controladores.
  • Usando @tracked e não usando @computed .
  • Convertendo o componente t-r em um componente somente de modelo porque não havia necessidade de uma classe de apoio.
  • Usando a sintaxe de colchetes angulares ao invocar componentes.
  • Usando args nomeados e this. onde apropriado nos modelos.

Depois disso, o melhor tempo que obtive de 3.18.1 foi de 276 ms, portanto, uma melhoria significativa em linha com o número de 2,18.

No entanto, esses testes de desempenho não eram particularmente científicos e não investiguei qual mudança foi a mais importante em termos de desempenho.

A criação de perfil em um twiddle é bastante sujeita a erros, podemos portar para um repo de aplicativo ember-cli normal (usando um branch para cada uma das duas versões) para definir o perfil?

@rwjblue Estou obtendo os mesmos resultados em um aplicativo ember-cli normal. Pode ser testado aqui

@ richard-viney Pode haver melhorias a serem consideradas, mas o problema é que nenhum código obsoleto usado em ambas as versões e experimentando uma perda de desempenho parece inaceitável.

  • Usar template-only-component pode estar causando um aumento de desempenho, mas tr certamente precisará de uma classe de apoio para calcular alguns estilos internos. O exemplo foi simplificado para demonstrar o problema.
  • Com toda a refatoração, você obtém 2 por cento (283ms -> 276ms) de ganho de desempenho contra 2,18. Considere a atualização de um aplicativo 2.18 existente para 3.X. Refatorar todos os componentes apenas para obter aquele aumento de 2 por cento definitivamente não é viável.

@barisnisanci Concordo, eu não estava querendo sugerir que esse tipo de refatoração fosse necessário para evitar regressões de desempenho significativas durante a atualização. Foi um experimento para ver se havia algum impacto no uso das convenções modernas, pois isso pode ajudar a isolar o problema e / ou permitir que seja contornado, se necessário.

Seria interessante saber quais versões do Ember introduziram a regressão de desempenho, testando também as versões LTS intermediárias, ou seja, 3.4, 3.8, 3.12 e 3.16.

@barisnisanci Ember ember serve executados no modo de desenvolvimento por padrão. Durante o desenvolvimento, muitas ferramentas extras são ativadas e podem regredir seriamente o desempenho. Normalmente não consideramos isso uma regressão ou problema, a menos que seja ruim o suficiente para afetar a ergonomia do desenvolvedor. Portanto, primeiro, gostaria de verificar se você está executando as duas versões no modo de produção.

Baixei seu exemplo e servi 2.8 e 3.18 lado a lado no modo de produção. O que descobri foi que parece que você pode estar correto, em média, o tempo entre as duas operações auxiliares (que é o que está sendo medido aqui) parece maior em 3.18 do que era em 2.8. Isso se baseia em eu pegar algumas amostras no meu laptop de trabalho sem muitos controles, então é difícil dizer com certeza, mas olhando para isso, pode ser uma pequena mudança.

No entanto, olhando para outras métricas mais significativas, não estou vendo uma mudança. Olhando especificamente para o tempo geral para renderizar o conteúdo, eles parecem iguais em geral. A hora de pintar pela primeira vez é quase a mesma, por exemplo.

Screen Shot 2020-05-18 at 11 10 15 AM

É importante ter em mente que temos muito trabalho espalhado em vários lugares e, quando fazemos alterações, às vezes esse trabalho muda, mas não afeta as métricas _geral_. É por isso que usamos o TracerBench para verificar as mudanças de desempenho, porque ele foi projetado para considerar as fases gerais de renderização e para contabilizar todas as mudanças em um nível _macro_, ao invés de um nível _micro_, como o tempo entre os auxiliares em execução.

Provavelmente deveríamos tentar fazer um teste TracerBench em breve, por um período de tempo mais longo, apenas para verificar essas descobertas e ter certeza de que não escorregamos em geral (normalmente o usamos para mudanças menores onde esperamos regressões potenciais). Também devemos tentar colocá-lo em execução em intervalos regulares, para que possamos ver a linha de tendência.

@pzuraq Acabei de atualizar o repositório com rowsCount:300 e columnsCount:20 diferença deve ser mais perceptível agora. Ambos rodando com --environment production

  • 3,18 Primeira pintura: 3489 ms
    3 18
  • 2,18 Primeira pintura: 2814 ms
    2 18

Também notei que JS Heap nunca foi lançado no 3.18, mas talvez algum azar no GC.

Posso adicionar vínculos de estilo, injeções de serviço, cálculos mais pesados ​​em componentes em vez de aumentar as contagens, entretanto, eles podem obscurecer o problema subjacente.

Assim como você mencionou, as métricas gerais são muito mais importantes do que pequenas alterações. No entanto, pequenas diferenças somam uma grande queda de desempenho em nosso caso. O tempo de renderização inicial de nosso aplicativo comercial aumentou de 15 segundos para 20 segundos após a atualização para 3.18. Esperançosamente, você considerará a regressão em termos de porcentagem, em vez de pequenas mudanças em milissegundos.

Nossa empresa está sofrendo com esse problema. Atualizamos a versão do ember de 2.18 para 3.16. então, nossos tempos de renderização ficaram mais longos que '50' por cento. Quando usamos estruturas complicadas, a diferença entre os tempos de renderização se torna mais óbvia, em vez de pequenas alterações em milissegundos. Alguma atualização para esse problema? Temos benchmarks que mostram um aumento de 50% no tempo de renderização. Decidiu manter a 2,18 por enquanto. Podemos considerar a troca de frameworks se isso exigir um grande refator.

@ Caglayan06 Você poderia confirmar que está executando a bandeira de produção? Só quero ter certeza de que os números são iguais!

@ Caglayan06 - É improvável que seja uma coisa única. A reprodução fornecida por @barisnisanci pode não corresponder ao que seu perfil de aplicativos mostra. Você pode fornecer uma reprodução do problema geral em seu aplicativo (ou confirmar que o exemplo de repositório de

Você tem algum comentário sobre a última postagem de @barisnisanci neste tópico?
Tivemos problemas de desempenho semelhantes após a atualização do 2.18 para o 3.16. Tivemos 40% de perda de desempenho. Nós rebaixamos para 3.12, mas só conseguimos economizar 20% dessa perda, ainda não tão boa quanto 2.18. Refatorar da maneira que você mencionou antes leva quase tanto tempo quanto alternar entre estruturas. Devemos esperar alguma ação sobre este problema?

Recentemente, atualizamos para o ember 3.16.8, não temos nenhum caso de teste de desempenho e não encontramos problema de desempenho óbvio agora.
mas eu gostaria de resolver e encerrar os problemas de desempenho o mais breve possível.
>

PS: mais memória e cpu usados ​​no ie11. às vezes, causa o travamento do ie11.

@ Caglayan06 - É improvável que seja uma coisa única. A reprodução fornecida por @barisnisanci pode não corresponder ao que seu perfil de aplicativos mostra. Você pode fornecer uma reprodução do problema geral em seu aplicativo (ou confirmar que o exemplo de repositório de

O exemplo de @rwjblue @barisnisanci funciona para mim da mesma forma que @barisnisanci diz.

@ Caglayan06 Você poderia confirmar que está executando a bandeira de produção? Só quero ter certeza de que os números são iguais!

@scottmessinger sim, estamos executando o sinalizador de produção. Nossos resultados são semelhantes aos resultados de @barisnisanci '.

Melhoramos nossa estrutura de código. Ele aumentou o desempenho, mas ainda não é tão rápido quanto a versão 2.18 do ember. Se fizermos essas alterações no 2.18, obteremos os melhores resultados.

Não podemos reformular nosso sistema de código para alterar a sintaxe do código 3.16 e novos recursos. Isso é muito caro para nós, porque nosso projeto é enorme. Provavelmente, refatorar todo o projeto é mais caro do que mudar a estrutura. Alguma ação será tomada em relação a este problema?

Alguma ação será tomada em relação a este problema?

Sim, claro! Precisamos apenas encontrar tempo para criar um perfil e descobrir o que está acontecendo. Mas isso realmente não precisa esperar por ninguém, a não ser você cavar 😸

O exemplo de @rwjblue @barisnisanci funciona para mim da mesma forma que @barisnisanci diz.

@ Caglayan06 - Hmm, não foi exatamente isso que perguntei. Sei que o exemplo de @barisnisanci funciona, estou pedindo que você o revise / crie um perfil / compare as características de desempenho com o seu aplicativo e veja se a _ maneira_ que o exemplo funciona (e é mais lento) corresponde ao seu aplicativo.

@ Caglayan06 - Hmm, não foi exatamente isso que perguntei. Sei que o exemplo de @barisnisanci funciona, estou pedindo que você o revise / crie um perfil / compare as características de desempenho com o seu aplicativo e veja se a _ maneira_ que o exemplo funciona (e é mais lento) corresponde ao seu aplicativo.

@rwjblue i integre o repositório de ao nosso aplicativo, ele deu resultados semelhantes. Quando mudamos a versão 3.16 para 3.12, nosso desempenho foi impulsionado.
Mas ainda não tão rápido quanto a versão 2.18.

Em nosso aplicativo para alguns exemplos:
2977

Como um resultado:
Até nós melhoramos a estrutura do código, tempo médio total de renderização;
2,18 tempo de renderização: 1x seg
3,16 tempo de renderização: 1,6x seg.
3,12 tempo de renderização: 1,4x seg.

3.20 tem uma atualização de VM, então eu me pergunto se isso ajudaria aqui

@NullVoxPopuli não teve sorte com 3.20.0-beta.2 FP: 3.4 segundos (mesmo com 3.18)

Como o 3.12 mostra melhores resultados, acho que o problema pode ser introduzido com o rastreamento automático. Também # 18225 pode estar relacionado considerando a queda de desempenho de todo o aplicativo nos benchmarks de @ Caglayan06 3.12 -> 3.16.

Hm. Eu me pergunto quanta sobrecarga está o material compatível com versões anteriores

Algumas perguntas gerais:

  • Qual é o valor do sinalizador de recurso opcional do observador assíncrono?
  • O aplicativo em questão usa QPs?
  • A velocidade negativa afeta todas as rotas ou apenas algumas?

Algumas perguntas gerais:

  • Qual é o valor do sinalizador de recurso opcional do observador assíncrono?
  • O aplicativo em questão usa QPs?
  • A velocidade negativa afeta todas as rotas ou apenas algumas?

@rwjblue

  1. Não usando o sinalizador de observadores assíncronos, acho que o padrão é falso no 3.12. Em 3.16 Testado com ambos não faz muita diferença.
  2. QPs amplamente utilizados nas principais rotas. No entanto, queda de desempenho observada mesmo sem nenhum.
  3. Todas as rotas são afetadas

Além disso, o repositório de exemplo não usa nenhum dos itens acima, mas ainda é mais lento no 3.X. Os tempos de renderização podem ter aumentado gradualmente em cada versão secundária, portanto, não podemos identificar o problema exato.

Os relatórios do Tracerbench mostram que 2,18 a 3,18 regredem ~ 17% para este cenário, mas também melhora em vez de regredir em ~ 18% se uma conversão para o componente de brilho for feita.

2,18 a 3,18 Nenhuma outra alteração
2,18 a 3,18 + octano + componentes de brilho

Eu tenho minha própria bifurcação, onde adicionei um runner automatizado para isso, e estou trabalhando para melhorar o runner para que possamos restringir rapidamente por versão / commit para encontrar onde a (s) regressão (ões) ocorreram. https://github.com/runspired/version-performance/runs/801596557

Muito obrigado a

Para contextualizar, @krisselden desenvolveu o TracerBench como uma ferramenta especificamente para testar o desempenho de uma forma holística, e temos usado para os principais refatores internamente, como a implementação de decoradores e rastreamento automático / revisão . No LinkedIn, nós o usamos para testar nossos aplicativos antes de cada atualização do Ember, e não vimos esse nível de regressão.

No entanto, definitivamente poderia ser algo que perdemos. No final, estamos testando aplicativos específicos, que têm casos de uso e comportamentos específicos. Isso pode ser um problema que não detectamos porque nossos aplicativos de caso de teste não usaram a funcionalidade que regrediu, como a reprodução de @barisnisanci . Também é possível que, mesmo se consertarmos os problemas nessa reprodução, não consigamos consertar outras, portanto, se você estiver enfrentando regressões, definitivamente apreciaríamos reproduções para seu caso de uso. Estaremos trabalhando para tornar a configuração do TracerBench mais fácil de usar para que você possa testá-la localmente e enviar uma reprodução como a de @runspired .

Vamos nos aprofundar para descobrir qual é o problema exato e descobrir uma solução. Mais importante ainda, este nível de regressão não é aceitável para _qualquer_ API, mesmo se estivermos vendo uma aceleração com o Octane. Se os usuários não podem atualizar e mudar gradativamente, então não estamos todos escalando a montanha juntos.

Fique ligado para mais atualizações, nós o avisaremos enquanto descobrimos as coisas!

Muito obrigado a @runspired por seu https://github.com/TracerBench/tracerbench-compare-action

Só queria dar uma atualização rápida sobre isso:

Executamos um teste TracerBench semelhante ao que @runspired configurou com emberobserver.com , que é um de nossos aplicativos de teste usuais, para ver se havia alguma fervura do sapo ocorrida (por exemplo, pequenas alterações de desempenho que eram insignificantes da versão para versão, mas resumiu-se a uma grande mudança). Aqui estão os resultados desse teste:

ember-observer-2.18-3.18.pdf

Podemos ver a partir desses resultados que existem dois saltos bastante definitivos:

  1. Ember 3.0 a Ember 3.1
  2. Ember 3.16 a Ember 3.17

A regressão no 3.17 é devido à atualização do Glimmer VM, e atualmente estamos nos concentrando em reduzir isso, uma vez que é bastante recente e provavelmente começará a afetar os aplicativos que estão sendo atualizados no ciclo LTS em breve.

A regressão no 3.1 era realmente conhecida na época, após discussão com a equipe principal. Isso foi causado, em parte, pela ativação de getters nativos e pelo uso de Object.defineProperty . Foi considerada uma regressão aceitável para permitir que a estrutura avance com recursos de navegador mais recentes.

Em geral, o cenário {{each}} que foi levantado no início desta edição parece ter regredido mais e de maneiras diferentes do que emberobserver.com. Depois de nos aprofundarmos na regressão 3.17, nos concentraremos na otimização de {{each}} para ver o que pode ser melhorado em geral.

Obrigado a todos pela paciência!

Podemos obter uma atualização sobre este problema? Já se passaram cerca de dois meses.

Sim! Já se passaram dois longos meses, estivemos trabalhando duro nessa questão e continuando nossos refatores no Glimmer VM, que se adaptaram bem a isso.

Como mencionei antes, estávamos nos concentrando em dois conjuntos separados de correções:

  1. Refatores de baixo risco para pousar na versão 3.20 LTS, para quem está tentando atualizar para o próximo LTS
  2. Refatores em escala maior para pousar no mestre, para melhorar o desempenho a longo prazo

Para o primeiro conjunto de correções, refatoramos uma quantidade razoável de código Ember clássico, pois foi o código mais afetado. Conseguimos reduzir a perda de desempenho geral de 3,16-3,20 para valores estatisticamente insignificantes dessa forma, com base em testes em nossos aplicativos internos no LinkedIn. Eu não tive a chance de executar os testes contra o Ember Observer, infelizmente, mas acho que seria um resultado semelhante, já que eles costumam acompanhar muito próximos.

Para o segundo conjunto de correções, conseguimos, há relativamente pouco tempo, porque muitos deles eram muito grandes, incluindo:

  • Atualizar a VM para ser totalmente autotracking internamente, eliminando o excesso de tags
  • Refatorando a VM para usar uma única classe de referência monomórfica, em vez de muitas implementações com muita complexidade
  • Removendo o modo de compilação AoT não utilizado

Os resultados são muito bons!

results.pdf

Isso é uma comparação do master atual do Ember com o Ember 2.18, com a reprodução acima de @barisnisanci. Agora, como mencionado antes, este é um benchmark para um caso de uso muito específico, que também é extremamente simples. _Não_ vimos uma melhoria tão dramática em nenhum de nossos benchmarks de aplicativos do mundo real, foi muito mais modesto no geral. Esperamos que isso ajude as aplicações de @barisnisanci e de outros e estamos definitivamente interessados ​​em ouvi-los!

Repo testado

Também testado em nossa produção com diferentes versões de brasa. O branch master parece% 25 a% 40 mais lento do que 3.12 em nosso aplicativo. Com os resultados abaixo, não podemos atualizar o ember sem uma grande refatoração.

perf

@barisnisanci Desculpe, parece ser o caso! Como mencionei antes neste tópico, precisaremos reproduzir esses resultados de maneira estatisticamente sólida para poder A. confirmar o problema e B. iterar em direção a melhorias e uma melhor solução geral. Eu recomendo adicionar o TracerBench ao seu aplicativo para que você possa executar esses benchmarks sozinho ou fazer outra reprodução que demonstre o problema agora em master .

Esta página foi útil?
0 / 5 - 0 avaliações