2009-04-13 9 views
5

Da quando uso jQuery 1.3+ tutto tranne un test a tempo lo sta usando. L'altro è un javascript semplice che ho trovato nel 2000. Ho smesso di seguire quella strada perché erano necessari circa 150 secondi per eseguire il test. Ho letto alcune pagine web di ottimizzazione jQuery relative alla selezione di un singolo elemento. Un '#id' è il miglior caso per utilizzarlo, ma ora ho il problema di che controlla tutte le checkbox in una colonna in una tabella piuttosto grande che ha più caselle di controllo.Qual è il modo più veloce per selezionare una grande quantità di checkbox e de/selezionarli?

Quello che ho fatto è impostare una pagina crea 20.000 righe di tabella con due colonne di caselle di controllo. L'obiettivo è controllare la seconda colonna per vedere quanto tempo è durato, quindi deselezionarli e vedere quanto tempo è durato. Ovviamente vogliamo il tempo più basso. Sto usando solo IE6 e 7 e nel mio caso tutti i miei utenti faranno lo stesso.

20.000 righe che dici? Questo è quello che ho detto anche io, ma questo è in produzione (fuori dalle mie mani) ed è troppo tardi per cambiare ora. Sto solo provando a lanciare un messaggio di saluto con un secondo a sinistra dell'orologio. Inoltre, ho imparato che input.chkbox non è il selettore più veloce (per IE7)! :)

La domanda è, c'è un modo migliore per fare questo jQuery o in altro modo? Mi piacerebbe che funzionasse in meno di mezzo secondo sulla mia macchina.

Quindi non c'è bisogno di digitare nuovamente tutte le stronzate ho già fatto qui è la roba di prova mi si avvicinò con:

Aggiornato Mattina 4/14 per includere ulteriori prove contro il tempo:

<form id="form1" runat="server"> 
<div>   
     <a href="#" id="one">input[id^='chkbox'][type='checkbox']</a><br /> 
     <a href="#" id="two">#myTable tr[id^='row'] input[id^='chkbox'][type='checkbox']</a><br /> 
     <a href="#" id="three">#myTable tr.myRow input[id^='chkbox'][type='checkbox']</a><br /> 
     <a href="#" id="four">tr.myRow input[id^='chkbox'][type='checkbox']</a><br /> 
     <a href="#" id="five">input[id^='chkbox']</a><br /> 
     <a href="#" id="six">.chkbox</a><br /> 
     <a href="#" id="seven">input.chkbox</a><br /> 
     <a href="#" id="eight">#myTable input.chkbox</a><br /> 

     <a href="#" id="nine">"input.chkbox", "tr"</a><br /> 
     <a href="#" id="nine1">"input.chkbox", "tr.myRow"</a><br /> 
     <a href="#" id="nine2">"input.chkbox", "#form1"</a><br /> 
     <a href="#" id="nine3">"input.chkbox", "#myTable"</a><br /> 

     <a href="#" id="ten">input[name=chkbox]</a><br /> 
     <a href="#" id="ten1">"input[name=chkbox]", "tr.myRow"</a><br /> 
     <a href="#" id="ten2">"input[name=chkbox]", "#form1"</a><br /> 
     <a href="#" id="ten3">"input[name=chkbox]", "#myTable"</a><br /> 

     <a href="#" id="ten4">"input[name=chkbox]", $("#form1")</a><br /> 
     <a href="#" id="ten5">"input[name=chkbox]", $("#myTable")</a><br /> 

     <a href="#" id="eleven">input[name='chkbox']:checkbox</a><br /> 
     <a href="#" id="twelve">:checkbox</a><br /> 
     <a href="#" id="twelve1">input:checkbox</a><br /> 
     <a href="#" id="thirteen">input[type=checkbox]</a><br /> 

     <div> 
      <input type="text" id="goBox" /> <button id="go">Go!</button> 
      <div id="goBoxTook"></div> 
     </div> 

     <table id="myTable"> 
      <tr id="headerRow"><th>Row #</th><th>Checkboxes o' fun!</th><th>Don't check these!</th></tr> 
      <% for(int i = 0; i < 20000;i++) { %> 
      <tr id="row<%= i %>" class="myRow"> 
       <td><%= i %> Row</td> 
       <td> 
        <input type="checkbox" id="chkbox<%= i %>" name="chkbox" class="chkbox" /> 
       </td> 
       <td> 
        <input type="checkbox" id="otherBox<%= i %>" name="otherBox" class="otherBox" /> 
       </td> 
      </tr> 
      <% } %> 
     </table> 
</div> 
     <script type="text/javascript" src="<%= ResolveUrl("~/") %>Javascript/jquery.1.3.1.min.js"></script> 
     <script type="text/javascript"> 

      $(function() {     
       function run(selectorText, el) {      
        var start = new Date();      
        $(selectorText).attr("checked", true);        
        var end = new Date(); 
        var timeElapsed = end-start; 
        $(el).after("<br />Checking Took " + timeElapsed + "ms"); 

        start = new Date();      
        $(selectorText).attr("checked", false);        
        end = new Date(); 
        timeElapsed = end-start; 
        $(el).after("<br />Unchecking Took " + timeElapsed + "ms"); 
       }  

       function runWithContext(selectorText, context, el) {      
        var start = new Date();      
        $(selectorText, context).attr("checked", true);        
        var end = new Date(); 
        var timeElapsed = end-start; 
        $(el).after("<br />Checking Took " + timeElapsed + "ms"); 

        start = new Date();      
        $(selectorText, context).attr("checked", false);         
        end = new Date(); 
        timeElapsed = end-start; 
        $(el).after("<br />Unchecking Took " + timeElapsed + "ms"); 
       } 

       $("#one").click(function() {       
        run("input[id^='chkbox'][type='checkbox']", this); 
       }); 

       $("#two").click(function() { 
        run("#myTable tr[id^='row'] input[id^='chkbox'][type='checkbox']", this); 
       }); 

       $("#three").click(function() { 
        run("#myTable tr.myRow input[id^='chkbox'][type='checkbox']", this); 
       }); 

       $("#four").click(function() { 
        run("tr.myRow input[id^='chkbox'][type='checkbox']", this); 
       }); 

       $("#five").click(function() { 
        run("input[id^='chkbox']", this); 
       }); 

       $("#six").click(function() { 
        run(".chkbox", this); 
       }); 

       $("#seven").click(function() { 
        run("input.chkbox", this); 
       }); 

       $("#eight").click(function() { 
        run("#myTable input.chkbox", this); 
       }); 

       $("#nine").click(function() { 
        runWithContext("input.chkbox", "tr", this); 
       }); 


       $("#nine1").click(function() { 
        runWithContext("input.chkbox", "tr.myRow", this); 
       }); 
       $("#nine2").click(function() { 
        runWithContext("input.chkbox", "#form1", this); 
       }); 
       $("#nine3").click(function() { 
        runWithContext("input.chkbox", "#myTable", this); 
       }); 

       $("#ten").click(function() { 
        run("input[name=chkbox]", this); 
       });     

       $("#ten1").click(function() { 
        runWithContext("input[name=chkbox]", "tr.myRow", this); 
       }); 

       $("#ten2").click(function() { 
        runWithContext("input[name=chkbox]", "#form1", this); 
       }); 

       $("#ten3").click(function() { 
        runWithContext("input[name=chkbox]", "#myTable", this); 
       }); 

       $("#ten4").click(function() { 
        runWithContext("input[name=chkbox]", $("#form1"), this); 
       }); 

       $("#ten5").click(function() { 
        runWithContext("input[name=chkbox]", $("#myTable"), this); 
       }); 

       $("#eleven").click(function() { 
        run("input[name='chkbox']:checkbox", this); 
       }); 

       $("#twelve").click(function() { 
        run(":checkbox", this); 
       }); 

       $("#twelve1").click(function() { 
        run("input:checkbox", this); 
       }); 

       $("#thirteen").click(function() { 
        run("input[type=checkbox]", this); 
       }); 

       $('#go').click(function() { 
        run($('#goBox').val(), this); 
       }); 
      }); 
     </script> 
</form> 
+0

Non intendo essere inutile, ma 20k righe in una pagina sono solo pessime progettazioni. Dovresti aggiustarlo. :) –

+0

Beh ... non sto scherzando. :) Non l'ho fatto! Al momento non c'è abbastanza tempo per risolverlo per questa versione. Sarà la prima cosa da fare nella prossima versione. Questo progetto ha sollevato molte sfide "interessanti" fino ad ora. – rball

risposta

8

input [nome = chkbox] è il selettore jQuery più veloce sulla mia macchina sotto IE7.

Unchecking Took 2453ms 
Checking Took 2438ms 
Unchecking Took 2438ms 
Checking Took 2437ms 
Unchecking Took 2453ms 
Checking Took 2438ms 

input.chkbox e ...

Unchecking Took 2813ms 
Checking Took 2797ms 
Unchecking Took 2797ms 
Checking Took 2797ms 
Unchecking Took 2813ms 
Checking Took 2797ms 

ingresso: checkbox.chkbox sembra legato

Unchecking Took 2797ms 
Checking Took 2797ms 
Unchecking Took 2813ms 
Checking Took 2781ms 

.chkbox vuole quasi il doppio del tempo come il input.chkbox

Unchecking Took 4031ms 
Checking Took 4062ms 
Unchecking Took 4031ms 
Checking Took 4062ms 

Il javascript per ciclo è di gran lunga il peggiore attestandosi a:

Checking Took 149797ms 

150 secondi! Blocca anche il browser. Questo mi rende davvero colpito da jQuery. Onestamente non mi aspettavo che fosse così lento. Probabilmente perché sto attraversando ogni singolo elemento che deve poi trovare ...

questo era abbastanza interessante per me così:

ingresso [id^= 'chkbox']

Unchecking Took 3031ms 
Checking Took 3016ms 

preso meno tempo di:

ingresso [id^= 'chkbox'] [type = 'checkbox']

Unchecking Took 3375ms 
Checking Took 3344ms 

Ho pensato che da quando ho postato più filtri sarebbe più veloce. No!

Specifica ancor più percorsi alla casella di controllo rende più lentamente:

#myTable tr [id =^'riga'] Ingresso [id =^'chkbox'] [type = 'casella']

Checking Took 10422ms 

Non ha nemmeno eseguito la seconda deselezione in quanto mi ha chiesto se volevo continuare a eseguire gli script sul mio computer. Pazzo! : P

Aggiornamento Mattino 4/14:

Qualcuno portò fino delineato il contesto: in realtà ho fatto alcuni di quelli e molto per la mia sorpresa e contro quello che un sacco di persone hanno detto sul web su IE7 questi erano più lenti! Qui ci sono le volte che ho avuto con un contesto diverso pochi specificato in coppia con il selettore di cui sopra più veloce:

"input.chkbox", "tr"

Checking Took 8546ms 

"input.chkbox", "tr .myRow"

Checking Took 8875ms 

"input.chkbox", "# form1"

Unchecking Took 3032ms 
Checking Took 3000ms 

"input.chkbox", "#myTable"

Unchecking Took 2906ms 
Checking Took 2875ms 

vincitore attuale (ancora): ingresso [name = chkbox]

Unchecking Took 2469ms 
Checking Took 2453ms 

"ingresso [nome = chkbox] "," tr.myRow"

Checking Took 9547ms 

"ingresso [name = chkbox]", "# form1"

Unchecking Took 3140ms 
Checking Took 3141ms 

"ingresso [name = chkbox]", "#myTable"

Unchecking Took 2985ms 
Checking Took 2969ms 

Aggiornamento 2 mattina 4/14

Pensavo che avrei potuto averne uno migliore dopo aver notato una differenza di sintassi da http://beardscratchers.com/journal/jquery-its-all-about-context. Sembra che questi NON siano gli stessi di , ma stanno dando tempi leggermente migliori, ma ancora non battono il selettore senza contesti - dannatamente.

"ingresso [name = chkbox]", $ ("# form1")

Unchecking Took 3078ms 
Checking Took 3000ms 
Unchecking Took 3078ms 
Checking Took 3016ms 

"ingresso [name = chkbox]", $ ("# myTable")

Unchecking Took 2938ms 
Checking Took 2906ms 
Unchecking Took 2938ms 
Checking Took 2921ms 

Update 3 di mattina 4/14

Russ mi ha voluto provare questi fuori, che de/selezionare tutto il bo xes ma ancora una volta è stato interessante:

: casella di controllo

Unchecking Took 8328ms 
Checking Took 6250ms 

ingresso: casella di controllo

Unchecking Took 5016ms 
Checking Took 5000ms 

-> più veloce?!?! input [type = casella di controllo]

Unchecking Took 4969ms 
Checking Took 4938ms 

Il fatto che il terzo lassù è il più veloce è molto interessante in quanto che va contro quello che avrei pensato. Perché non dovrebbe (per IE7 almeno) la casella di controllo: utilizzare solo la casella di controllo type = per ottenere un tempo più veloce? Questi sono punteggi molto vicini ma il controllo ha richiesto 62ms di tempo in meno. Inoltre, perché i primi due sono del tutto diversi? C'è un elemento diverso oltre a un input che può avere una casella di controllo?

+0

Altri criteri di selezione non velocizzano una query a meno che ciascuno non riduca la dimensione impostata. Dal momento che tutte le caselle di controllo sono in righe di tabella e hanno input, aggiungerle come criteri non aiuta. –

+0

"Ho pensato che da quando ho postato più filtri sarebbe più veloce." come ha detto Zan, più filtri = più controlli = più elaborazione = più tempo. A meno che ciascun filtro non riduca significativamente le dimensioni impostate per il filtro successivo, si tratta solo di cicli. – nickf

5

Non l'ho ancora provato, ma si può provare a creare un array [] di riferimenti alle checkbox sul caricamento della pagina, quindi semplicemente ripetere su di esso ogni volta che si desidera apportare una modifica?

Pagheresti il ​​costo delle prestazioni al caricamento della pagina, ma è possibile che sia più veloce di camminare ogni volta il DOM. Ehi, quantomeno starai eseguendo il pesante sollevamento dei "tempi morti" degli utenti (quanto tempo ci vuole per trovare le persone e fare clic sulle opzioni deseleziona/seleziona).

+0

Oppure mi chiedo se è possibile "archiviarli" in un array la prima volta (o al caricamento), e quindi sarebbe più veloce quando lo colpiscono di nuovo. Bella idea, ci provo. – rball

+0

fammi sapere come vai avanti! – Codebrain

+0

Lo farò, ma potrebbe essere domani, dato che la giornata lavorativa è quasi terminata. – rball

2

Il mio unico suggerimento probabilmente non funzionerà neanche. Cambia browser. Ma ho avuto solo una società in realtà d'accordo. Abbiamo fatto passare la società a FireFox e gli utenti specifici passano a Google Chrome. IE è troppo lento con JavaScript.

Inoltre, è possibile provare a memorizzare nella cache l'elenco delle query jquery.

Se tutto il resto fallisce, risolvilo con la psicologia. Ciò significa far sapere all'utente che qualcosa richiederà molto tempo. Metti un div "Please wait" mentre la funzione è in esecuzione. In questo modo l'utente sa che il browser non è solo bloccato, e sanno quando possono tornare al lavoro. Ho avuto molte pagine lente "risolte" facendo proprio questo.

+0

Lol, sì proprio non succederà. Sono "abbastanza fortunato" da poter usare IE7. Tutti gli altri devono utilizzare IE6. Vedrò il pre-caching. – rball

+0

Un'altra opzione ... Si sta utilizzando la manipolazione degli attributi JQuery per l'impostazione selezionata: $ (selectorText) .attr ("checked", false); Si potrebbe anche provare $ (selectorText) .each (function() {this.checked = false}); Nessuna garanzia, ma potrebbe valerne la pena. –

+0

Pensavo di farlo. Farò un tentativo e vedere cosa succede. In realtà stiamo facendo una notifica di attesa, prima che arrivasse a 150 secondi, ma scendere a 2-3 sarà grandioso. – rball

1

Hai provato i selettori jQuery con un context per vedere se questo migliora le prestazioni? Presumibilmente i controlli saranno all'interno di un modulo ASP.NET e forse un altro elemento identificabile in modo univoco?

Per esempio, dove si ha

$("input[id^='chkbox']") 

Prova con

$("input[id^='chkbox']", "#myFormID") 

Here's a BeardScratchers article sul contesto

EDIT:

seguito gli aggiornamenti, sembra 2.45- 6 secondi potrebbe essere il più veloce che si possa raggiungere, date le circostanze.

Solo per completezza, hai provato i seguenti selettori?

$(':checkbox') 
$('input[type=checkbox]') 
+0

Sembra essere più lento. Forse non ho ancora ottenuto il contesto "giusto" sebbene ... – rball

+0

Post aggiornato con risultati. – rball

+0

Aspetta ... leggi l'articolo completo, sembra che possa aver fornito il contesto sbagliato ?? – rball

Problemi correlati