In che modo le classi nascoste consentono un accesso più rapido alle proprietà nel V8 di Google?

7

Come Lars Bak e Jay Conrod descritto in diversi video e documenti, l'idea principale delle classi nascoste nel V8 è quella di memorizzare l'offset concreto o la transizione verso un'altra classe nascosta che probabilmente contiene questo offset per la proprietà di ogni oggetto, invece di fare una ricerca "lenta" in hashtable che contiene tutte le proprietà.

In modo antiquato di accesso alla proprietà, ad esempio per ottenere point.x , dobbiamo calcolare l'hashcode da x e quindi passare attraverso l'array (se non ci fosse hashcode-collision quando la proprietà è stata aggiunta noi ' Otterrai il valore istantaneamente). Ma in modo new-fashion abbiamo una classe nascosta (solo una Map ?) E abbiamo bisogno di iterare attraverso di essa per scoprire che contiene la chiave x o no e solo dopo possiamo prendere il valore della proprietà per offset in% campox. O nel caso più complicato, dobbiamo fare alcuni passi aggiuntivi attraverso le transizioni verso altre classi nascoste. Quindi non vedo una differenza tra la memorizzazione di tutte le proprietà in hashtable e l'utilizzo di classi nascoste. Forse c'è qualche trucco di assemblaggio che non capisco?

    
posta mopdobopot 22.03.2015 - 15:50
fonte

2 risposte

2

V8 e altre implementazioni linguistiche che utilizzano tecniche simili sono compilatori just-in-time. Generano codice e il codice generato è ottimizzato speculativamente (con i controlli per tornare a un codice più lento e più generale se la specializzazione risulta non valida). Quindi, quando si genera codice, il compilatore JIT spesso ha una buona ipotesi su quale sia la classe nascosta di un oggetto - dall'inferenza di tipo o dai dati raccolti durante l'esecuzione del programma - e genera un codice come questo:

compare hidden class pointer to address of assumed 
if not equal, de-optimize, otherwise:
access the property at a hard-coded offset

Ogni riga di cui sopra può essere una singola istruzione assembler su x86. Poiché assume una classe nascosta durante la generazione di questo codice, il compilatore JIT può recuperare l'offset dalla classe nascosta al momento della compilazione JIT e codificarlo nel codice, in modo che il codice che viene eseguito spesso non sia mai tocca la classe nascosta.

    
risposta data 22.03.2015 - 16:05
fonte
2

La chiave è che questo viene utilizzato in un JIT che produce codice specializzato.

Diciamo che abbiamo una funzione simile a questa:

function add_points(a, b) {
   return new Point(a.x + b.x, a.y + b.y);
}

V8 genererà in realtà versioni diverse di questa funzione, per diversi argomenti possibili che si passeranno. Ad esempio, genererebbe una versione della funzione che viene utilizzata solo quando a e b sono entrambi membri di una classe Point nascosta.

Point add_points(Point a, Point b) {
   return new Point(a.x + b.x, a.y + b.y);
}

Il trucco è che siccome sappiamo che questa funzione sarà usata solo per oggetti con la classe Hidden point, x e y avranno sempre lo stesso offset. Quindi non dobbiamo cercarlo ogni volta, il compilatore lo ha cercato una volta durante la costruzione di questa funzione e ha inserito l'offset nel codice generato.

    
risposta data 22.03.2015 - 16:15
fonte

Leggi altre domande sui tag