2011-12-22 22 views
10

Scorri verso il basso per il confronto getById.getByClassName vs. qSA!


Se volessimo per selezionare tutti gli elementi della classe "bar" che sono all'interno dell'elemento con l'ID "foo", potremmo scrivere questo:

$('#foo .bar') 

o questo:

$('.bar', '#foo') 

Ci sono naturalmente altri metodi per raggiungere questo obiettivo, ma per il gusto di questa domanda, confrontiamo solo questi due metodi.

Quindi, quale dei metodi precedenti funziona meglio? (Che ha bisogno di meno tempo per eseguire?)

Ho scritto questo test di prestazione:

(function() { 
    var i; 

    console.time('test1'); 
    for(i = 0; i < 100; i++) { 
     $('#question-mini-list .tags'); 
    } 
    console.timeEnd('test1'); 

    console.time('test2'); 
    for(i = 0; i < 100; i++) { 
     $('.tags', '#question-mini-list'); 
    } 
    console.timeEnd('test2'); 
})(); 

Dovete eseguirlo dall'interno della console sul Stack Overflow start-page. I miei risultati sono i seguenti:

Firefox:
test1: ~ 90 ms
test2: ~ 18ms

Chrome:
test1: ~ 65ms
test2: ~ 30ms

Opera:
test1: ~ 50 ms
test2: ~ 100 ms

Quindi in Firefox e Chrome, t il secondo metodo è più volte più veloce, proprio come mi aspettavo. Tuttavia, in Opera la situazione è invertita. Mi chiedo cosa sta succedendo qui.

Potresti eseguire il test sulla tua macchina e spiegare perché Opera funziona in modo diverso?


Aggiornamento

ho scritto questo test, al fine di verificare se QSA di Opera è davvero super-veloce. A quanto pare, lo è.

(function() { 
    var i, limit = 5000, test1 = 'test1', test2 = 'test2'; 

    console.time(test1); 
    for(i = 0; i < limit; i += 1) { 
     document.getElementById('question-mini-list').getElementsByClassName('tags'); 
    } 
    console.timeEnd(test1); 

    console.time(test2); 
    for(i = 0; i < limit; i += 1) { 
     document.querySelectorAll('#question-mini-list .tags'); 
    } 
    console.timeEnd(test2); 
})(); 

Anche in questo caso, è necessario eseguire questo codice all'interno della console nella pagina iniziale di Stack Overflow. Ho usato il bookmarklet Firebug Lite per IE9 (poiché il browser non implementa console.time).

Così, ho confrontato questo metodo:

document.getelementById('A').getElementsByClassName('B'); 

a questo metodo:

document.querySelectorAll('#A .B'); 

ho eseguito lo script di cui sopra per cinque volte consecutive in ogni browser.Le medie aritmetiche sono:

enter image description here

(Tutti i numeri sono in millisecondi.)

Così, le prestazioni del primo metodo è più o meno lo stesso nei browser testati (16-36ms). Tuttavia, mentre qSA è molto più lento rispetto al primo metodo, in Opera è in realtà più veloce!

Quindi, l'ottimizzazione QSA è possibile, mi chiedo che cosa gli altri browser sono in attesa di ...

+0

'test1: 73ms',' test2: 11ms'. Opera è un browser strano, non sono sicuro del perché è in ritardo. – Blender

+1

@Blender Aumentare il limite del loop. Il mio portatile è molto lento, quindi sono andato con 100. Prova 1000.(I risultati più piccoli di '4ms' non sono affidabili ...) –

+0

Hai considerato di includere' document.getElementById ('foo'). GetElementsByClassName ('bar') 'per completezza? – RobG

risposta

3

jQuery/Sizzle eviteranno di utilizzare il motore Sizzle basato su JavaScript se il browser supporta querySelectorAll e se si passa un selettore valido (nessun selettore personalizzato, non CSS).

Ciò significa che in definitiva si stanno confrontando le implementazioni di querySelectorAll, presupponendo che si stiano testando i browser che lo supportano.

Non ci sono altre ottimizzazioni che jQuery o Sizzle usi, quindi è difficile quando si confrontano i diversi tipi di selezione DOM in diversi browser.

La ragione di conseguenza le prestazioni di Opera sembra essere che essi hanno un molto altamente ottimizzato querySelectorAll attuazione. qSA, essendo un metodo relativamente nuovo, non è stato altrettanto ottimizzata in alcuni browser rispetto ai vecchi metodi come getElementsByTagName.

+0

Bene, qSA non è nuovo. È in Chrome da sempre, in Firefox dal 3.5 e in IE dalle 8. I browser hanno avuto tutto il tempo per ottimizzarlo. Vergogna su di loro (controlla il mio nuovo test sopra). –

+0

@ ŠimeVidas: Sì, nuovo solo rispetto ad altri metodi. Ma hai ragione. Mi sembra che abbiano avuto tutto il tempo per ottimizzare. Sono sicuro che alla fine arriveranno. –

+0

@ ŠimeVidas: Ho intenzione di lanciare un'altra possibilità là fuori. Dal momento che il tuo test non fa nulla con il risultato, mi chiedo se l'ottimizzazione non si preoccupi affatto della selezione DOM. Forse chiama il metodo, ma abbandona la ricerca. Questo potrebbe spiegare perché il primo test richiede più tempo (chiamate a due funzioni). Questa è pura speculazione, naturalmente. –

1

E il vincitore è ....

prova 3$('#question-mini-list').find('.tags');

  • test1: 25ms
  • test2: 19ms
  • test3: 10ms

I due metodi avete suggerito non sono equivalenti.

test 1: Sizzle analizza da destra a sinistra (non chiedere di cercare mai un elemento nella pagina, quindi limitare a un ID).

test 2: L'utilizzo di una stringa come contesto non è generalmente inutile, utilizzare gli elementi come contesto.

test 3: Trovare elementi con un ID è incredibilmente veloce. Una volta che sei lì, è un gioco da ragazzi concentrarsi su un elemento di una determinata classe.

+0

"* Sizzle analizza da destra a sinistra *" - Mi piacerebbe una fonte per questo. –

+1

Sizzle ha un'ottimizzazione che se la stringa inizia con un selettore di id, [lo usa per primo] (http://stackoverflow.com/questions/7757744/will-jquery-search-for-the-id-before-filtering- other-parameters-in-the-selector/7757792 # 7757792), quindi dovrebbero essere equivalenti. – Dennis

+0

jQuery trasforma '$ ('. Bar', '#foo')' in '$ ('# pippo'). Trova ('. Bar')' internamente. Li considero equivalenti. Quest'ultimo è leggermente più veloce, naturalmente. –

1

Per avere un riferimento, questo è 30x più veloce:

document.getElementById("foo").getElementsByClassName("bar"); 

See jsPerf: http://jsperf.com/jquery-selector-variations/3. Ciò richiederebbe uno shim per funzionare nelle versioni precedenti di IE.

Mentre jQuery è estremamente utile, se la velocità è di fondamentale, non è sempre lo strumento migliore per il lavoro.

+0

La barra "Plain JS" ha rovinato il grafico ': P' –

+0

@ ŠimeVidas - Sì, l'ho notato anche io. Non mi aspettavo una differenza così drammatica. Puoi tornare alla versione precedente se vuoi solo quelle. Si passa a mostrare quanto sovraccarico, ci può essere sia in analisi di un selettore generale e in oggetti jQuery in generale. – jfriend00

Problemi correlati