software‎ > ‎módulos‎ > ‎web framework‎ > ‎

dicas sobre desempenho

Custo das exceções em JavaScript

postado em 1 de out de 2010 12:39 por Usuário desconhecido   [ atualizado em 4 de nov de 2011 06:20 por Usuário desconhecido ]

Normalmente as linguagens de programação com suporte a exceções partem do pressuposto que exceções são ... "exceções". Devem ser raras e indicam uma quebra abrupta do fluxo normal de um processamento. 

Com base neste pressuposto, os compiladores e interpretadores buscam eliminar os custos das estruturas de captura de exceções para o cenário mais frequente, quando não ocorrem exceções. Esta otimização normalmente implica na geração um custo elevado no momento da captura de uma exceção.

As implicações práticas deste comportamento é que devemos evitar a criação de códigos onde a geração de exceções seja frequente, principalmente em laços. Nestes casos, o try...catch deve ser substituído por uma código que teste um comportamento sem o uso da tentativa e erro.

Exemplo com exceções:

function test(n) {
   if (n % 2) {
      throw new Error("Fail!");
   }
}
var failCount = 0;
for (var i = 0; i < 10000; ++i) {
   try {
      test(i);
   } catch (e) {
      failCount++;
   }
}

RunTime: 62 milisegundos

Exemplo sem exceções:

function test(n) {
   return !(n % 2);
}
var failCount = 0;
for (var i = 0; i < 10000; ++i) {
   if (!test(i)) {
      failCount++;
   }
}

RunTime: 15 milisegundos


Os exemplos acima são extremos e tem o objetivo de demonstrar o custo de uma exceção. No dia-a-dia, observamos casos aparentemente inocentes, mas igualmente danosos. Exemplos: 
  1. Testar se um campo existe em um DataSet, acessando-o como uma propriedade e ignorando o erro caso não exista. Nestes casos, o try/catch pode ser substituído por um findField.
  2. Tentar identificar a tabela de uma chave tentando acessar um campo que somente existe em uma tabela. É mais elegante e otimizado utilizar o método dbCache.findKey(), que retorna um objeto onde uma das propriedades é o tableName.

Loop em uma String versus indexOf

postado em 1 de out de 2010 12:24 por Usuário desconhecido   [ atualizado em 1 de out de 2010 12:31 por Usuário desconhecido ]

Não faça um loop em uma string quando pode ser utilizando um indexOf. A iteração em JavaScript possui um desempenho bem inferior ao indexOf nativo.

Código original com loop: 46 execuções demoraram 905 ms.
Código otimizado com indexOf: 46 execuções demoraram 16 ms.

Original:

function prepareStringToXmlParser(str) {
   var resultArray = new Array();
   var lastCopyPos = 0;
   for (var i = 0; i < str.length; i++) {
      if (str.charCodeAt(i) == 13) {
         resultArray.push(str.substring(lastCopyPos, i) + String.fromCharCode(10));
         if (((i+1) < str.length) && (str.charCodeAt(i+1) == 10)) {
            i++;
         }
         lastCopyPos = i + 1;
      }
   }
   resultArray.push(str.substring(lastCopyPos, i));

   return resultArray.join('');
}


Otimizado:

function prepareStringToXmlParser(s) {
   var escaped = null;
   var startIdx = 0;
   var len = s.length;
   var idx = s.indexOf("\r");
   while (idx != -1) {
      escaped += s.substring(startIdx, idx);
      startIdx = idx + 1;
      if (startIdx === len || s.charCodeAt(startIdx) !== 10) {
         escaped += "\n";
      }
      idx = s.indexOf("\r", idx+1);
   }

   if (escaped === null) {
      return s;
   } else {
      return escaped + s.substr(startIdx);
   }
}

1-2 of 2