Ottimizzazione di FCP/LCP tramite la memorizzazione nella cache delle ricerche del modulo raw-view

Sto cercando di migliorare First Contentful Paint (FCP) e Largest Contentful Paint (LCP) con queste due PR:

Sono molto interessato all’impatto effettivo di queste modifiche, quindi provate a darle un’occhiata e a fornire un feedback.

Naturalmente, qualsiasi aiuto per il testing, il refactoring e la copertura dei test è più che benvenuto.

11 Mi Piace

Il primo sembra un’ottimizzazione semplice che penso abbia senso, @david e @eviltrout hanno dedicato del tempo all’ottimizzazione di quest’area, quindi sarò molto curioso di vedere cosa ne pensano.

Il secondo sembra un po’ più fragile a lungo termine, capisco totalmente il desiderio di ottimizzare, ma mi preoccupa un po’ perché sarà un’area che dovremo mantenere.

5 Mi Piace

Ciao @rrit - grazie per le PR. La prima sembra un buon miglioramento. Sei riuscito a misurare l’impatto sulle prestazioni? Quanto tempo fa risparmiare?

Come ha detto @sam, la manutenibilità della seconda è un po’ preoccupante. Sembra una copia/incolla dal codice sorgente di Ember? Hai cambiato qualcosa per migliorare le prestazioni?

4 Mi Piace

lookupView-patch

Implementato ora tramite Map invece di Array.

Tempo impiegato all’avvio dell’applicazione in lookupView - per istanza di sviluppo:

Tempo risparmiato: ~115 ms

Questo riduce il tempo impiegato all’interno di appendOutletView da 1.083 ms a 946 ms - per istanza di sviluppo.


patch su helper handlebar grezzi

Sì, è in realtà un copia-incolla con una modifica: usa un controllo economico per isPath.

      // sostituisce @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;

Ad esempio, renderTopicListItem attiva in definitiva molte chiamate a _getPath (altri 50-100 ms da risparmiare):
Firefox Profiler (callstack filtrato su _getPath all’interno di renderTopicListItem)

Forse le chiamate costose a _getPath sono qualcosa da ottimizzare in Ember.js e non in Discourse.


E dai un’occhiata a Firefox Profiler per avere qualche informazione sull’esecuzione di JavaScript:

4 Mi Piace

Grazie per le patch. La seconda sembra un po’ fragile.

I tuoi benchmark vengono eseguiti in modalità di sviluppo o in modalità di produzione? Ember ha un profilo piuttosto diverso in entrambi i casi.

2 Mi Piace

@david ha trovato un ottimo modo per risolvere questo problema: vedi il suo commento su github.

Il tempo per le chiamate a renderTopicListItem sulla pagina web ‘latest’ scende da 348 ms a 201 ms in una build ‘production’ di Ember.

I benchmark precedenti venivano ancora eseguiti in modalità di sviluppo.


Come posso eseguire benchmark in modalità di produzione Ember.js?

# Avvia ember in modalità di produzione
d/ember-cli server --environment="production"
2 Mi Piace

Sfortunatamente non sono riuscito a replicare questo grande aumento di velocità. Su Firefox e Chrome (macOS) non vedo alcun miglioramento misurabile. Chrome impiega circa 23 ms in renderTopicListItem. Firefox 30 ms. Su un vecchio dispositivo Android (Pixel 3), vedo circa 108 ms. I numeri non sembrano cambiare prima/dopo la modifica.

A proposito, ho misurato questi numeri utilizzando l’API performance. Ho aggiunto performance.mark("rtli-start") all’inizio di renderTopicListItem, e poi performance.measure("rtli", "rtli-start") alla fine.

Quindi ricarico il browser con gli strumenti di sviluppo chiusi e i plugin del browser disabilitati (gli strumenti di sviluppo e i plugin del browser possono influire in modo significativo sulle prestazioni di rendering). Poi, dopo che il caricamento è completo, apro gli strumenti di sviluppo ed eseguo questo per sommare le misurazioni:

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

Certamente uniremo questa modifica: è chiaramente un’implementazione migliore. Ma non sono sicuro che ci darà una differenza visibile nelle prestazioni di rendering :thinking:

7 Mi Piace

Posso ancora riprodurre i vantaggi in termini di prestazioni utilizzando l’API delle prestazioni in modalità privata di Firefox (Linux).

Testando http://localhost:4200/latest
Il tempo impiegato in renderTopicListItem è sceso a circa 190 ms da circa 290 ms.

La mia istanza di test di Discourse ha molti argomenti con molte risposte e molti autori diversi - dati estratti da un’istanza produttiva. Ciò si traduce in molti elementi da renderizzare.
Forse questa è la differenza nei nostri benchmark?


Pre-rendering del contenuto sotto la piega

Discourse pre-renderizza 30 argomenti nella pagina ‘latest’. Quindi il contenuto viene visualizzato per la prima volta (FCP). Sopra la piega sono visibili solo circa 12 argomenti.

Lo stesso per una pagina di argomento: 20 post pre-renderizzati, ma al massimo 6 post su una riga sono visibili sopra la piega.

Questo potrebbe essere un altro punto di ottimizzazione per FCP.

1 Mi Piace

Ti dispiacerebbe condividere la versione di Firefox e del sistema operativo? Il numero 290ms è quasi 3 volte più lento di un dispositivo Android del 2018, il che è un po’ sorprendente.

Potrebbe spiegare parte della differenza, sì. Nel mio caso, li ho eseguiti utilizzando dati live da Meta:

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

Sì, questo è un possibile miglioramento. Tuttavia, dovremo fare molta attenzione che il layout e/o lo scorrimento non saltino (ad esempio, se l’utente aggiorna la pagina quando è già a metà pagina). La definizione di ‘sotto la piega’ varia anche in base al dispositivo/browser/tema.

3 Mi Piace

Proxy per meta.discourse.org

Purtroppo, l’esecuzione di ember con un proxy non funziona per me:

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

http://localhost:4200/

Discourse Build Error

Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP non corrisponde ai nomi alternativi del certificato:
Host: localhost. non è nei nomi alternativi del certificato: DNS:*.cdck-prod-meta.discourse.cloud

http://127.0.0.1:4200/

Discourse Build Error

Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP non corrisponde ai nomi alternativi del certificato:
Host: meta.discourse.org. non è nei nomi alternativi del certificato: DNS:*.cdck-prod-meta.discourse.cloud

Sistema utilizzato per i benchmark

Estratto da Firefox about:support

Nome Firefox
Versione 95.0.2
Build-ID 20211219102529
Distributions-ID 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
File dell’applicazione /snap/firefox/777/usr/lib/firefox/firefox
Nome Firefox Developer Edition
Versione 96.0b10
Build-ID 20211228195952
Directory di aggiornamento /opt/firefox-dev-autoinstall
Canale di aggiornamento 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
File dell’applicazione /opt/firefox-dev-autoinstall/firefox-bin

Estratto da Chromium chrome://system/

CHROME VERSION 90.0.4430.212 built on Debian 10.9, running on Debian 10.11
OS VERSION Linux: 5.10.0-0.bpo.9-amd64

Versione 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 Mi Piace

Il PR per il refactoring è ora unito:

Grazie per aver sollevato questo problema @rrit - è un bel miglioramento!

5 Mi Piace

Questo argomento è stato chiuso automaticamente dopo 9 ore. Non sono più consentite nuove risposte.