2013-02-27 21 views
12

L'API JavaScript Object.observe() consente a qualsiasi parte di codice di ricevere notifiche di modifica per tutte le modifiche di proprietà di qualsiasi oggetto JavaScript.In che modo Object.observe() influisce sulle prestazioni?

Questo non influisce gravemente sulla generazione del codice e sulle ottimizzazioni delle prestazioni che possono essere eseguite dal motore JavaScript (ad es. V8)? Sembra che il codice nativo generato ora debba controllare ogni singola scrittura dell'oggetto se deve essere generata una notifica di modifica. Non è possibile determinare staticamente se un determinato oggetto ha impostato o meno notifiche. Quindi i controlli non possono essere ottimizzati.

Sembra che qualsiasi motore JavaScript conforme sia ora bloccato in una permanente e grave perdita di prestazioni dovuta a questa API.

+0

"* Non è possibile determinare in modo statico se un determinato oggetto ha impostato le notifiche *" - Perché? – Bergi

+0

@ Bergi come lo faresti? Staticamente significa senza eseguire il codice o ispezionare un oggetto. – usr

risposta

17

moderna JavaScript utilizzano caching in linea e tecniche di ricompilazione adattiva per minimizzare l'impatto dell'invio dinamico sul codice generato.

Se stiamo parlando di V8, il fatto che l'oggetto sia osservato o meno è codificato nella sua classe nascosta. Sia gli stub di cache inline che il codice ottimizzato già controllano la classe nascosta rispetto ad alcuni valori attesi per determinare se un oggetto ha una forma prevista o meno. Lo stesso controllo fornisce informazioni sul fatto che l'oggetto sia osservato o meno. Quindi nulla cambia sui percorsi del codice che funzionano con oggetti non osservati. Iniziare a osservare l'oggetto viene trattato allo stesso modo della sua modifica: la classe nascosta dell'oggetto viene passata a un'altra, con un set di bit osservato: puoi leggere Runtime_SetIsObserved per vederlo.

Il ragionamento simile si applica alle parti del sistema che omettono le guardie nel codice ottimizzato e invece deoptimizzano il codice in base alle ipotesi di "forma": una volta che un oggetto viene osservato, tutto il codice ottimizzato in base all'assunzione che tale oggetto non è stato osservato essere deottimizzato Quindi, di nuovo, non viene pagato alcun prezzo per gli oggetti non osservati.

Detto questo, l'attuale implementazione di Object.observe in V8 fa sì che gli oggetti osservati paghino un prezzo elevato perché li normalizza (li converte in rappresentazione di dizionario) e richiede round trip attraverso il sistema runtime per la registrazione di osservazioni. Ma non ci sono difficoltà tecniche intrinseche nel ridurre significativamente questo costo in seguito.

+0

Tuttavia, questo * richiede * motori per adottare un approccio dinamico "classe nascosta" per sempre. In questo momento sarebbe possibile risolvere più di queste ottimizzazioni di specializzazione usando analisi statiche o annotazioni di tipo (in una versione futura di JavaScript). Ciò sarà ora impossibile per sempre. JS non può mai essere veloce come, ad esempio, Java o .NET anche con informazioni di tipo perfetto. – usr

+0

Innanzitutto, osservo che l'analisi del tipo statico per l'intero JavaScript nella sua forma attuale è troppo costosa e poco pratica; e le annotazioni di tipo sono una cosa ipotetica di domani e anche quando i motori introdotti dovranno mantenere le classi nascoste per eseguire velocemente il codice non annotato "oldschool" per la compatibilità all'indietro. In secondo luogo, confrontando alcune nozioni astratte sulla velocità del linguaggio X contro il linguaggio Y non è costruttivo, dovresti specificare il benchmark, i modelli linguistici di cui stiamo discutendo ecc. Infine ho delineato in modo specifico l'approccio in cui il codice di esecuzione contiene * no *. –

+0

Quest'ultimo approccio si basa su Object.observe che deoptimizza il codice potenzialmente in grado di scrivere negli oggetti osservati. È abbastanza simile alla deoptimizzazione del codice quando, ad esempio, viene collegato il debugger. A seconda di come sono implementate le cose, può deoptimizzare tutto o solo le funzioni interessate. –

2

Questo non influisce gravemente sulla generazione del codice e sulle ottimizzazioni delle prestazioni che possono essere eseguite dal motore JavaScript (ad es. V8)?

Sì. Proprio come Proxy, Getter/Setter e forse anche oggetti prototipo - tutti sono dinamici in JavaScript.

Tuttavia, a causa della loro asincronia, saranno possibili nuove (e migliori) ottimizzazioni; e potevano rendere obsoleto un altro codice più inefficiente. Citando le Goals from the harmony draft:

  • Nessun involucro o del proxy oggetti necessari, fornendo l'efficienza della memoria e dell'identità oggetto
  • modificare le notifiche su Add/delete di una proprietà su un oggetto
  • modificare le notifiche sulle modifiche descrittore di proprietà di proprietà su un oggetto
  • La possibilità per un oggetto di indicare manualmente quando una proprietà accessor è stata modificata
  • efficiente implementabile nei motori
  • semplice, mirato, estensione a corrente ES
  • asincrono notifica delle modifiche, ma consentono il recupero sincrona dei cambiamenti in attesa di consegna motori
Problemi correlati