macchina - v8 motore javascript




Qual è la performance di Objects/Arrays in JavaScript?(in particolare per Google V8) (3)

A un livello base che rimane all'interno dei regni di JavaScript, le proprietà sugli oggetti sono entità molto più complesse. È possibile creare proprietà con setter / getter, con diverse enumerabilità, scrivibilità e configurabilità. Un articolo in un array non può essere personalizzato in questo modo: esiste o non lo è. Al livello del motore sottostante ciò consente una maggiore ottimizzazione in termini di organizzazione della memoria che rappresenta la struttura.

In termini di identificazione di una matrice da un oggetto (dizionario), i motori JS hanno sempre fatto linee esplicite tra i due. Ecco perché c'è una moltitudine di articoli sui metodi per provare a creare un oggetto semi-falso simile ad Array che si comporta come uno ma consente altre funzionalità. La ragione per cui questa separazione esiste anche perché i motori JS stessi memorizzano i due in modo diverso.

Le proprietà possono essere archiviate su un oggetto array ma ciò dimostra semplicemente come JavaScript insiste nel rendere tutto un oggetto. I valori indicizzati in una matrice vengono memorizzati in modo diverso da qualsiasi proprietà che si decide di impostare sull'oggetto matrice che rappresenta i dati dell'array sottostante.

Ogni volta che si utilizza un oggetto array legittimo e si utilizza uno dei metodi standard di manipolazione di tale array, si verrà colpiti dai dati dell'array sottostante. In V8 in particolare, questi sono essenzialmente gli stessi di un array C ++, quindi queste regole verranno applicate. Se per qualche motivo stai lavorando con un array che il motore non è in grado di determinare con sicurezza è un array, allora sei su un terreno molto più shakier. Con le versioni recenti di V8 c'è però più spazio per lavorare. Ad esempio, è possibile creare una classe che ha Array.prototype come prototipo e ottenere comunque un accesso efficiente ai vari metodi di manipolazione degli array nativi. Ma questo è un cambiamento recente.

Link specifici alle recenti modifiche alla manipolazione dell'array possono tornare utili qui:

Come extra, ecco gli array Array Pop e Array Push direttamente dalla sorgente V8, entrambi implementati in JS stesso:

function ArrayPop() {
  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
    throw MakeTypeError("called_on_null_or_undefined",
                        ["Array.prototype.pop"]);
  }

  var n = TO_UINT32(this.length);
  if (n == 0) {
    this.length = n;
    return;
  }
  n--;
  var value = this[n];
  this.length = n;
  delete this[n];
  return value;
}


function ArrayPush() {
  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
    throw MakeTypeError("called_on_null_or_undefined",
                        ["Array.prototype.push"]);
  }

  var n = TO_UINT32(this.length);
  var m = %_ArgumentsLength();
  for (var i = 0; i < m; i++) {
    this[i+n] = %_Arguments(i);
  }
  this.length = n + m;
  return this.length;
}

Le prestazioni associate a matrici e oggetti in JavaScript (in particolare Google V8) sarebbero molto interessanti da documentare. Non trovo alcun articolo completo su questo argomento da nessuna parte su Internet.

Capisco che alcuni oggetti utilizzano le classi come struttura dati sottostante. Se ci sono molte proprietà, a volte è trattata come una tabella hash?

Capisco anche che gli array sono a volte trattati come array C ++ (cioè indicizzazione casuale veloce, cancellazione lenta e ridimensionamento). E, altre volte, sono trattati più come oggetti (indicizzazione veloce, inserimento / rimozione veloce, più memoria). E, a volte, possono essere archiviati come liste concatenate (es. Indicizzazione casuale lenta, rimozione / inserimento veloce all'inizio / fine)

Qual è la prestazione precisa dei recuperi e delle manipolazioni di Array / Object in JavaScript? (in particolare per Google V8)

Più in particolare, qual è l'impatto sulle prestazioni di:

  • Aggiunta di una proprietà a un oggetto
  • Rimozione di una proprietà da un oggetto
  • Indicizzazione di una proprietà in un oggetto
  • Aggiunta di un elemento a una matrice
  • Rimozione di un elemento da una matrice
  • Indicizzazione di un elemento in una matrice
  • Chiamando Array.pop ()
  • Chiamare Array.push ()
  • Chiamare Array.shift ()
  • Chiamare Array.unshift ()
  • Chiamare Array.slice ()

Qualsiasi articolo o link per maggiori dettagli sarebbe apprezzato, pure. :)

EDIT: Mi sto davvero chiedendo come funzionano gli array e gli oggetti JavaScript sotto il cofano. Inoltre, in quale contesto il motore V8 "sa" di "passare" a un'altra struttura dati?

Ad esempio, supponiamo di creare un array con ...

var arr = [];
arr[10000000] = 20;
arr.push(21);

Cosa sta succedendo davvero qui?

O ... che mi dici di questo ... ???

var arr = [];
//Add lots of items
for(var i = 0; i < 1000000; i++)
    arr[i] = Math.random();
//Now I use it like a queue...
for(var i = 0; i < arr.length; i++)
{
    var item = arr[i].shift();
    //Do something with item...
}

Per gli array convenzionali, la performance sarebbe terribile; mentre, se è stata utilizzata una lista collegata ... non così male.


Durante l'esecuzione di node.js 0.10 (basato sulla v8) vedevo un utilizzo della CPU eccessivo per il carico di lavoro. Ho rintracciato un problema di prestazioni in una funzione che stava verificando l'esistenza di una stringa in un array. Quindi ho eseguito alcuni test.

  • caricato 90.822 host
  • la configurazione di caricamento ha impiegato 0,087 secondi (array)
  • la configurazione di caricamento ha richiesto 0.152 secondi (oggetto)

Il caricamento di voci 91k in un array (con convalida e push) è più veloce dell'impostazione di obj [chiave] = valore.

Nel test successivo, ho cercato ogni hostname nell'elenco una volta (91k iterazioni, per calcolare la media del tempo di ricerca):

  • la ricerca ha richiesto 87,56 secondi (array)
  • la ricerca della configurazione ha richiesto 0,21 secondi (oggetto)

L'applicazione qui è Haraka (un server SMTP) e carica l'host_list una volta all'avvio (e dopo le modifiche) e successivamente esegue questa ricerca milioni di volte durante l'operazione. Passare a un oggetto è stata una grande vittoria per le prestazioni.


AGGIORNAMENTO: nota che JSPref è attualmente inattivo

(Ho salvato una copia del test case e aggiornerò la risposta una volta che JSPref è stato corretto / un successore è stato trovato)

Hmm ... forse un overkill per la risposta ... ma ho creato una suite di test, proprio per esplorare questi problemi (e altro) ( copia archiviata ).

E in questo senso, puoi vedere i problemi di prestazioni in questo tester test 50+ (ci vorrà molto tempo).

Inoltre, come suggerisce il nome, esplora l'utilizzo dell'utilizzo della natura dell'elenco link nativo della struttura DOM.

(Attualmente inattivo, ricostruito in corso) Maggiori dettagli sul mio blog a riguardo .

Il riassunto è come seguito

  • La matrice V8 è veloce, MOLTO VELOCE
  • Il push / pop / shift della matrice è ~ circa 20 volte più veloce di qualsiasi oggetto equivalente.
  • Sorprendentemente Array.shift() è veloce ~ circa 6 volte più lento di un array pop, ma è ~ circa 100 volte più veloce di una cancellazione di attributo oggetto.
  • Divertente, Array.push( data ); è più veloce di Array[nextIndex] = data di quasi 20 (array dinamico) a 10 (array fisso) volte.
  • Array.unshift(data) è più lento come previsto ed è ~ circa 5 volte più lento di una nuova aggiunta di proprietà.
  • Nullare l' array[index] = null valori array[index] = null è più veloce di cancellarlo delete array[index] (indefinito) in un array di ~ approx 4x ++ più veloce.
  • Sorprendentemente Nullare un valore in un oggetto è obj[attr] = null ~ circa 2 volte più lento del solo cancellare l'attributo delete obj[attr]
  • Non sorprende che il Array.splice(index,0,data) sia lento, molto lento.
  • Sorprendentemente, Array.splice(index,1,data) è stato ottimizzato (nessun cambio di lunghezza) ed è 100 volte più veloce di un semplice splice Array.splice(index,0,data)
  • non sorprendentemente, la divLinkedList è inferiore a un array su tutti i settori, tranne la dll.splice(index,1) (dove ha rotto il sistema di test).
  • GRANDE SORPRESA di tutto ciò [come sottolineato da jjrv], le scritture di array V8 sono leggermente più veloci di V8 reads = O

Nota: queste metriche si applicano solo a grandi array / oggetti che v8 non "ottimizza completamente". Ci possono essere casi di prestazioni ottimizzati molto isolati per dimensioni di array / oggetto meno di una dimensione arbitraria (24?). Ulteriori dettagli possono essere visti in modo estensivo su diversi video IO di Google.

Nota 2: questi meravigliosi risultati delle prestazioni non sono condivisi tra i browser, in particolare *cough* IE. Anche il test è enorme, quindi devo ancora analizzare e valutare completamente i risultati: per favore modificalo in =)

Nota aggiornata (dic 2012): i rappresentanti di Google hanno video su youtubes che descrivono il funzionamento interno di chrome stesso (come quando passa da un array di liste di collegamenti a un array fisso, ecc.) E su come ottimizzarli. Vedi GDC 2012: da Console a Chrome per ulteriori informazioni.

Nota aggiornata (febbraio 2013): Thx @badunk, per fornire il collegamento video nel punto esatto

Nota aggiornata (giugno 2016): Thx @Benedikt, riguardante la differenza delle prestazioni di spinta dell'array negli array fissi / dinamici.





v8