Optimización de FCP/LCP mediante el almacenamiento en caché de búsquedas de módulos raw-view

Estoy intentando mejorar First Contentful Paint (FCP) y Largest Contentful Paint (LCP) con estas dos PR:

Estoy muy interesado en el impacto real de estos cambios, ¡así que por favor pruébalos y da tu opinión!

Y, por supuesto, cualquier ayuda para probar, refactorizar y cubrir pruebas es más que bienvenida.

11 Me gusta

El primero parece una optimización sencilla que creo que tiene sentido, @david y @eviltrout dedicaron tiempo a optimizar esta área, así que tendré mucha curiosidad por ver qué piensan al respecto.

El segundo se siente un poco más frágil a largo plazo, entiendo totalmente el deseo de optimizar, pero me preocupa un poco porque será un área que necesitaremos mantener.

5 Me gusta

Hola @rrit: gracias por las PR. La primera parece una buena mejora. ¿Pudiste medir el impacto en el rendimiento? ¿Cuánto tiempo ahorra?

Como dijo @sam, la mantenibilidad de la segunda es un poco preocupante. ¿Parece una copia/pega del código fuente de Ember? ¿Cambiaste algo para mejorar el rendimiento?

4 Me gusta

lookupView-patch

Implementado ahora a través de Map en lugar de Array.

Tiempo dedicado al arranque de la aplicación en lookupView - para instancia de desarrollo:

Tiempo ahorrado: ~115 ms

Esto disminuye el tiempo dedicado dentro de appendOutletView de 1.083 ms a 946 ms - para instancia de desarrollo.


patch en helpers de handlebar crudos

Sí, en realidad es un copiar y pegar con un cambio: usar una comprobación económica para isPath.

      // reemplaza @ember/-internals/utils isPath
      // @see: https://github.com/emberjs/ember.js/blob/3537670c14883346e11e841fcb71333384fcbc87/packages/%40ember/-internals/metal/lib/path_cache.ts#L5-L7
      // @see: https://github.com/emberjs/ember.js/blob/255a0dd3c7de1187f4a2f61a97cf78bfff8f66a8/packages/%40ember/-internals/glimmer/lib/utils/bindings.ts#L70
      let isPath = context.indexOf('.') > -1;

Por ejemplo, renderTopicListItem finalmente activa muchas llamadas a _getPath (otros 50-100 ms que ahorrar):
Firefox Profiler (callstack filtrado a _getPath dentro de renderTopicListItem)

Quizás las llamadas costosas a _getPath sean algo a optimizar en Ember.js y no en Discourse.


Y echa un vistazo a Firefox Profiler para obtener información sobre la ejecución de JavaScript:

4 Me gusta

Gracias por los parches. El segundo parece un poco frágil.

¿Se están ejecutando sus benchmarks en modo de desarrollo o en modo de producción? Ember tiene un perfil bastante diferente en ambos.

2 Me gusta

@david encontró una excelente manera de solucionar este problema: consulta su comentario en github.

El tiempo de las llamadas a renderTopicListItem en la página web ‘latest’ se reduce de 348 ms a 201 ms en una compilación de producción de Ember.

Los benchmarks anteriores todavía se ejecutaban en modo de desarrollo.


¿Cómo puedo ejecutar benchmarks en modo de producción de Ember.js?

# Inicia ember en modo de producción
d/ember-cli server --environment="production"
2 Me gusta

Desafortunadamente, no he podido replicar este gran aumento de velocidad. En Firefox y Chrome (macOS) no veo ninguna mejora medible. Chrome gasta alrededor de 23 ms en renderTopicListItem. Firefox 30 ms. En un dispositivo Android antiguo (Pixel 3), veo alrededor de 108 ms. Los números no parecen cambiar antes/después del cambio.

Por cierto, medí estos números usando la API de rendimiento. Añadí performance.mark("rtli-start") al principio de renderTopicListItem, y luego performance.measure("rtli", "rtli-start") al final.

Luego recargo el navegador con las herramientas de desarrollador cerradas y los complementos del navegador deshabilitados (las herramientas de desarrollador y los complementos del navegador pueden afectar significativamente el rendimiento de renderizado). Luego, después de que la carga se complete, abro las herramientas de desarrollador y ejecuto esto para sumar las mediciones:

performance.getEntriesByName("rtli").reduce((v, m) => v + m.duration, 0);

Definitivamente fusionaremos este cambio, es claramente una mejor implementación. Pero no estoy seguro de si nos dará una diferencia visible en el rendimiento de renderizado :thinking:

7 Me gusta

Todavía puedo reproducir los beneficios de rendimiento utilizando la API de rendimiento en el modo privado de Firefox (Linux).

Probando http://localhost:4200/latest
El tiempo dedicado a renderTopicListItem se reduce de ~290 ms a ~190 ms.

Mi instancia de prueba de Discourse tiene muchos temas con muchas respuestas y muchos autores diferentes: datos extraídos de una instancia productiva. Esto da como resultado muchos elementos para renderizar.
¿Quizás esta sea la diferencia en nuestros benchmarks?


Pre-renderizado de contenido debajo del pliegue

Discourse pre-renderiza 30 temas en la página ‘latest’. Luego, el contenido se muestra por primera vez (FCP). Encima del pliegue solo son visibles ~12 temas.

Lo mismo para una página de tema: se pre-renderizan 20 publicaciones, pero como máximo 6 publicaciones de una línea son visibles encima del pliegue.

Este podría ser otro punto de optimización para FCP.

1 me gusta

¿Podrías compartir la versión de Firefox y del sistema operativo? El número de 290 ms es casi 3 veces más lento que un dispositivo Android de 2018, lo cual es un poco sorprendente.

Eso podría explicar parte de la diferencia, sí. En mi caso, los ejecuté usando datos en vivo de Meta:

bin/ember-cli --environment production --proxy https://meta.discourse.org

Sí, esta es una posible mejora. Sin embargo, tendremos que tener mucho cuidado de que el diseño y/o el desplazamiento no salten (por ejemplo, si el usuario actualiza la página cuando ya está desplazado hasta la mitad). La definición de ‘debajo del pliegue’ también varía según el dispositivo/navegador/tema.

3 Me gusta

Proxy a meta.discourse.org

Desafortunadamente, ejecutar ember con un proxy me falla:

d/ember-cli --environment production --proxy https://meta.discourse.org

http://localhost:4200/

Discourse Build Error

Error [ERR_TLS_CERT_ALTNAME_INVALID]: El nombre de host/IP no coincide con los nombres alternativos del certificado:
Host: localhost. no está en los nombres alternativos del certificado: DNS:*.cdck-prod-meta.discourse.cloud

http://127.0.0.1:4200/

Discourse Build Error

Error [ERR_TLS_CERT_ALTNAME_INVALID]: El nombre de host/IP no coincide con los nombres alternativos del certificado:
Host: meta.discourse.org. no está en los nombres alternativos del certificado: DNS:*.cdck-prod-meta.discourse.cloud

Sistema utilizado para las pruebas de rendimiento

Extraído de Firefox about:support

Nombre Firefox
Versión 95.0.2
ID de compilación 20211219102529
ID de distribución canonical-002
User-Agent Mozilla/5.0 (X11; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0
Sistema operativo Linux 5.10.0-0.bpo.9-amd64 #1 SMP Debian 5.10.70-1~bpo10+1 (2021-10-10)
Tema del sistema operativo Adwaita-dark / Adwaita
Archivo del programa de aplicación /snap/firefox/777/usr/lib/firefox/firefox
Nombre Firefox Developer Edition
Versión 96.0b10
ID de compilación 20211228195952
Directorio de actualización /opt/firefox-dev-autoinstall
Canal de actualización aurora
User-Agent Mozilla/5.0 (X11; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0
Sistema operativo Linux 5.10.0-0.bpo.9-amd64 #1 SMP Debian 5.10.70-1~bpo10+1 (2021-10-10)
Tema del sistema operativo Adwaita-dark / Adwaita
Archivo del programa de aplicación /opt/firefox-dev-autoinstall/firefox-bin

Extraído de Chromium chrome://system/

VERSIÓN DE CHROME 90.0.4430.212 compilado en Debian 10.9, ejecutándose en Debian 10.11
VERSIÓN DEL SISTEMA OPERATIVO Linux: 5.10.0-0.bpo.9-amd64

Versión del sistema operativo:

# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
2 Me gusta

La PR de la refactorización ya se ha fusionado:

Gracias por plantear esto, @rrit, ¡es una buena mejora!

5 Me gusta

Este tema se cerró automáticamente después de 9 horas. Ya no se permiten nuevas respuestas.