2013-09-27 9 views
12

Quindi questo è interessante ... Mentre stavo testando le prestazioni di setAttribute rispetto alla proprietà normale impostata su un elemento, ho trovato un comportamento strano, che ho quindi testato su oggetti regolari e ... È ancora strano!Prestazioni di Chrome: nomi di proprietà "standard" rispetto a non standard

Quindi, se si dispone di un oggetto A = {}, e si imposta la sua proprietà come A['abc_def'] = 1, o A.abc_def = 1, sono fondamentalmente la stessa. Ma se lo fai, A['abc-def'] = 1 o A['123-def'] = 1, allora sei nei guai. Va molto più lentamente. Ho impostato un test qui: http://jsfiddle.net/naPYL/1/. Funzionano tutti allo stesso modo su tutti i browser tranne Chrome. La cosa divertente è che per la proprietà "abc_def", Chrome è in realtà molto più veloce di Firefox e IE, come mi aspettavo. Ma per "abc-def" è almeno due volte più lento.

Che cosa succede qui in fondo (almeno dal mio test) è che quando si usa la sintassi "corretto" per le proprietà (sintassi C legale, che può essere utilizzato con le proprietà punti) - E 'veloce, ma quando si utilizza la sintassi che richiede usando parentesi (a [...]), allora sei nei guai.

Ho cercato di immaginare quali dettagli di implementazione si sarebbero distinti in tal modo tra le due modalità e non potevano. Perché se ci penso, se supporti quei nomi non standard, probabilmente stai traducendo tutti i nomi con la stessa meccanica, e il resto è solo la sintassi che è compilata in quella meccanica. Così . la sintassi e [] dovrebbero essere tutti uguali dopo la compilazione. Ma ovviamente qualcosa sta andando nella direzione opposta qui ...

Senza guardare il codice sorgente del V8, qualcuno potrebbe pensare ad una risposta davvero soddisfacente? (Pensate a come un esercizio :-))

Here's also a quick jsperf.com example

Grazie al NDM per l'esempio jsperf!

Edit:

Per chiarire, naturalmente voglio anche una risposta concreta dal codice vero e proprio (che ho già trovato) o per essere più precisi - la ragione che specifica implementazione. Questa è una delle ragioni per cui ho chiesto a di guardarlo "come un esercizio", di guardare dietro l'implementazione tecnica e provare a trovare il motivo.

Ma volevo anche vedere come le menti degli altri lavorano in casi come questi. Può sembrare "vago" per alcuni di voi - ma è molto utile provare e pensare allo come altre persone di volta in volta, o prendere il loro punto di vista. It migliora il tuo modo di pensare.

+4

Domanda stupefacente. V8 ha un meccanismo di classe di supporto che tenterà di accoppiare una classe C++ standard agli oggetti per velocizzare le cose. Potrebbe essere - sembra, infatti - che quando la sintassi non è standard questa classe di supporto non può essere costruita, quindi Chrome gestisce la proprietà in un modo standard (la tabella hash molto probabilmente). – GameAlchemist

+1

Ho aggiunto un test jsperf e l'ho collegato alla tua domanda. FYI sul mio cromo era più lento del 6%. In FF erano ugualmente veloci, ma 7 volte più veloci del cromo! – NDM

+1

Penso che questa domanda sia a rischio di chiusura dovuta principalmente al * "senza guardare il codice sorgente del V8 [...] pensarlo come un esercizio" * line. Questa è una domanda interessante, ma questa linea incoraggia la speculazione invece di risposte concrete, e questo è generalmente disapprovato. –

risposta

5

Quindi gli oggetti JS possono essere utilizzati per due scopi contrastanti. Possono essere usati come oggetti ma possono anche essere usati come tabelle di hash. Tuttavia, ciò che è veloce e ragionevole per gli oggetti non è lo stesso per le tabelle hash, quindi V8 prova a indovinare cosa sia un determinato oggetto.

Alcuni segni che l'utente può dare che vuole che un dizionario stia cancellando una proprietà o giving a property a name that cannot be accessed using dot notation.

Sono state utilizzate anche altre euristiche, ho creato un aspetto https://gist.github.com/petkaantonov/6327915.

V'è tuttavia a really cool hack che redempts un oggetto da tabella hash inferno:

function ensureFastProperties(obj) { 
    function f() {} 
    f.prototype = obj; 
    return obj; 
} 

vedere in azione: http://jsperf.com/property-dash-parformance/2.

L'oggetto non aggiornato non è veloce quanto l'originale poiché le proprietà sono memorizzate nell'array delle proprietà esterne anziché nell'oggetto. Ma è ancora molto meglio del tavolo hash. Si noti che questo benchmark è ancora abbastanza rotto, non pensare per un secondo che le tabelle hash siano solo 2 volte più lente delle proprietà degli inobject.

+0

La simpatica hack non sembra funzionare in 'Chrome 30.0.1599.65 beta-m' – C5H8NNaO4

+0

@ C5H8NNaO4 si deve indagare .. il codice per ottimizzare l'oggetto nell'assegnazione del prototipo è ancora lì anche sulla maggior parte dei bleeding edge v8 – Esailija

Problemi correlati