Performance – preciso me preocupar tanto?

Este post surgiu quando eu ia publicar aqui a apresentação Extreme Javascript Performance, do autor do script.aculo.us, Thomas Fuchs. O post é mais amplo, não trata de javascript e nem do código em si, mas sim da importância (ou não) de levar em consideração possíveis problemas de performance que poderão causar problemas no futuro.

Quando comecei a "programar"¹ eu não ligava muito para performance. Ok, eu não ligava nem um pouco. 

Motivos que levam um desenvolvedor (noob) não ligar para performance:

  • Ele não sabe bem o que está fazendo
  • A aplicação terá poucos usuários (sobra de recursos)
  • Eventuais problemas de performance não vão causar prejuízo financeiro
  • Pensamento POG: funcionou, deixa assim

Pois bem, guri novo que era, tinha os 4 elementos que precisava para fazer cagada. E obviamente fazia. Fiz meu primeiro blog em PHP, funcionava, postava, subia imagem… o código era uma porcaria, mas funcionava.

 Fazer bem feito...

Fazer bem feito para fazer só uma vez, né?

 

Performance – porque se preocupar?

Com o tempo cresci (apenas no modo de pensar e programar, na altura quem me conhece sabe: nada.), aprendi coisas novas e coisas que eu já deveria saber, brinquei fazendo "mini-serviços", desenvolvi o And After e testei e produzi uma ferramenta que inicialmente era só para o And After mas acabei abrindo e foi utilizada por centenas de publishers – a Vitrine Fácil.

Nesta época eu já dava importância para performance, código bem escrito, mas ainda faltava experiência de gerenciar de "cabo a rabo" uma aplicação que fosse utilizada por diversos usuários, e eu tinha uma tremenda inexperiência com uma coisa importantíssima quando se fala de performance: cache.

Mas mais do que aprender como melhorar performance (isso a gente aprende programando e lendo, mas as vezes "esquece") eu aprendi os motivos para se preocupar com performance dos nosso códigos. E segue uma listinha:

  • Downtime custa CARO quando a ferramenta é lucrativa
  • Downtime suja o nome do serviço (lembram do No Donut for you?)
  • Se o sistema/aplicativo for bom ele terá usuários
  • Você não pode freiar o crescimento do sistema (é o mesmo que freiar os lucros)
  • Muitas vezes é impossível prever o crescimento

 

Como melhorar a performance do código?

Já que optei neste post por não tratar de nenhuma linguagem específica, para alguns leitores as dicas podem ficar uma coisa superficial, mas espero que de alguma forma ajudem na forma de um guia inicial para começar a se preocupar com performance…

  • Cache é importante
  • Estude e domine a linguagem que está utilizando (siga as boas práticas recomendadas)
  • Acompanhe o crescimento do seu serviço / site
  • Realize testes de stress no servidor
  • Monitore "de perto" como está o seu servidor (consumo)
  • Lembre-se denovo: cache é importante
  • Verifique: é necessário otimizar? Não vai prejudicar a manutenção do código ou o desenvolvimento de novas features?

 

Cada caso é um caso, otimizar é importante e pode fazer você economizar com servidor porém não deve lhe causar muita dor de cabeça na hora de fazer uma alteração ou aumentar as funcionalidades do sistema… 😉

Recomendo um posto do meu xará, Guilherme Chapiewski: A falácia da otimização prematura, que aborda a célebre frase “A otimização prematura é a raiz de todo o mal” – e muitas vezes não é bem assim.

 

E você, se preocupa com performance? Discorda do que foi dito acima? Concorda?

Comente, gostaria de saber opiniões dos leitores também 😀

 


¹ As aspas são para indicar um fato simples e que não precisa de maiores explicações: comecei a programar sozinho, like a noob.

Extreme JavaScript performance

Faz algum tempo que comecei a escrever sobre performance no javascript, como introdução a uma apresentação de slides deste neste post, mas achei que o assunto era bastante pano pra manda e resolvi repartir as coisas.

Comecei a escrever tanto sobre a importância de alguns cuidados com perfomance que o post deixou de ser direcionado a Javascript e se tornou um relato da minha curta experiência com cuidados com performance – backend e frontend. Meu post inicial virou um rascunho para um post que sairá em breve: Performance – preciso me preocupar *tanto*? –  linko-o aqui quando publicar.

Voltando ao Javascript, nunca me preocupei tanto com questões de performance no Javascript – pois não fazia coisas muito complexas até um tempo atrás, e sempre me preocupei mais com questões de performance no backend.

Porém quando a aplicação é maior e você precisa manipular bastante interface, informações e tem interação direta com o usuário acaba percebendo que você já tem diversas classes e todas elas precisam funcionar perfeitamente para não comprometer o funcionamento de nada. Não se preocupar com performance neste caso é perigoso, errado, chato bobo e feio.

Thomas Fuchs (o ninja autor do script.aculo.us) realizou uma série de testes comparando métodos de executar uma mesma ação no JavaScript, e fez isso em quatro navegadores: Firefox, Internet Explorer, Ópera e Chrome.

Javascript ninja

Javascript ninja

A apresentação respondeu algumas curiosidades e dúvidas, mostrando qual a forma mais performática de executar um loop, um contador, criar arrays e objetos, declarar variáveis, etc…

 

 

Achei a apresentação e testes realizados bem legais, dá para entender melhor e – na medida do possível – alterar o método de desenvolver para uma forma mais performnática.

Compreendo e concordo que performance não é tudo, pois alguns dos métodos mais performáticos não são os mais produtivos – como por exemplo evitar chamar funções dentro de funções.

Mas de qualquer forma, pensar em performance – e endender um pouco melhor como nossos precioso script vai ser interpretado sempre é interessante!

Sorteio no Twitter com PHP

Semana passada ganhei cinco seriais do Mind Meister Premium (um aplicativo web para construção de mapas mentais) para distribuir e dois deles resolvi distribuir no Twitter.

Questionado pelo @fefurst sobre os próximos prêmios, falei que não sabia como iria fazer o sorteio e ele, monstrinho programador que é, prontamente respondeu que "ia dar uma olhadinha na API do Twitter".

Dito e feito, na mesma manhã ele me envia a primeira versão de um script em PHP (já viu as novidades do PHP 5.3?)que utiliza a API Serch do Twitter procurando por uma mensagem específica (a da promoção, que você pode setar no script) para sortear entre os participantes…

 

Features

  1. Configuração da frase a ser buscada
  2. Pode sortear vários participantes
  3. Lista todos os tweets que estão participando
  4. Não sorteia o responsável pela promoção
  5. Não sorteia mais de uma vez um usuário
  6. Elimina RT´s duplicados
  7. Permite filtrar a data inicial e final dos tweets que participarão do sorteio

 

O código

Agora está na versão 0.3, tudo na agilidade do Furst para publicar um código bonitinho e corrigir alguns bugs. O código está como deve ser: enxuto e fácil de entender, não ousei nem adicionar mais comentários, pois está bastante legível.

 

 

<?php
/*
 * Sorteio no twitter... :D v. 0.3 RC1
 *
 * Auhor: Felipe Furst
 * email: [email protected]
 *
 */
// login de onde origina o sorteio
$login = "gserrano";
// início do perído para avaliação de RT
$data_inicio = strtotime("2009-11-13 08:00");
// fim do perído para avaliação de RT
$data_fim = strtotime("2009-11-18 12:00");
// msg q foi retwitada, atenção as vezes alguém pode retwitar uma msg e ela icar cortada, interessante colocar um código junto da msg ou cortar alguma palavras do final
$rt_string = "@gserrano";
// número de pessoas para sortear
$num_premios = 2;
// ------------------ a partir daqui não se mexe -----------------------
// ------------------ a partir daqui não se mexe -----------------------
// ------------------ a partir daqui não se mexe -----------------------
// ------------------ a partir daqui não se mexe -----------------------
$str = Array("á", "à", "â", "ã", "ä", "é", "è", "ê", "ë", "í", "ì", "î", "ï", "ó", "ò", "ô", "õ", "ö", "ú", "ù", "û", "ü");
$rep = Array("a", "a", "a", "a", "a", "e", "e", "e", "e", "i", "i", "i", "i", "o", "o", "o", "o", "o", "u", "u", "u", "u");
$rt_string = str_replace($str, $rep, strtolower($rt_string));
$search_str = "{$login}";
if(strlen($rt_string) > 0) {
	$temp = explode(" ", $rt_string);
	foreach($temp as $t) {
		$search_str.="+{$t}";
	}
}
$page=1;
$sorteio = Array();
echo "Sorteio de {$num_premios} pr&ecirc;mios.<br><br>";
echo "Twittadas:<br>";
while(true) {
	$twtr_search = "http://search.twitter.com/search.atom?q={$search_str}&rpp=100&page={$page}"; // busca todos os registros possíveis ...
	$str_xml = file_get_contents($twtr_search);
	$xml = new SimpleXMLElement($str_xml);
	$page++;
	if($page > 1500) // a api do twitter só retorna 1500 páginas
		break;
	if(count($xml->{"entry"}) > 0) {
		foreach($xml->{"entry"} as $e) {
			if(strtotime($e->{"published"}) <= $data_fim && strtotime($e->{"published"}) >= $data_inicio) { // tem que estar dentro da data do sorteio
				if(array_search(utf8_decode($e->{"author"}->{"name"}), $sorteio) === false) { // verifica se o cara retwittou mais de uma vez para não aumentar a chance de vitória
					echo date("m.d.y H:i:s", strtotime($e->{"published"})). " - ";
					echo utf8_decode($e->{"author"}->{"name"}).": ".str_replace(Array("<b>", "</b>"), "", utf8_decode($e->{"content"}))."<br>";
					if(strrpos($e->{"author"}->{"name"}, $login) === false) { // não sorteia quem proporciona o sorteio
						$sorteio[] = utf8_decode($e->{"author"}->{"name"});
					}
				}
			}
		}
	}
	else {
		break;
	}
}
if(!empty($sorteio)) {
	echo "<br><br>Sorteado(s):";
	for($i=0; $i<$num_premios; $i++) {
		if(empty($sorteio)) {
			echo "<br><br>sobraram ".($num_premios-$i)." pr&ecirc;mios.";
			break;
		}
		srand(strtotime("now"));
		$randval = rand(0, count($sorteio)-1);
		echo "<br>O vencedor do pr&ecirc;mio n&uacute;mero ".($i+1)." &eacute;: {$sorteio[$randval]}";
		unset($sorteio[$randval]); // não sortei o cara mais de uma vez ...
		$sorteio = array_values($sorteio); // refaz o vetor eliminando a posição nula do maluco removido
	}
}
else {
	echo "<br><br>Não houve twittadas para o sorteio.";
}

 

 

Testei ele aqui e está funcionando perfeitamente. Com essa base dá para implenetar mais coisas, como um reply automático para os vencedores, adicionar periodicamente os concorrentes em um BD para gerar uma "lista" de quem está participando da promoção (caso ela dure vários dias, por exemplo)… criatividade, programadores deste mundo!

 

A base está aí, valeu @fefurst!

Fazer um loop (foreach) no Velocity, com array ou limite numérico

O Chris certa vez publicou aqui um guia inicial de Velocity que ensina os conceitos básicos dessa linguagem para desenvolvimento de templates com objetos Java.

Quando li o post não entendi patavinas, hoje trabalhando com o Chris aqui na MMCafé estou um pouco mais familiarizado com o Velocity, por isso resolvi publicar aqui algumas soluções que estão facilitando minha vida! 😀

Como fazer um loop no velocity com array

Primeiro o básico, listar os itens de um array:

#set ($arr= ["flush", "straight", "full house"])
#foreach($item in $arr)
  Mão no poker: $item
#end

Como fazer um loop no velocity com limite numérico

Agora o que achei que seria mais simples, mas demorei um pouco mais para encontrar em posts e documentações pela interwebs, como fazer um loop de N até 3N por exemplo:

#foreach($i in [3..9])
   <li>$i</li>
#end

 

Pronto, simples assim! Espero ter ajudado quem está começando com o Velocity!

Em tempo, vejam essa programação mágica (POG de primeira) que o Chris publicou lá no blog dele.

Como criar seletores customizados com jQuery

Dia desses estava estudando os seletores do jQuery e nas pesquisas internérdicas encontrei um post bastante interessante sobre seletores customizados do jQuery. Isso significa que eu posso criar uma regra em javascript para praticamente verificar qualquer coisa dos elementos, e utilizar isso como um selector do jQuery.

Exemplo de uso

Tenho um site com diversos links para a wikipedia e gostaria de aplicar uma classe nos links específicos para a wikipedia. Eu posso colocar a classe para cada link criado, mas vamos supor que eu quero automatizar isso (para aplicar a aregra também em links antigos, por exemplo).

A idéia é eu criar um seletor tipo:

$("a:wikipedia").addClass("wikipedia")

Este seletor não existe no jQuery, então vamos ao objetivo do post: criar um seletor customizado. Para extender (não sei se esta seria a palavra correta) e jQuery e criar um seletor customizado o comando á:

$.expr[":"].nomedoseletor = function(obj){
   //Aqui vão as regras

   //return true inclui o elemento no seletor
   //return false
};

 

No meu caso, a regra é simples: quero que o seletor procure links que contenham em alguma parte de sua href o link "wikipedia.org". Para a regra resolvi utilizar expressões regulares (ER), e o nome do meu seletor é wikipedia.

 

Seletor customizado com jquery

Eis o código:

$.expr[":"].wikipedia = function(obj){
   return obj.href.match(/wikipedia.org/);

};

 

E para chamar o seletor:

$("a:wikipedia").addClass("wikipedia")

 

O Chris já alertou que isso não deve ser muito performático, mas tenho que dizer: pode ser bastante útil. Neste exemplo fiz um seletor simples, mas as regras podem ser mais complexas: selecionar links internos, links para áreas específicas do seu site para aplicar ícones nos links, selecionar imagens pelo tamanho, elementos com ou sem atributos específicos…

Ainda sobre a performance, recomendo utilizar seletores específicos preferencialmente dentro de ID´s, poe exemplo: $("#content a:wikipedia") e não "globalizar" os apenas quando necessário não deve causar TANTOS problemas, né?

Não realizei nenhum teste de performance com os seletores customizados, testei apenas o códido de exemplo, funcionou certinho. Hoje a noite quando eu estiver em casa publico o exemplo* no diretório de exemplos do O Desenvolvedor! 🙂

 

Referência: jQuery howto (recomendo a leitura, vários posts interessantes)

 

* resolvi postar mesmo sem o exemplo devido a simplicidade do código 😉