Perfilamos la carga de Habr o cómo 189 solicitudes en la página representan influencia

Toma jugo de cereza espeso


Hace algún tiempo, me interesé en el rendimiento del sitio web, las optimizaciones de descarga y similares. Y ahora, una vez más yendo al Habr, pensé que estaba acostumbrado a percibir una carga de recursos bastante rápida como algo dado, sin siquiera pensar en cómo se logró esto. Por lo tanto, decidí combinar negocios con placer, para ver cómo van las cosas con el rendimiento de Habr y qué soluciones técnicas se hicieron para optimizarlo.


Para aquellos que estén interesados ​​en saber lo que se ha hecho para que recibamos el contenido lo más rápido posible y cómo se ve la descarga del Habr de Argentina, por favor, bajo cat.


Preparación


Necesitaremos una versión nueva de Chrome / Canary que funcione en modo anónimo (asegúrese de que todas las extensiones estén desactivadas). Además, en la Consola de desarrollador (Herramientas de desarrollador - F12), en la pestaña de red, debe establecer el indicador de deshabilitar caché, porque Solo perfilaremos el primer arranque, aunque todavía no hay recursos en el caché.


Etapa uno - "Arriba"


El objetivo principal de esta parte es familiarizarse con el sitio en su conjunto, comprender su estructura y descubrir qué recursos específicos necesita.


Abrimos herramientas para desarrolladores, vamos a la pestaña de red, abrimos el sitio y en la parte inferior de la pestaña miramos las estadísticas sobre el uso de la red:


Y una capa blanca de madre.


Todo el sitio se cargó en 2.02 segundos, lo que se ve genial (considerando la carga de Habr). El evento DomContentLoaded (en adelante, simplemente DCL) generalmente apareció en 1.01 segundos, lo que se ve aún mejor. Con todo esto, el sitio realiza 189 solicitudes y carga 9.6MB de recursos. Esto nos dice que o bien el equipo de Habra es un genio (puede serlo), y que el artículo debería estar terminado aquí (y pedirles al equipo café y galletas), o recordar que tengo un canal de 100 Mb / sy Core I7 . Es decir necesita acercarse un poco más a la realidad y al menos limitar el ancho del canal.


Activamos el modo Fast 3G y volvemos a mirar:


Vierta suavemente el jugo sobre la capa -


DCL empeoró a 3.48 segundos, lo que aún es razonablemente aceptable. Pero finalmente el sitio se cargó en ateo 54.76 segundos. Ahora todo es lógico: no puede descargar y descargar casi 10 megabytes cuando tiene una conexión débil. Lo más probable es que los chicos hicieron un buen trabajo para mostrarnos el contenido lo más rápido posible (esto se evidencia por el hecho de que incluso en modo fast3g DCL surge lo suficientemente rápido), y dejaron todo lo que no era crítico para cargar en segundo plano. Comprobaremos esto un poco más tarde, y ahora veamos por qué cargamos tanto tiempo. Ordenar todas las solicitudes por tiempo de carga:


Aparecerá un lugar.
Clickable


Las imágenes (top-7) se cargan más tiempo y un archivo JavaScript es prebid.js. Si observamos su tamaño, podemos suponer que esta es precisamente la razón de la carga lenta.


Sobre supuestos

Con suposiciones debes ser extremadamente cuidadoso. Por ejemplo, una carga prolongada de un recurso puede ser causada no solo por el tamaño del archivo, sino también, por ejemplo, por problemas con el DNS, la carga máxima de almacenamiento o la caché del servidor en frío. Por lo tanto, una suposición no verificada puede hacer que pierda el tiempo resolviendo un problema que ni siquiera existe.


Mirando las estadísticas ( TTFB : 0.610 ms, carga: 40 000 ms), podemos concluir que nuestra suposición es bastante probable. Admiramos nuestro TOP 1 (png, 1560X780, 24 bits):


Ahora que no hay lugar


De hecho, los problemas con las imágenes son principalmente problemas de nuestro tráfico con usted. Las imágenes (a diferencia de los estilos y las secuencias de comandos) no bloquean la representación de la página web y, por lo tanto, a pesar de la presencia de esos pesos pesados ​​(puede ser peor, lo vieron), esto casi no tiene efecto en el rendimiento. Aunque, por supuesto, la optimización en esta dirección (por ejemplo, la transcodificación a jpeg2000 o webp, o la carga progresiva no sería superflua).


Sobre imagenes

Como escribí anteriormente, las imágenes no bloquean la representación de la página. Pero usan nuestro grupo de conexiones, y en http 1.x su número es limitado, y con http 2.xy Chrome también, no todo es tan fácil como escuché. Por lo tanto, incluso aquí existe la posibilidad de que alguna imagen ralentice la carga de una secuencia de comandos síncrona, y que, a su vez, ya deje de mostrar la página. Además, cargar la imagen también puede causar un recuento del diseño, lo que ralentiza el renderizado. Si observamos el marcado de Habr, casi todas las etiquetas img tienen ancho y alto. Esto elimina la necesidad de reflujo para impactar positivamente el rendimiento de descarga. Puedes leer más sobre esto aquí .


Veamos qué otros recursos extrae el Habr: repasaremos los tipos y los ordenaremos por tiempo de carga. Comencemos con JavaScript


Javascript


Sobre javascript

JavaScript tiene varios problemas en términos de rendimiento del sitio. En primer lugar (todo el mundo lo sabe desde hace mucho tiempo), js síncrono bloquea la representación de páginas adicionales. Es decir hasta que recibamos y ejecutemos nuestro JavaScript, el navegador esperará (en realidad no del todo, el navegador, especialmente Chrome, puede optimizar, pero esta es otra historia) y no mostrará más contenido. Usando scripts síncronos en la cabeza, posponemos el momento en que el usuario ve al menos algo (incluso texto). Por lo tanto, todos están tratando de lanzar Js al final de la página o incluso hacerlo asíncrono. Esto funciona, pero no resuelve el segundo problema que nos trae el hecho de que JavaScript sigue siendo un lenguaje de secuencias de comandos. Por lo tanto, el navegador no es suficiente solo para descargarlo, sino que también debe ser "entendido". Y aquí, resulta que este es un problema, porque los procesadores débiles (por ejemplo, en teléfonos o netbooks baratos, o incluso en computadoras portátiles buenas en modo de rendimiento limitado) lo hacen lentamente, bloqueando el hilo principal. A continuación se muestra un ejemplo de cómo un guión publicitario asíncrono entró en la sección crítica del renderizado de Habr y aunque fue un poco, pero aún estropeó el rendimiento. Si alguien está interesado, hay un muy (muy, muy) buen artículo sobre este tema.


Las secuencias de comandos de Habr se cargan mucho: 1.1 MB (y esto ya está en forma comprimida) para 40 solicitudes. Esto es francamente significativo, todavía nos llega y necesitamos hacer algo al respecto. Ordene nuestros guiones "por la cascada". Nuestra tarea es encontrar scripts que se carguen ANTES de la línea azul, ya que son ellos (muy probablemente) los que nos impiden mostrar el sitio lo más rápido posible.


En la capa de mi madre
Clickable


Abrimos el html que Habr nos dio (es importante mirar la respuesta, ya que el html final se verá diferente) y revisaremos la lista. Como puede ver, jQuery, raven.js, advert.js y adriver.js se cargan sincrónicamente directamente desde la etiqueta principal (es decir, bloquean todo). Gpt y Publisher se cargan desde head pero ya de forma asincrónica (es decir, no bloquean nada, el navegador mostrará la página más mientras se está cargando). Los proveedores, Main y Math, checklogin se cargan al final, pero sincrónicamente (es decir, el texto ya está allí, podemos leerlo, pero el DCL no aparecerá hasta que se carguen). El resto no aparece en la respuesta inicial: se agregan dinámicamente, pero este es otro tema.


Entonces, encontramos esos scripts que de alguna manera afectan la rapidez con que vemos el texto en la página. Estos son los primeros candidatos para la optimización. Idealmente, deben hacerse asíncronos o colocarse lo más bajo posible para permitir que el navegador muestre contenido para nosotros. Sin embargo, el ideal no se puede lograr, ya que lo más probable es que haya otros scripts en el sitio que dependan del mismo jQuery. También se puede entender el deseo de descargar raven lo antes posible: una biblioteca para rastrear varios errores que ocurren en el cliente. Pero advert.js y adriver.js ya son candidatos reales para al menos desplazarse hacia abajo en la página, y como máximo también en modo asíncrono. Una historia similar con gpt y editor. Sí, se cargan de forma asincrónica, pero, sin embargo, pueden (e interferirán) con nosotros al cargar. Por lo tanto, también podrían enviarse al final de la página. Además, puede intentar usar los atributos de Sugerencias de recursos : preload / prefetch / dns-prefetch para decirle al navegador qué cargar por adelantado. Por cierto, le aconsejo que lea sobre Sugerencias de recursos, una herramienta muy interesante, aunque con soporte limitado (hasta ahora).


Ahora ordena la lista por tamaño de archivo:


La capa debe estar metida entera
https://github.com/Drag13/articles/blob/habrformance/habrformance/scripts.PNG


Vemos un script que se carga dos veces (pubads). También notamos que prebid.js se carga desde la carpeta no para productos


En espeso jugo de cereza.


Para despejar nuestra conciencia, verificamos que todos los guiones estén minificados. De repente, los scripts check-login.js y adriver.js no fueron minimizados. Especialmente satisfecho con el contenido de este último:


Toma una capa de cereza


Y con los scripts puedes terminar temporalmente.


Estilos


Sobre estilos

Con los estilos, tampoco todo es tan simple. En primer lugar, la carga sincrónica de estilos también bloquea el hilo principal (aunque se analizan rápidamente, más rápido que JavaScript). Y en segundo lugar, todo es un poco más complicado. ¿Por qué el navegador necesita CSS? Para construir CSSOM . ¿Qué puede hacer JavaScript con CSS? Así es, cambio. ¿Y qué sucederá si CSSOM aún no está construido y js ya está tratando de cambiar algo allí? La respuesta es quién sabe. Por lo tanto, el navegador retrasa la ejecución de JavaScript hasta que se calcula el CSSOM. Como está escrito correctamente en otro artículo muy útil : sin CSS = sin JavaScript. Por lo tanto, cargar CSS bloquea la ejecución de JS.


Estos son los estilos que carga Habr:


Y una jarra de leche.
Clickable


Como puede ver, solo hay tres de ellos, con el segundo y el tercero cargados en un marco separado, por lo que los ignoramos. Pero el primer conjunto de estilos es crucial para todo el sitio. Y lo descargamos durante mucho tiempo. Por qué En primer lugar, esperaron mucho tiempo por una respuesta del servidor (TTFB 570 ms, volveremos a ello en la tercera sección), y en segundo lugar, se cargaron 713 ms durante mucho tiempo. ¿Qué se puede hacer aquí? La primera y más simple es intentar agregar el atributo de precarga. Esto hará que el navegador comience a cargar CSS lo antes posible. La segunda opción es resaltar CSS crítico e incrustarlo directamente en la página web, y cargar el resto sincrónicamente (o incluso asincrónicamente). Esto conducirá a un aumento en el tamaño de la página (pero ya no es pequeño y + 5kb no estropeará nada) y a un posible rediseño del diseño (pérdida de tiempo), pero puede intentarlo.


Ni siquiera mostraré las fuentes. Está allí solo, aunque por alguna razón se carga directamente desde el servidor Habr en lugar de la CDN (y muy probablemente por alguna razón). Pero diré gracias por el hecho de que solo hay una fuente.


En esto, la parte general del análisis del sitio se puede considerar completada. Es hora de ir más profundo.


Etapa dos - "Modo manual"


En la última etapa vimos que Habr carga. Ahora veremos cómo se representa esto.


Vaya a la pestaña de perfiles. Verificamos qué ralentización es fast3g (luego ejecutamos nuevamente sin restricciones) y ejecutamos. En primer lugar, estamos interesados ​​en todo lo que sucede antes del evento First contentful paint (FCP) y, por si acaso, DCL. Seleccionamos el área desde el inicio de la carga en FCP y miramos el diagrama final.


Vierte la leche pensada -


Todo sucede bastante rápido: 2.161 segundos antes del FCP (fue más rápido, pero aparentemente algo había cambiado), pero como puede ver, la mayoría de las veces el navegador estaba inactivo. La carga útil solo tomó el 14% del tiempo (aproximadamente 310 ms). Idealmente, el subproceso principal del navegador se ejecuta continuamente: al analizar html, CSS, se ejecuta JS. Y aquí, nada. Por qué Porque el navegador simplemente no tenía nada que hacer. ¿Recuerdas que redujimos el tráfico? El navegador ha enviado solicitudes y ahora solo espera a que se completen. Si abrimos el diagrama de los procesos de red (el más alto) todo se aclarará de inmediato.


Aparecerá un lugar.
Clickable


En 2029, el navegador vio main.bundle.css, envió una solicitud para recibirlo y comenzó a esperar. En este momento, el preescaner (smart chrome, puede ejecutarse por delante) descubrió que hay scripts síncronos a continuación y, sin esperar a que css llegue, envió una solicitud de scripts. Luego anuncie y cargue un controlador (pero recordamos que si bien CSSOM no se crea, no puede tocar JS), por lo que el navegador los ignoró. Después de eso, gpt y raven se cargaron, pero el CSS todavía se estaba cargando, por lo que también se ignoraron. Finalmente, se cargó CSS, que el navegador analizó en 12 ms e inmediatamente fue a analizar el JS incrustado en la página. Luego, el navegador volvió a "quedarse dormido" a casi 150 ms esperando jQuery.min.js. Y después de eso ya comencé a trabajar en serio: descubrí el jQuery cargado (20 ms), analicé raven.js (4 ms), analicé casi toda la página (36 ms), volví a contar los estilos (28 ms), calculé el diseño (78 ms + 8 ms) y, finalmente, durante ~ 6 ms, pintamos la página. Aquí tenemos FCP. A continuación, analizamos la página, analizamos los scripts: hola a nadie (publishertag.js, gpt.js que se metió en el hilo principal antes de DCL), jugamos un poco con los estilos (lo que causó una ligera pérdida de tiempo debido al recálculo del diseño) y comenzamos a esperar a los proveedores. bundle.js. Con el fin de esperar a los vendedores, pasamos casi inactivos otros 1100 ms. Es cierto que, en paralelo, también cargamos main.bundle.js (que, por cierto, arrancó más rápido), por lo que no todo es tan malo. Entonces todo volvió a salir bien. Analizamos los proveedores, analizamos el paquete principal, analizamos Math.Jax y finalmente analizamos la página y obtuvimos DCL. Es cierto que algún tipo de controlador funcionó allí, lo que en mi I7 detuvo el hilo principal a 80 ms (es decir, el sitio pareció congelarse a 80 ms). Ahora casi no nos damos cuenta de esto, pero en un procesador débil, teóricamente, puede ser notable. Si ves esto después de que se muestra el contenido, esta es una ocasión para comprobar JS.


Que puedo decir De nuevo, a pesar de que se ve bastante bien. Los principales problemas nos fueron entregados:


  • Un navegador grande y simple (incluso debido al desequilibrio artificial entre la potencia informática de la computadora y el ancho del canal, pero este también es un escenario bastante válido)
  • Larga carga de CSS que retrasó el trabajo con js críticos
  • Carga sincrónica de jQuery, proveedores y paquetes principales que detuvieron la aparición de contenido.

Lo que podemos hacer con esto ya lo hemos discutido:


  • Intente agregar el atributo de precarga para CSS y tal vez algo de JS
  • Reducir o CSS en línea
  • Intente generalmente lanzar scripts fuera de la carga síncrona (al menos algunos)

Ahora repitamos lo mismo sin restricciones en el ancho del canal. La imagen ya es mucho mejor: 0.452 segundos a FMP, ¡la más simple de todas! 13 ms. DCL - 953 ms, simple 15 ms. Así es como se ve la descarga de mis sueños. Eso es exactamente lo que sucedió porque abrí una nueva pestaña y no eliminé el almacenamiento en caché. Probemos lo mismo, pero sin un caché:


Ahora que no hay lugar


Todo también es bastante bueno, FCP / FMP - 1689, carga útil 45%. Por cierto, ajustar la carga al 100% también es malo, ya que las máquinas más débiles se sobrecargarán. Por lo tanto, es mejor tener una reserva para el tiempo de inactividad. Pero, inesperadamente, aquí se dedicó mucho tiempo a la representación: 400 ms para FMP. De estos, 200 ms fueron a recálculo de estilos y recálculo de diseño.


Por cierto, otro punto interesante. ¿Recuerdas los guiones de anuncios: gpt.js y publishertag.js que se mencionaron en la primera parte? Ahora puede ver que, a pesar de su asincronía, pudieron (aunque sea un poco) arruinar nuestras estadísticas. Esto sucedió porque la ejecución de los scripts asincrónicos se realiza de acuerdo con la disponibilidad de los mismos scripts. Es decir Esto puede suceder en cualquier momento, incluso antes de FCP / DCL, que ocurrió en 3309.


Entonces, hicimos el desmontaje manual. Es hora de descubrir la automatización.


Etapa tres: "Teníamos que comenzar desde esto"


Sobre la granja colectiva

Creo que todos entienden que este estudio es muy arbitrario. Al menos, porque todo el tiempo, mientras estaba probando nuevos artículos aparecían, la carga en el servidor y la carga en la red troncal cambiaban. En el buen sentido, debe implementar un servidor dedicado en el que nadie escriba nada, emule la carga relevante con demoras relevantes y solo luego haga un perfil. De lo contrario, puede hacer algunas suposiciones (por ejemplo, sobre la necesidad de agregar un atributo de precarga en CSS), agregarlo, implementarlo en producción, y luego resulta que la carga durante la prueba aumentó considerablemente y el servidor nos dio el mismo estilo 500 ms después. Y resulta que la precarga es mala, simplemente empeoró todo. Y el autor es el último rábano en absoluto. Además, la creación de perfiles manualmente (como en la segunda parte), hasta que elimine todas las herramientas automáticas y resuelva los problemas encontrados allí, también tiene poco sentido, porque después de sus primeros cambios, la imagen cambiará.


Por lo tanto, antes de cualquier experimento, necesitamos el entorno más estable. Esta vez El segundo: nunca debe profundizar (por ejemplo, en la creación de perfiles) desde el principio. Inicie las herramientas automáticas primero, deje que trabajen para usted. Recopile informes, vea qué se puede hacer lo mejor posible en un tiempo mínimo. Intenta hacerlo. Si es posible, es posible que ya tenga suficiente. Por ejemplo, su css.bundle pesa 100kb, pero en realidad necesita 45kb (por cierto, la situación real: tomaron todo el arranque, pero solo se necesitaba la cuadrícula). Redujeron el tamaño de los estilos y ganaron medio segundo prácticamente por nada. Estos son dos Siempre verifique dos veces. Parece que los estilos están en línea, todo debería mejorar, pero empeorará. Por qué Y porque en los estilos de 50kb de imágenes base64, y nuestra página acaba de cargar 200kb de recursos. Solo recuerda que no hay bala de plata y guiones universales. Estos son tres. Y la última, incluso si contradice la oración anterior. Si no tiene un sitio complicado, solo controle TTFB (problemas del servidor), el tamaño de los recursos descargados (hola a los logotipos por 2 MB) y no le dé acceso al Administrador de etiquetas de Google a nadie. Lo más probable es que esto sea suficiente.


No iremos muy lejos, en las mismas Herramientas para desarrolladores, abra la pestaña de auditoría e inicie LightHouse (LH) con la siguiente configuración: escritorio, solo rendimiento, sin limitación, almacenamiento limpio. Después de esperar un poco (no salga de la página en la que se realiza la auditoría y no haga nada mejor) obtenemos números fantásticos (incluso con el caché deshabilitado)


En la capa de mi madre


Incluso me parece que estaban especialmente diseñados para estas figuras.


Sin embargo, LH todavía se queja de:


  • Formato de imagen desactualizado (sugiere usar webp, jpeg2000, etc.)
  • DOM node – : 2533, 1500.
  • — 23
  • document.write

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


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


, fast3g , , ( I7, celeron):


La capa debe estar metida entera


( 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 ).


En una sartén con leche.


( , )


. ( ) 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 ) —
  • , ( )

Conclusiones


. :


:


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

:


  • DOM-a

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




PS. Pido disculpas por la gran cantidad de anglicismos (especialmente por el diseño) y por Longrid. Pero sin ellos, es realmente difícil, y todas estas partes 1, 2, 3, ya me cansé del orden.

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


All Articles