Nós perfilamos o carregamento do Habr ou como 189 solicitações na página tornam a influência

Tomo suco de cereja grosso


Há algum tempo, me interessei pelo desempenho do site, pelas otimizações de download e similares. E agora, mais uma vez indo ao Habr, pensei que estava acostumado a perceber um carregamento de recursos bastante rápido como um dado, sem sequer pensar em como isso foi alcançado. Por isso, decidi combinar negócios com prazer - para ver como estão as coisas com o desempenho da Habr e quais soluções técnicas foram feitas para otimizá-lo.


Para aqueles que estão interessados ​​em saber o que foi feito para que possamos receber o conteúdo o mais rápido possível e como é o download do Habr da Argentina - por favor, abaixo do gato.


Preparação


Precisamos de uma versão nova do Chrome / Canary funcionando no modo anônimo (verifique se todas as extensões estão desativadas). Além disso, no Developer Console (Developer Tools - F12), na guia rede, você deve definir o sinalizador de desativar cache, porque Vamos traçar o perfil apenas da primeira inicialização, embora ainda não haja recursos no cache.


Estágio Um - "No andar de cima"


O principal objetivo desta parte é familiarizar-se com o site como um todo, entender sua estrutura e descobrir quais recursos específicos ele precisa.


Abrimos as ferramentas do desenvolvedor, acessamos a guia rede, abrimos o site e, na parte inferior da guia, analisamos as estatísticas de uso da rede:


E uma capa de uma mãe branca.


Todo o site foi carregado em 2,02 segundos, o que parece ótimo (considerando a carga do Habr). O evento DomContentLoaded (daqui em diante simplesmente DCL) geralmente apareceu em 1,01 segundos, o que parece ainda melhor. Com tudo isso, o site faz 189 solicitações e carrega 9,6MB de recursos. Isso nos diz que ou a equipe Habra é um gênio (pode muito bem ser), e o artigo deve ser finalizado aqui (e peça para a equipe tomar café e biscoitos), ou lembre-se de que eu tenho um canal de 100 Mb / s e o Core I7 . I.e. você precisa se aproximar um pouco da realidade e, pelo menos, limitar a largura do canal.


Ativamos o modo 3G Rápido e olhamos novamente:


Despeje delicadamente o suco na capa -


O DCL piorou para 3,48 segundos, o que ainda é razoavelmente aceitável. Mas finalmente o site carregou em ateus 54,76 segundos. Agora tudo está lógico - você não pode baixar e baixar quase 10 megabytes quando a conexão está fraca. Provavelmente, os caras fizeram um bom trabalho para nos mostrar o conteúdo o mais rápido possível (isso é evidenciado pelo fato de que mesmo no modo fast3g o DCL surge rápido o suficiente), e tudo o que não era crítico foi deixado em segundo plano. Vamos verificar isso um pouco mais tarde, e agora vamos ver por que carregamos tanto tempo. Classifique todas as solicitações por tempo de carregamento:


Um ponto será exibido.
Clicável


As imagens (top 7) são carregadas por mais tempo e um arquivo JavaScript é prebid.js. Se observarmos o tamanho deles, podemos assumir que esse é precisamente o motivo do carregamento lento.


Sobre suposições

Com suposições, você precisa ser extremamente cuidadoso. Por exemplo, um carregamento longo de um recurso pode ser causado não apenas pelo tamanho do arquivo, mas também, por exemplo, problemas com DNS, pico de carga de armazenamento ou um cache frio do servidor. Portanto, uma suposição não verificada pode fazer com que você perca tempo resolvendo um problema que nem existe.


Observando as estatísticas ( TTFB : 0,610 ms, carga: 40 000 ms), podemos concluir que nossa suposição é bastante provável. Vamos admirar o nosso TOP 1 (png, 1560X780, 24 bits):


Agora que não há lugar


De fato, problemas com imagens são principalmente problemas do nosso tráfego com você. Imagens (diferentemente de estilos e scripts) não bloqueiam a renderização de uma página da Web e, portanto, apesar da presença de tais pesos pesados ​​(pode ser pior, eles viram), isso quase não afeta o desempenho. Embora, é claro, a otimização nessa direção (por exemplo, transcodificar para jpeg2000 ou webp ou carregamento progressivo não seja supérflua).


Sobre imagens

Como escrevi acima, as imagens não bloqueiam a renderização da página. Mas eles usam nosso pool de conexões e, no http 1.x, o número deles é limitado, e no http 2.xe no Chrome também, nem tudo é tão bom quanto eu ouvi. Portanto, mesmo aqui, existe a chance de alguma imagem retardar o carregamento de um script síncrono e que, por sua vez, já pare de renderizar a página. Além disso, o carregamento da imagem também pode causar uma recontagem do layout, diminuindo a velocidade da renderização. Se observarmos a marcação Habr, quase todas as tags img têm largura e altura. Isso elimina a necessidade de reflow para impactar positivamente o desempenho do download. Você pode ler mais sobre isso aqui .


Vamos ver quais outros recursos o Habr extrai - analisaremos os tipos e os classificaremos pelo tempo de carregamento. Vamos começar com JavaScript


Javascript


Sobre javascript

JavaScript tem vários problemas em termos de desempenho do site. Em primeiro lugar (todo mundo sabe disso há muito tempo), o js síncrono bloqueia a renderização adicional da página. I.e. até recebermos e executarmos nosso JavaScript, o navegador aguardará (na verdade, não exatamente, o navegador, especialmente o Chrome, poderá otimizar, mas essa é outra história) e não renderizará mais conteúdo. Usando scripts síncronos na cabeça, adiamos o momento em que o usuário vê pelo menos alguma coisa (mesmo texto). Portanto, todo mundo está tentando lançar Js no final da página ou até torná-lo assíncrono. Isso funciona, mas não resolve o segundo problema que nos traz o fato de que o JavaScript ainda é uma linguagem de script. Portanto, o navegador não é suficiente apenas para baixá-lo - ele também precisa ser "entendido". E aqui, verifica-se que isso é um problema, porque processadores fracos (por exemplo, em telefones baratos ou netbooks, ou mesmo bons laptops em modo de desempenho limitado) fazem isso lentamente, bloqueando o segmento principal! Abaixo está um exemplo de como um script de publicidade assíncrono entrou na seção crítica da renderização Habr e, embora um pouco, mas ainda prejudicou o desempenho. Se alguém estiver interessado, há um artigo muito (muito, muito) bom sobre esse tópico.


Os scripts Habr carregam muito - 1,1 MB (e isso já está em um formato compactado) para 40 solicitações. Isso é francamente significativo, ainda volta para nós e precisamos fazer algo sobre isso. Classifique nossos scripts "pela cachoeira". Nossa tarefa é encontrar scripts carregados ANTES da linha azul, pois são eles (provavelmente) que nos impedem de renderizar o site o mais rápido possível.


Na capa da minha mãe
Clicável


Abrimos o html que o Habr nos deu (é importante olhar para a resposta, pois o html final terá uma aparência diferente) e passamos pela lista. Como você pode ver - jQuery, raven.js, advertise.js e adriver.js são carregados de forma síncrona diretamente da tag head (ou seja, eles bloqueiam tudo). O Gpt e o editor são carregados do cabeçalho, mas já de forma assíncrona (ou seja, eles não bloqueiam nada, o navegador renderiza a página ainda mais durante o carregamento). Os fornecedores, Main e Math, checklogin são carregados no final, mas de forma síncrona (ou seja, o texto já está lá, podemos lê-lo, mas o DCL não aparecerá até o carregamento). O restante não aparece na resposta inicial - eles são adicionados dinamicamente, mas esse é outro tópico.


Então, encontramos os scripts que de alguma forma afetam a rapidez com que vemos o texto na página. Estes são os primeiros candidatos à otimização. Idealmente, eles devem ser assíncronos ou colocados o mais baixo possível para permitir que o navegador renderize conteúdo para nós. No entanto, o ideal não é possível, pois provavelmente existem outros scripts no site que dependem do mesmo jQuery. O desejo de baixar o raven o mais rápido possível - uma biblioteca para rastrear vários erros que ocorrem no cliente, também pode ser entendido. Mas advertise.js e adriver.js já são verdadeiros candidatos a pelo menos descer a página e, no máximo, também no modo assíncrono. Uma história semelhante com gpt e editora. Sim, eles são carregados de forma assíncrona, mas, no entanto, eles podem (e irão) interferir conosco durante o carregamento. Portanto, eles também podem ser enviados para o final da página. Além disso, você pode tentar usar os atributos de Dicas de recursos - preload / prefetch / dns-prefetch para informar ao navegador o que carregar antecipadamente. A propósito, recomendo que você leia sobre as Dicas de recursos - uma ferramenta muito interessante, embora com suporte limitado (até o momento).


Agora classifique a lista por tamanho de arquivo:


A capa deve ser dobrada inteira
https://github.com/Drag13/articles/blob/habrformance/habrformance/scripts.PNG


Vemos um script que carrega duas vezes (pubads). Também observamos que o prebid.js é carregado na pasta not-for-prod


Em suco de cereja grosso.


Para limpar nossa consciência, verificamos se todos os scripts estão minificados. De repente, os scripts check-login.js e adriver.js não foram minificados. Especialmente satisfeito com o conteúdo deste último:


Pegue a capa de uma mãe de cereja


E com scripts você pode terminar temporariamente.


Estilos


Sobre estilos

Com estilos, tudo também não é tão simples. Primeiro, o carregamento síncrono de estilos também bloqueia o encadeamento principal (embora eles sejam analisados ​​rapidamente, mais rapidamente que o JavaScript). E segundo, tudo é um pouco mais complicado. Por que o navegador precisa de CSS? Para criar CSSOM . O que o JavaScript pode fazer com CSS? Isso mesmo - mude. E o que acontecerá se o CSSOM ainda não estiver construído e o js já estiver tentando alterar alguma coisa lá? A resposta é quem sabe. Portanto, o navegador atrasa a execução do JavaScript até que o CSSOM seja calculado. Como corretamente escrito em outro artigo muito útil - sem CSS = sem JavaScript. Portanto, carregar CSS bloqueia a execução JS.


Aqui estão os estilos que Habr carrega:


E uma caneca de leite.
Clicável


Como você pode ver, existem apenas três deles, com o segundo e o terceiro carregados em um quadro separado, por isso os ignoramos. Mas o primeiro conjunto de estilos é crucial para todo o site. E nós o baixamos por muito tempo. Porque Primeiro, eles esperaram muito tempo por uma resposta do servidor (TTFB 570 ms, retornaremos a ele na terceira seção) e, em segundo lugar, 713 ms foram carregados por um longo tempo. O que pode ser feito aqui. A primeira e mais simples é tentar adicionar o atributo preload. Isso solicitará que o navegador comece a carregar o CSS o mais cedo possível. A segunda opção é realçar o CSS crítico e incorporá-lo diretamente na página da web, e carregar o restante de forma síncrona (ou até assíncrona). Isso levará a um aumento no tamanho da página (mas já não é pequeno e + 5kb não estragará nada) e a um possível redesenho do layout (perda de tempo), mas você pode tentar.


Eu nem vou mostrar fontes. Ele está lá sozinho, embora por algum motivo ele seja carregado diretamente do servidor Habr, em vez da CDN (e provavelmente por um motivo). Mas vou agradecer pelo fato de haver apenas uma fonte.


Com isso, a parte geral da análise do site pode ser considerada concluída. Hora de ir mais fundo.


Estágio Dois - "Modo Manual"


Na última etapa, vimos que Habr carrega. Agora vamos ver como isso é renderizado.


Vá para a guia de criação de perfil. Verificamos o que é a desaceleração fast3g (depois executamos novamente sem restrições) e executamos. Antes de tudo, estamos interessados ​​em tudo o que acontece antes do evento Primeira pintura com conteúdo (FCP) e, apenas no caso, em DCL. Selecionamos a área desde o início do carregamento até o FCP e olhamos para o diagrama final.


Despeje o leite ordenadamente -


Tudo acontece muito rapidamente - 2,161 segundos antes do FCP (era mais rápido, mas aparentemente algo havia mudado), mas como você pode ver, na maioria das vezes o navegador estava ocioso. A carga útil levou apenas 14% do tempo (cerca de 310 ms). Idealmente, o segmento principal do navegador é executado continuamente - analisando html, CSS, executa JS. E aqui - nada. Porque Porque o navegador simplesmente não tinha nada para fazer. Lembra-se de reduzir o tráfego? O navegador enviou solicitações e agora aguarda a conclusão. Se abrirmos o diagrama dos processos de rede (o mais alto), tudo ficará imediatamente claro.


Um ponto será exibido.
Clicável


Em 2029, o navegador viu main.bundle.css, enviou uma solicitação para recebê-lo e começou a esperar. No momento, o pré-scanner (smart chrome, pode executar adiante) descobriu que existem scripts síncronos abaixo e, sem esperar a chegada do css, enviou uma solicitação de scripts. Em seguida, o anúncio e o carregador são carregados (mas lembramos que, embora o CSSOM não seja criado, você não pode tocar em JS), o navegador os ignorou. Depois disso, o gpt e o raven foram carregados, mas o CSS ainda estava carregando, então eles também foram ignorados. Por fim, foi carregado o CSS, que o navegador analisou em 12 ms e imediatamente analisou o JS incorporado na página. Em seguida, o navegador novamente "adormeceu" a quase 150 ms, aguardando o jQuery.min.js. Depois disso, eu já comecei a trabalhar seriamente - descobri o jQuery carregado (20ms), analisou raven.js (4ms), analisou quase a página inteira (36ms), recontou os estilos (28ms), calculei o layout (78 ms + 8 ms) e, finalmente, por ~ 6 ms, pintamos a página. Aqui temos o FCP. Em seguida, analisamos a página, analisamos os scripts - olá para ninguém (publishertag.js, gpt.js que entrou no segmento principal antes do DCL), brincamos um pouco com os estilos (o que causou uma ligeira perda de tempo devido ao recálculo do layout) e começamos a aguardar os fornecedores. bundle.js. Para aguardar os fornecedores, passamos quase 1100 ms inativos. É verdade que, paralelamente, também carregamos o main.bundle.js (que, aliás, inicializou mais rapidamente), para que nem tudo seja tão ruim. Então tudo correu bem novamente. Analisamos os fornecedores, analisamos o pacote principal, analisamos Math.Jax e finalmente analisamos a página e obtivemos o DCL. É verdade que algum tipo de manipulador funcionou ali, que no meu I7 parou o segmento principal em 80 ms (ou seja, o site parecia congelar em 80 ms). Agora quase não percebemos isso, mas em um processador fraco, teoricamente, isso pode ser percebido.Se você vir isso depois que o conteúdo for renderizado, esta é uma ocasião para verificar o JS.


O que posso dizer? Novamente, apesar de parecer muito bom. Os principais problemas foram entregues a nós:


  • Um navegador grande e simples (inclusive devido ao desequilíbrio artificial entre a capacidade de computação do computador e a largura do canal, mas esse também é um cenário bastante válido)
  • Carregamento longo de CSS que atrasou o trabalho com js críticos
  • Carregamento síncrono de jQuery, fornecedores e principais pacotes que interromperam a aparência do conteúdo.

O que podemos fazer com isso já discutimos:


  • Tente adicionar o atributo preload para CSS e talvez alguns JS
  • Reduzir ou CSS embutido
  • Tente jogar geralmente scripts fora do carregamento síncrono (pelo menos alguns)

Agora vamos repetir a mesma coisa sem restrições na largura do canal. A imagem já está muito melhor: 0,452 segundo a FMP, a mais simples de todas! 13 ms. DCL - 953 ms, 15 ms simples. É assim que o download dos meus sonhos se parece. Foi exatamente o que aconteceu porque eu abri uma nova guia e não removi o cache. Vamos tentar a mesma coisa, mas sem um cache:


Agora que não há lugar


Tudo também é muito bom, FCP / FMP - 1689, carga útil de 45%. A propósito, ajustar a carga para 100% também é ruim, pois as máquinas mais fracas serão sobrecarregadas. Portanto, é melhor ter uma reserva para o tempo de inatividade. Mas aqui, inesperadamente, muito tempo foi gasto na renderização - 400 ms para o FMP. Desses, 200 ms entraram em recálculo de estilos e recálculo de layout.


A propósito, outro ponto interessante. Lembra dos scripts de anúncio - gpt.js e publishertag.js mencionados na primeira parte? Agora você pode ver que, apesar da assincronia, eles foram capazes (embora um pouco) de arruinar nossas estatísticas. Isso aconteceu porque a execução de scripts assíncronos é feita de acordo com a disponibilidade dos próprios scripts. I.e. isso pode acontecer a qualquer momento, inclusive antes do FCP / DCL, que ocorreu em 3309.


Então, fizemos a desmontagem manual. É hora de descobrir a automação.


Etapa Três - "Tivemos que começar com isso"


Sobre a fazenda coletiva

Acho que todo mundo entende que este estudo é muito arbitrário. Pelo menos, porque todo o tempo em que eu estava testando novos artigos apareceu, a carga no servidor e a carga nos backbones da rede mudaram. De uma maneira boa, você precisa implantar um servidor dedicado no qual ninguém escreverá nada, emulará a carga relevante com atrasos relevantes e somente então criará um perfil de algo. Caso contrário, você pode fazer algumas suposições (por exemplo, sobre a necessidade de adicionar um atributo de pré-carregamento no CSS), adicioná-lo, implantá-lo na produção e, em seguida, verifica-se que a carga durante o teste aumentou acentuadamente e o servidor nos forneceu o mesmo estilo 500 ms depois. E acontece que a pré-carga é ruim - apenas piorou tudo. E o autor é o último rabanete. Além disso, a criação de perfil manual (como na segunda parte), até você executar todas as ferramentas automáticas e resolver os problemas encontrados lá, também faz pouco sentido, porque após as primeiras alterações, a imagem muda.


Portanto, antes de qualquer experimento, precisamos do ambiente mais estável. Desta vez. A segunda - você nunca deve se aprofundar (por exemplo, na criação de perfil) desde o início. Inicie as ferramentas automáticas primeiro, deixe-as trabalhar para você. Colete relatórios, veja o que pode ser feito da melhor maneira possível em tempo mínimo. Tente fazer isso. Se possível, você já pode ter o suficiente. Por exemplo, seu css.bundle pesa 100kb, mas na realidade você precisa de 45kb (a propósito, a situação real: eles usaram o bootstrap inteiro, mas apenas a grade era necessária). Reduziram o tamanho dos estilos e ganharam meio segundo praticamente por nada. Estes são dois. Sempre verifique. Parece que os estilos estão alinhados, tudo deve melhorar, mas piora. Porque E porque nos estilos de 50kb imagens base64, e nossa página carregava apenas 200kb de recursos. Lembre-se de que não há bala de prata e scripts universais. Estes são três. E a última, mesmo que contradiga a frase anterior. Se você não possui um site complicado, basta monitorar o TTFB (problemas do servidor), o tamanho dos recursos baixados (olá para os logotipos de 2 MB) e não conceder acesso ao Gerenciador de tags do Google. Muito provavelmente isso será suficiente.


Não iremos muito longe, nas mesmas Ferramentas do desenvolvedor, abra a guia auditoria e inicie o LightHouse (LH) com as seguintes configurações: área de trabalho, somente desempenho, sem limitação, armazenamento limpo. Depois de esperar um pouco (não deixe a página em que a auditoria está sendo conduzida e não faça nada melhor), obtemos números fantásticos (mesmo com o cache desativado)


Na capa da minha mãe


Parece-me até que eles foram especialmente adaptados a esses números.


No entanto, o LH ainda reclama sobre:


  • Formato de imagem desatualizado (sugere o uso de webp, jpeg2000, etc.)
  • DOM node – : 2533, 1500.
  • — 23
  • document.write

. (), DOM — node (-), ( ), document.write- writer ( - )


( ) . , , , . , , . CSS, — , , JavaScript. , , . .


, fast3g , , ( I7, celeron):


A capa deve ser dobrada inteira


( FCP 3500 ms, FMP 5.7):


  • , . LH next-gen , , , 11
  • . adriver.js advertise.js 50 , .
  • CSS , 5kb 45kb.
  • main thread. JavaScript — (8.5 script evaluation 2186 ms raven.js). ?

? . - . :


  • DOM
  • JavaScript

, , (, raven.js).


, , — webpagetest.org


— , , . — , . , . , , . , , , — -.


https://habr.com ( ru/en ).


Em uma panela com leite.


( , )


. ( ) DNS (500 ms ), , ssl . , 1150 ms c ( ). , ( habrastorage).


main.bundle.css. , dr.habracdn.net , dns lookup — 36 ms ( 400 ms). SSL negotiation 606 ms, TTFB 601 ms, . . DCL — 4100 ms , .


image analysis , , . - PNG 1.4, webp + downscaling ( , ) — 17.7 KB. , , png 154. . , :


  • ( , , .. ).
  • . , .
  • TTFB (webpagetest F ) —
  • , ( )

Conclusões


. :


:


  • TTFB 500 ms ( dns, ssl initial connection)
  • habrastorage

:


  • DOM-a

, , . , , . , SPA, , JS — . . //,




PS.Peço desculpas pelo grande número de anglicismos (especialmente pelo layout) e pelo Longrid. Mas sem eles, é realmente difícil, e todas essas partes 1, 2, 3, eu já cansei do pedido.

Source: https://habr.com/ru/post/pt454444/


All Articles