High Performance Javascript




Tuesday, May 4, 2010
Posicionamento de
                              Scripts

               • Cada <script> bloqueia o render da página
                       até acabar o seu download
               • Tags <script> devem ser colocadas o mais
                       abaixo possível na página, antes de ser
                       fechado o </body>




Tuesday, May 4, 2010
Agrupar Scripts


               • Os Scripts devem ser minificados e
                       agrupados, melhorando o tempo de
                       download e libertando slots de pedidos
                       HTTP




Tuesday, May 4, 2010
Elementos de Script
                           Dinâmicos
                              loadScript.js




Tuesday, May 4, 2010
Acesso a Dados

               • Valores literais (null, undefined, ...)
               • Variáveis (var x = “teste”)
               • Arrays (var arr=[1, 2, “três”])
               • Object Members (var obj = {chave: “valor”})


Tuesday, May 4, 2010
Acesso a Dados


               • Regra geral, o tempo de acesso a variáveis
                       locais e valores literais é bastante
                       menor do que o tempo de acesso a arrays
                       e objectos.




Tuesday, May 4, 2010
Acesso a Dados


               • Variáveis locais e literais devem ser
                       utilizados sempre que possível em vez de
                       arrays ou objectos.




Tuesday, May 4, 2010
Scope Chain
               • Cada função tem uma propriedade interna
                       ( [[Scope]])
               • Contém uma colecção de objectos que
                       representa o scope no qual a função foi
                       criada.
               • Determina os dados a que a função pode
                       aceder



Tuesday, May 4, 2010
Scope Chain

               • Quando a função é criada, herda todas as
                       variáveis presentes na Scope Global
               • Cada chamada a uma função cria um
                       “Execution Context”, que define o ambiente
                       em que a função é executada




Tuesday, May 4, 2010
Scope Chain

               • É criado um “Activation Object”, que
                       contém entradas para todas as variáveis,
                       argumentos (e a colecção arguments) e a
                       variável this.
               • Este Activation Object é adicionado à Scope
                       Chain, à frente do objecto Global.



Tuesday, May 4, 2010
Scope Chain

               • Quando uma variável é acedida, o motor
                       procura-a por toda a Scope Chain,
                       começando pelo objecto mais à frente na
                       cadeia.
               • Quanto mais longe na cadeia estiver a
                       variável pretendida, mais impacto tem na
                       performance.



Tuesday, May 4, 2010
Scope Chain


               • É aconselhável armazenar todos os objectos
                       fora do Activation Object da função,
                       reduzindo o impacto na performance.

                                 storing_in_locals.js



Tuesday, May 4, 2010
Closures

               • Uma função dentro de outra função cria
                       uma closure.
               • Quando a primeira função acaba de
                       executar, o seu Activation Object não
                       morre, e continua acessível à função em
                       closure.


                                      closures.js
Tuesday, May 4, 2010
Object Members


               • Quanto mais longe na Prototype Chain um
                       membro estiver, mais custa aceder-lhe.
               • Fazer cache de valores em Object Members!

                                       objects.js

Tuesday, May 4, 2010
DOM Access

               • DOM Tree: Representação da estrutura da
                       página
               • Render Tree: Representação de como os nós
                       do DOM devem ser mostrados.




Tuesday, May 4, 2010
DOM Access


               • Quando uma mudança no DOM afecta a
                       geometria de um elemento (altura &
                       largura), o browser necessita de recalcular a
                       geometria desse elemento




Tuesday, May 4, 2010
DOM Access

               • ... E a geometria e posição de todos os
                       elementos que possam ser afectados!!
               • Este processo chama-se reflow.
               • Quando o reflow acaba, o browser redesenha
                       as partes do documento afectadas (repaint)




Tuesday, May 4, 2010
DOM Access

               • A maioria dos browsers optimiza o processo
                       de reflow com uma queue de mudanças.
               • Podemos dar ordem (involutariamente, por
                       vezes) para esvaziar a queue...




Tuesday, May 4, 2010
DOM Access

               • ... Quando são pedidas informações de
                        layout:
                       • offsetTop, offsetLeft, offsetWidth, offsetHeight;
                       • scrollTop, scrollLeft, scrollWidth, scrollHeight;
                       • clientTop, clientLeft, clientWidth, clientHeight
                       • getComputedStyle (currentStyle em IE)



Tuesday, May 4, 2010
DOM Access

               • Enquanto mudamos estilos, devemos evitar
                       ler ou escrever estas propriedades.
               • O número de reflows e repaints deve ser
                       reduzido ao máximo para evitar bloquear a
                       UI.




Tuesday, May 4, 2010
DOM Access


               • Mudanças do DOM em batch:
                       •   Retirar o elemento do flow do documento

                       •   Aplicar todas as mudanças

                       •   Trazer o elemento de volta ao documento




                                                  dom.js

Tuesday, May 4, 2010
Event Delegation
               • 1000+ elementos no DOM com event
                       listeners (!!!!)
               • Quantos mais handlers, mais tempo
                       demoram a ser atribuídos (isto geralmente
                       acontece em onLoad ou
                       DOMContentReady!!!)
               • Também gasta memória armazenar info
                       sobre todos os handlers na página!


Tuesday, May 4, 2010
Event Delegation

               • No DOM, os eventos bubble up, ou seja,
                       alastram desde o elemento que dispara o
                       evento até à root do documento (a menos
                       que sejam impedidos por instruções
                       especiais)




Tuesday, May 4, 2010
Event Delegation

               • Podemos assim criar um delegate, um único
                       handler de eventos, no topo do documento,
                       que se preocupe em lidar com todos os
                       eventos que lhe chegam a partir dos outros
                       elementos na página.


                                Event Delegation.js

Tuesday, May 4, 2010
Program Flow




Tuesday, May 4, 2010
Loops


                        loops.js




Tuesday, May 4, 2010
Loops


               • for ... in é bastante mais lento, pois necessita
                       de procurar propriedades de um objecto a
                       cada iteração




Tuesday, May 4, 2010
Loops


               • Principais bottlenecks:
                       •   Trabalho por iteração

                       •   Número de iterações




                                                   loops.js


Tuesday, May 4, 2010
Loops


               • Function based-iteration ($.each em jQuery)
                       é consideravelmente mais lento que loop-
                       based iteration, levando até 8 (!!) vezes mais
                       tempo a executar.




Tuesday, May 4, 2010
Lookup Tables


               • São extremamente mais rápidas que switch
                       ou encadeamentos if-else, e melhoram a
                       legibilidade do código.




Tuesday, May 4, 2010
Lookup Tables


               • Devem ser utilizadas quando existir um
                       mapeamento lógico entre uma chave e um
                       valor.




Tuesday, May 4, 2010
Lookup Tables


               • Um switch deve ser utilizado se cada chave
                       requerer um conjunto de acções muito
                       específico, que seja impossível de abstrair.




Tuesday, May 4, 2010
Optimizar jQuery


               • Cache de selectores!!!
               • Event delegation ($.delegate e $.live)
               • Esquecer $.each


Tuesday, May 4, 2010

Workshop js

  • 1.
  • 2.
    Posicionamento de Scripts • Cada <script> bloqueia o render da página até acabar o seu download • Tags <script> devem ser colocadas o mais abaixo possível na página, antes de ser fechado o </body> Tuesday, May 4, 2010
  • 3.
    Agrupar Scripts • Os Scripts devem ser minificados e agrupados, melhorando o tempo de download e libertando slots de pedidos HTTP Tuesday, May 4, 2010
  • 4.
    Elementos de Script Dinâmicos loadScript.js Tuesday, May 4, 2010
  • 5.
    Acesso a Dados • Valores literais (null, undefined, ...) • Variáveis (var x = “teste”) • Arrays (var arr=[1, 2, “três”]) • Object Members (var obj = {chave: “valor”}) Tuesday, May 4, 2010
  • 6.
    Acesso a Dados • Regra geral, o tempo de acesso a variáveis locais e valores literais é bastante menor do que o tempo de acesso a arrays e objectos. Tuesday, May 4, 2010
  • 7.
    Acesso a Dados • Variáveis locais e literais devem ser utilizados sempre que possível em vez de arrays ou objectos. Tuesday, May 4, 2010
  • 8.
    Scope Chain • Cada função tem uma propriedade interna ( [[Scope]]) • Contém uma colecção de objectos que representa o scope no qual a função foi criada. • Determina os dados a que a função pode aceder Tuesday, May 4, 2010
  • 9.
    Scope Chain • Quando a função é criada, herda todas as variáveis presentes na Scope Global • Cada chamada a uma função cria um “Execution Context”, que define o ambiente em que a função é executada Tuesday, May 4, 2010
  • 10.
    Scope Chain • É criado um “Activation Object”, que contém entradas para todas as variáveis, argumentos (e a colecção arguments) e a variável this. • Este Activation Object é adicionado à Scope Chain, à frente do objecto Global. Tuesday, May 4, 2010
  • 11.
    Scope Chain • Quando uma variável é acedida, o motor procura-a por toda a Scope Chain, começando pelo objecto mais à frente na cadeia. • Quanto mais longe na cadeia estiver a variável pretendida, mais impacto tem na performance. Tuesday, May 4, 2010
  • 12.
    Scope Chain • É aconselhável armazenar todos os objectos fora do Activation Object da função, reduzindo o impacto na performance. storing_in_locals.js Tuesday, May 4, 2010
  • 13.
    Closures • Uma função dentro de outra função cria uma closure. • Quando a primeira função acaba de executar, o seu Activation Object não morre, e continua acessível à função em closure. closures.js Tuesday, May 4, 2010
  • 14.
    Object Members • Quanto mais longe na Prototype Chain um membro estiver, mais custa aceder-lhe. • Fazer cache de valores em Object Members! objects.js Tuesday, May 4, 2010
  • 15.
    DOM Access • DOM Tree: Representação da estrutura da página • Render Tree: Representação de como os nós do DOM devem ser mostrados. Tuesday, May 4, 2010
  • 16.
    DOM Access • Quando uma mudança no DOM afecta a geometria de um elemento (altura & largura), o browser necessita de recalcular a geometria desse elemento Tuesday, May 4, 2010
  • 17.
    DOM Access • ... E a geometria e posição de todos os elementos que possam ser afectados!! • Este processo chama-se reflow. • Quando o reflow acaba, o browser redesenha as partes do documento afectadas (repaint) Tuesday, May 4, 2010
  • 18.
    DOM Access • A maioria dos browsers optimiza o processo de reflow com uma queue de mudanças. • Podemos dar ordem (involutariamente, por vezes) para esvaziar a queue... Tuesday, May 4, 2010
  • 19.
    DOM Access • ... Quando são pedidas informações de layout: • offsetTop, offsetLeft, offsetWidth, offsetHeight; • scrollTop, scrollLeft, scrollWidth, scrollHeight; • clientTop, clientLeft, clientWidth, clientHeight • getComputedStyle (currentStyle em IE) Tuesday, May 4, 2010
  • 20.
    DOM Access • Enquanto mudamos estilos, devemos evitar ler ou escrever estas propriedades. • O número de reflows e repaints deve ser reduzido ao máximo para evitar bloquear a UI. Tuesday, May 4, 2010
  • 21.
    DOM Access • Mudanças do DOM em batch: • Retirar o elemento do flow do documento • Aplicar todas as mudanças • Trazer o elemento de volta ao documento dom.js Tuesday, May 4, 2010
  • 22.
    Event Delegation • 1000+ elementos no DOM com event listeners (!!!!) • Quantos mais handlers, mais tempo demoram a ser atribuídos (isto geralmente acontece em onLoad ou DOMContentReady!!!) • Também gasta memória armazenar info sobre todos os handlers na página! Tuesday, May 4, 2010
  • 23.
    Event Delegation • No DOM, os eventos bubble up, ou seja, alastram desde o elemento que dispara o evento até à root do documento (a menos que sejam impedidos por instruções especiais) Tuesday, May 4, 2010
  • 24.
    Event Delegation • Podemos assim criar um delegate, um único handler de eventos, no topo do documento, que se preocupe em lidar com todos os eventos que lhe chegam a partir dos outros elementos na página. Event Delegation.js Tuesday, May 4, 2010
  • 25.
  • 26.
    Loops loops.js Tuesday, May 4, 2010
  • 27.
    Loops • for ... in é bastante mais lento, pois necessita de procurar propriedades de um objecto a cada iteração Tuesday, May 4, 2010
  • 28.
    Loops • Principais bottlenecks: • Trabalho por iteração • Número de iterações loops.js Tuesday, May 4, 2010
  • 29.
    Loops • Function based-iteration ($.each em jQuery) é consideravelmente mais lento que loop- based iteration, levando até 8 (!!) vezes mais tempo a executar. Tuesday, May 4, 2010
  • 30.
    Lookup Tables • São extremamente mais rápidas que switch ou encadeamentos if-else, e melhoram a legibilidade do código. Tuesday, May 4, 2010
  • 31.
    Lookup Tables • Devem ser utilizadas quando existir um mapeamento lógico entre uma chave e um valor. Tuesday, May 4, 2010
  • 32.
    Lookup Tables • Um switch deve ser utilizado se cada chave requerer um conjunto de acções muito específico, que seja impossível de abstrair. Tuesday, May 4, 2010
  • 33.
    Optimizar jQuery • Cache de selectores!!! • Event delegation ($.delegate e $.live) • Esquecer $.each Tuesday, May 4, 2010