2015-05-12 19 views
8

Nel mio sito Web ho molti array con dati. per esempio: array di vertici, matrice di colori, matrice di dimensioni ...Il modo migliore per inserire elementi nell'array?

Sto lavorando con grandi quantità di articoli. Fino a decine di milioni.

Prima di aggiungere i dati negli array, è necessario elaborarlo. Fino ad ora, l'ho fatto nel thread principale e questo ha reso il mio sito web congelato per X secondi. Si è bloccato a causa dell'elaborazione e dell'aggiunta dei dati elaborati negli array.

Oggi ho "spostato" (fatto molto lavoro) l'elaborazione in web worker, ma i dati elaborati vengono aggiunti nel thread principale. Sono riuscito a risparmiare il tempo di congelamento dell'elaborazione ma non dell'aggiunta.

L'aggiunta è fatta semplicemente da array.push() o array.splice().

Ho letto alcuni articoli su come funziona la matrice e ho scoperto che quando aggiungiamo un elemento a un array, l'array viene copiato completamente in una nuova posizione nella memoria con la dimensione array.length + 1 e lì aggiungendo il valore. Questo rallenta i miei dati.

Ho anche letto che l'array tipizzato è molto più veloce. Ma per questo avrei bisogno di conoscere la dimensione dell'array, che non conosco, e per creare un grande array tipizzato con un contatore extra e gestire l'aggiunta di elementi nel mezzo (e non la fine dell'array) sarebbe un molto cambiamento di codice, che non voglio fare in questo momento.

Quindi, per la mia domanda, Ho TypedArray che restituisce dal web worker, e questo ho bisogno di mettere in serie normale. Qual è il modo migliore per farlo? (oggi sono in esecuzione in un ciclo e spingendo uno dopo l'altro)

EDIT

Esempio di come il lavoro sito: il cliente aggiungere numero di elementi, diciamo 100000. Le voci grezzo i dati vengono raccolti e inviati al lavoratore. L'operatore sta elaborando tutte le informazioni e inviando i dati elaborati come array tipizzato (per l'utilizzo come oggetti trasferibili). Nel thread principale stiamo aggiungendo i dati elaborati agli array - alla fine o in qualche indice specifico. 2 ° turno. il cliente aggiunge altri 100000 articoli. invio al lavoratore e il risultato viene aggiunto agli array di thread principali. 3 ° round può essere di 10 elementi, 4 ° round 10000, 5 ° round può rimuovere gli indici 10-2000, ...

+1

Suona come si dovrebbe essere il caching. Inoltre, hai davvero/bisogno/tutti i dati nel client allo stesso tempo? – tyteen4a03

+0

Restituire un array tipizzato dal web worker e quindi rimetterlo in un array normale sarebbe probabilmente più lento di inserirlo in un array sul thread principale in primo luogo. –

+0

Potrebbe essere necessario copiare l'array originale e quindi mutare quello nuovo nel worker. Se l'array originale non contiene oggetti, puoi copiarlo con 'Array # slice'. – Pavlo

risposta

5

Ha fatto qualche altra ricerca usando i commenti e pensato a un'altra direzione.

Ho provato a utilizzare il metodo typedArray.set e ho scoperto che è molto molto veloce.

10 milioni di elementi che utilizzano set hanno impiegato 0,004 secondi, confrontati con array.push 0,866 secondi. Ho separato i 10 milioni in 10 array solo per assicurarmi che il metodo set non funzioni più velocemente partendo dall'indice 0.

In questo modo penso che implementerei anche il mio insertAtIndex utilizzando il TypedArray, che spinge tutto gli oggetti in avanti e l'impostazione del nuovo sono nell'indice giusto.

Inoltre, posso utilizzare TypedArray.subArray per recuperare miei dati secondari in base alla reale quantità di dati nella matrice (che non è copiare i dati) - utile per caricare i dati nel buffer (WebGL)

Ho detto che voglio lavorare con array regolari ma questo incremento delle prestazioni non credo che otterrei un altro saggio. E non è tanto il lavoro, quando sto avvolgendo MyNewTypedArray come TypedArray con tutte le push, splice, la propria implementazione.

Speranza queste informazioni ha aiutato chiunque

var maxCount = 10000000; 
 
var a = new Float32Array(maxCount); 
 
var aSimple = []; 
 

 
var arrays = []; 
 
var div = 10; 
 
var arrayLen = maxCount/div; 
 
for (var arraysIdx = 0; arraysIdx < div; arraysIdx++) { 
 
    var b = new Float32Array(arrayLen); 
 
    for (var i = 0; i < b.length; i++) { 
 
    b[i] = i * (arraysIdx + 1); 
 
    } 
 
    arrays.push(b); 
 
} 
 

 
var timeBefore = new Date().getTime(); 
 

 
for (var currArrayIdx = 0; currArrayIdx < arrays.length; currArrayIdx++) { 
 
    a.set(arrays[currArrayIdx], currArrayIdx * arrayLen); 
 
} 
 
var timeAfter = new Date().getTime(); 
 
good.innerHTML = (timeAfter - timeBefore)/1000 + " sec.\n"; 
 
timeBefore = new Date().getTime(); 
 
for (var currArrayIdx = 0; currArrayIdx < arrays.length; currArrayIdx++) { 
 
    for (var i = 0; i < arrayLen; i++) { 
 
    aSimple.push(arrays[currArrayIdx][i]); 
 
    } 
 
} 
 

 
timeAfter = new Date().getTime(); 
 
bad.innerHTML = (timeAfter - timeBefore)/1000 + " sec.\n";
Using set of TypedArray: 
 
<div id='good' style='background-color:lightGreen'>working...</div> 
 
Using push of Array: 
 
<div id='bad' style='background-color:red'>working...</div>

Problemi correlati