2012-10-19 11 views
6

Sto avendo seri problemi di prestazioni visive & con lo script seguente. Il problema più grande è che l'animazione dell'oggetto sta diventando davvero a scatti, quasi paralizzante in IE9, ma sempre più fastidiosa in Firefox.Prestazioni JS/jQuery scadenti, in particolare in IE9 e Firefox

È stato abbastanza veloce fino a poco tempo fa, ma sono preoccupato per la complessità che sta rallentando le cose. Stranamente il Sunspider benchmark viene eseguito più velocemente nella mia istanza di IE9, che in Firefox.

Lo script (che è un frammento di una collezione più ampia ***):

  1. assegni un registro di memorizzazione delle sessioni HTML5 della progressione utenti attraverso il gioco.
  2. A seconda del livello, anima un oggetto tra due punti utilizzando crSpline.
  3. garantisce la finestra del browser segue l'oggetto attraverso una grande tela, tramite scrollLeft ecc
  4. Infine, si carica una finestra di popup tramite colorbox.
  5. Quando questa casella è chiusa, il registro progressione utente viene incrementato di conseguenza e l'oggetto si sposta nuovamente.

Ci sono abili evidenti miglioramenti di velocità che potrei apportare al mio codice? C'è un bel po 'di ripetizione, come posso ridurlo? Ci sono cicli infiniti in esecuzione che mi mancano? C'è un software che posso usare per profilare i punti lenti del JS?

*** (non posso fornire altri file JS o HTML, ma ho identificato questo script come il problema)


UPDATE: Dopo un bel po 'di più test, sembra che la funzione animate passo - che segue l'oggetto nella finestra tramite scrollLeft - stia causando l'animazione a scatti. Rimozione migliora notevolmente le cose.

Tuttavia, questa non è una soluzione valida a lungo termine. Una soluzione rapida consiste nel richiamare la funzione follow al completamento, ma questa è un'esperienza molto meno fluida per l'utente finale, specialmente quando l'oggetto si sposta su distanze maggiori.

Quindi, come modifico la funzione di passo per eseguire un 'molto più' lento/più efficiente? Immagino che il movimento sia causato da esso utilizzando tutte le risorse disponibili per seguire l'oggetto ogni millisecondo.

(function ($) { 

    sessionStorage.gameMainStage = 0 

    moveShip = function() { 

    switch (sessionStorage.gameMainStage) 

{ 
    case '1': 
    $("#object").animate(
     { crSpline: $.crSpline.buildSequence([[715, 425], [582, 524], [556, 646], [722, 688], [963, 629], [1143, 467]]) },{ 
     duration: 10000, 
      step: function() { 
      var mover = $('#object'),    
      posX = mover.position().left; 
      posY = mover.position().top; 

      $(window) 
      .scrollLeft(posX - $(window).width()/2) 
      .scrollTop(posY - $(window).height()/2); 
      }, 
      complete: function() { 
      $.colorbox({href:"dialog-1.html", width:"737px", height:"474px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
      } 
     } 
    ); 
    break; 

    case '2': 
    $("#object").animate(
     { crSpline: $.crSpline.buildSequence([[1143, 467], [1343, 667], [1443, 367], [1243, 167], [1499, 285]]) }, 
     { 
      duration: 5000, 
      step: function() { 
      var mover = $('#object'),    
      posX = mover.position().left; 
      posY = mover.position().top; 

      $(window) 
      .scrollLeft(posX - $(window).width()/2) 
      .scrollTop(posY - $(window).height()/2); 
      }, 
      complete: function() { 
      $.colorbox({href:"dialog-2", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
      } 

     } 
    ); 
    break; 

    case '3': 
    $("#object").animate(
     { crSpline: $.crSpline.buildSequence([[1499, 285], [1922, 423]]) }, 
     { 
      duration: 5000, 
      step: function() { 
      var mover = $('#object'),    
      posX = mover.position().left; 
      posY = mover.position().top; 

      $(window) 
      .scrollLeft(posX - $(window).width()/2) 
      .scrollTop(posY - $(window).height()/2); 
      }, 
      complete: function() { 
      $.colorbox({href:"dialog-3.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
      } 

     } 
    ); 
    break; 

    case '4': 
    $("#object").animate(
     { crSpline: $.crSpline.buildSequence([[1922, 423], [2216, 578]]) },{ 
     duration: 5000, 
      step: function() { 
      var mover = $('#object'),    
      posX = mover.position().left; 
      posY = mover.position().top; 

      $(window) 
      .scrollLeft(posX - $(window).width()/2) 
      .scrollTop(posY - $(window).height()/2); 
      }, 

      complete: function() { 
      $.colorbox({href:"game-1.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
      } 
     } 
    ); 
    break; 

    case '5': 
    $("#object").animate(
     { crSpline: $.crSpline.buildSequence([[2216, 578], [2769, 904]]) },{ 
     duration: 5000, 
      step: function() { 
      var mover = $('#object'),    
      posX = mover.position().left; 
      posY = mover.position().top; 

      $(window) 
      .scrollLeft(posX - $(window).width()/2) 
      .scrollTop(posY - $(window).height()/2); 
      }, 

      complete: function() { 
      $.colorbox({href:"dialog-4.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
      } 
     } 
    ); 
    break; 

    case '6': 
    $("#object").animate(
     { crSpline: $.crSpline.buildSequence([[2769, 904], [3263, 903]]) },{ 
     duration: 5000, 
      step: function() { 
      var mover = $('#object'),    
      posX = mover.position().left; 
      posY = mover.position().top; 

      $(window) 
      .scrollLeft(posX - $(window).width()/2) 
      .scrollTop(posY - $(window).height()/2); 
      }, 

      complete: function() { 
      $.colorbox({href:"dialog-5.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
      } 
     } 
    ); 
    break; 

    case '7': 
    $.colorbox({href:"game-2.html", width:"500px", height:"600px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
    break; 

    case '8': 
    $.colorbox({href:"dialog-6.html", width:"737px", height:"567px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
    break; 

    case '9': 
    $("#object").animate(
     { crSpline: $.crSpline.buildSequence([[3263, 903], [4141, 820]]) },{ 
     duration: 5000, 
      step: function() { 
      var mover = $('#object'),    
      posX = mover.position().left; 
      posY = mover.position().top; 

      $(window) 
      .scrollLeft(posX - $(window).width()/2) 
      .scrollTop(posY - $(window).height()/2); 
      }, 

      complete: function() { 
      $.colorbox({href:"dialog-7.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
      } 
     } 
    ); 
    break; 

    case '10': 
    $("#object").animate(
     { crSpline: $.crSpline.buildSequence([[4141, 820], [4568, 949], [4447, 1175]]) },{ 
     duration: 5000, 
      step: function() { 
      var mover = $('#object'),    
      posX = mover.position().left; 
      posY = mover.position().top; 

      $(window) 
      .scrollLeft(posX - $(window).width()/2) 
      .scrollTop(posY - $(window).height()/2); 
      }, 

      complete: function() { 
      $.colorbox({href:"dialog-8.html", width:"737px", height:"434px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
      } 
     } 
    ); 
    break; 

    case '11': 
    $.colorbox({href:"dialog-9.html", width:"737px", height:"567px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
    break; 

    case '12': 
    $("#object").animate(
     { crSpline: $.crSpline.buildSequence([[4447, 1175], [4701, 1124], [4816, 822]]) },{ 
     duration: 5000, 
      step: function() { 
      var mover = $('#object'),    
      posX = mover.position().left; 
      posY = mover.position().top; 

      $(window) 
      .scrollLeft(posX - $(window).width()/2) 
      .scrollTop(posY - $(window).height()/2); 
      }, 

      complete: function() { 
      $.colorbox({href:"dialog-10.html", width:"900px", height:"687px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
      } 
     } 
    ); 
    break; 
} 

}; 

})(jQuery); 
+0

Solo una nota a margine dalla tua pagina di benchmark: 'Questo benchmark testa solo il linguaggio JavaScript principale, non il DOM o altre API del browser '- la tua colorbox e le animazioni sono quasi esclusivamente DOM. –

risposta

5

ho riscontrato questo problema con una pagina singola applicazione che agganciato a window.resize e window.scroll. Sembrava essere molto più lento su IE rispetto ad altri browser.

La prima cosa che ho notato, che in IE (versione 8 specifica), un callback collegato a window.scroll o .resize sembrava sparare tante volte in più rispetto a Chrome o FF durante il ridimensionamento della finestra (o scorrendo). Pertanto, qualsiasi callback collegato viene chiamato più volte di quanto Chrome aggiunga al relativo costo.

Siamo riusciti a risolvere il nostro problema riducendo al minimo ciò che viene fatto all'interno di questi callback al minimo, e il guadagno principale che abbiamo avuto è stato sbarazzarsi dei selettori jQuery. Quindi nel tuo caso hai ad esempio var mover = $ ('# object') nella funzione di callback, ogni volta che il tuo evento si attiva, IE proverà a trovare e ottenere oggetti e a racchiuderlo in jQuery, basta farlo una volta all'esterno di il callback e quindi utilizzare l'oggetto memorizzato nella cache. Nel nostro caso, questo ha migliorato le prestazioni in base all'ordine di grandezza e mi è sembrata una buona cosa da fare anche se non si sono verificati problemi di prestazioni (è stata un'operazione ripetuta inutilmente).

Quindi, nel caso in cui 8 per esempio, hanno qualcosa di simile:

case '10':{ 
    //caching myObject once and then use it afterwards 
    var myObject = $("#object"), 
     $window = $(window); 

    myObject.animate(
     { 
     crSpline: $.crSpline.buildSequence([[4141, 820], [4568, 949], [4447, 1175]]) }, 
     { 
     duration: 5000, 
      step: function() { 
      var mover = myObject, //no need to refetch the object    
      posX = mover.position().left; 
      posY = mover.position().top; 

      $window.scrollLeft(posX - $window.width()/2) 
      .scrollTop(posY - $window.height()/2); 
      }, 

      complete: function() { 
      $.colorbox({href:"dialog-8.html", width:"737px", height:"434px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
      } 
     } 
    ); 
} 

ps: Inoltre, non sono sicuro della semantica della vostra applicazione, ma potrebbe essere necessario aggiungere la propria logica per monitorare posX e POSY come potrebbero sempre fare riferimento all'originale oggetto memorizzato nella cache, ma in tutti i casi, fare i passaggi che ho citato per assicurarsi che il costo dei selettori è ciò che sta causando il problema (come era nel mio caso).

0

si potrebbe tentare di controllare per verificare se IE non cerca di lavorare in modalità diversa rispetto alla modalità del browser IE9 e modalità documento IE9 ossia stranezze o modalità di compatibilità. Se prova a forzarlo per usare quelli di default. Force IE compatibility mode off using tags

11

Ho paura che la libreria che si sta utilizzando sia troppo vecchia per aspettarsi grandi prestazioni.

non vedo nulla di male nel codice (tranne che si potrebbe avere utilizzato una funzione con un argomento di configurazione per ogni caso l'interruttore ma questo è solo una questione di refactoring che non influisce sulle prestazioni in modo significativo)

CrSpline utilizza le proprietà CSS sinistra e superiore.

Si potrebbe voler guardare in 2d CSS trasforma che sfruttano l'accelerazione hardware:

Usa -webkit/moz/ms-transform: translateX(-1000px) translateY(200px) invece di left: -1000px; top: 200px;

Penso che si potrebbe facilmente riscrivere parte del codice nella libreria crspline verso quella direzione .

Si potrebbe anche provare a cercare una libreria "splines" più aggiornata.

Un altro punto: crSpline non sembra utilizzare la funzione requestAnimationFrame. Il metodo animate di JQuery non lo è neanche. Consiglierei di dare un'occhiata alla libreria TweenLite/TweenMax: http://www.greensock.com/v12/

Saluti al tuo lavoro!

+0

Le trasformazioni CSS CSS non sono garantite per l'accelerazione hardware. Per assicurarti di ottenere l'accelerazione hardware, dovresti usare translate3d (0, 0, 0), che indica al browser che utilizzerai l'asse Z (e avvierai la GPU). Puoi ancora usare in alto a sinistra e ottenere l'accelerazione hardware. http://www.html5rocks.com/en/tutorials/speed/html5/ – skyline3000

+1

Vero - translate3d è accelerato in HW e porta a un enorme guadagno in termini di prestazioni, ma invocarlo su troppi elementi troppo spesso mangerà solo le risorse accelerate. Le trasformazioni 2d di solito non sono accelerate, tuttavia migliorano ancora di molto le prestazioni, perché la modifica dei loro valori non comporta il ricalcolo del dom e il re-rendering, che è il più grande maiale con le animazioni. – nxtwrld

2

In primo luogo, è necessario ottimizzare il codice creazione di una funzione per l'animazione (non testato, ma dovrebbe opere):

function animateMyObjet(duration,sequence,callback) 
{ 
    $("#object").animate(
    { crSpline: $.crSpline.buildSequence(sequence), 
     { 
      duration: duration, 
      step: function() { 
      var mover = $('#object'),    
      posX = mover.position().left; 
      posY = mover.position().top; 

      $(window) 
      .scrollLeft(posX - $(window).width()/2) 
      .scrollTop(posY - $(window).height()/2); 
      }, 
      complete: function() { 
      callback(); 
     } 
    } 
} 

Chiamato nel codice come questo:

switch (sessionStorage.gameMainStage) 
{ 
    case '1': animateMyObjet(10000,[[715, 425], [582, 524], [556, 646], [722, 688], [963, 629], [1143, 467]],                     
function() { 
$.colorbox({href:"dialog-1.html", width:"737px", height:"474px", iframe: true, overlayClose: false, escKey: false, close: ""}); 
     break; 

case '2' : ... 

} 

In secondo luogo, Alcune settimane fa ho scoperto che il numero di elementi della pagina web ha un impatto sulle prestazioni di IE9. Prova a nascondere tutti gli elementi di cui non hai bisogno come elemento nascosto a causa di un contenitore scorrevole.

A volte, il numero di elementi visibili dello schermo influisce sulle prestazioni delle animazioni. Per il test, prova a ridurre le dimensioni della finestra del browser e riproduci l'animazione. Sono abbastanza sicuro che l'animazione sarà più liscia.

Spero che questi consigli ti aiuteranno. Non dimenticarti di pubblicare la tua soluzione finale se pensi di risolvere il tuo problema!

E, infine, controllare un potenziale argomento correlato su IE9 problema spettacoli: IE9 : Always small CPU utilization on my web site

+0

Il collegamento sull'argomento correlato alla creazione di profili Javascript nella barra degli strumenti di sviluppo Web è davvero utile, grazie. –

0

Il mio pensiero, se si vedono i gestori di eventi chiamati troppo spesso, è che i gestori di eventi hanno appena impostato un timeout (diciamo 10 ms) se nessun timeout è attualmente impostato e hanno il movimento del movimento nella funzione di timeout.

Problemi correlati