Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

falcao544

Porque usar sprintf?

Recommended Posts

A minha dúvida é essa mesmo, porque usar sprintf? Vejo muitas pessoas usando o sprintf, mas não entendo o porque! Já li sobre o sprintf no php.net, mas mesmo assim não vi nada que justificasse tantas pessoas usarem!

 

 

Obrigado!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Mais ou menos, como o PHP não tem uma tipagem muito forte, igual a do Java, C++ ... um exemplo:

$x1 = '10' ; // string
$x2 = 10 ; // integer
$x = ($x1 + $x2); // 20 

 

Se você mandar '10', e sua função no C++ esperar um int, ou no Java, você terá um erro, lá você teria que fazer esse cast.

No php, independente de ser integer/string, a soma será feita.

 

Em java:

public class PrimitiveTypes {
      public static void main(String[] args) {
             int x1 = 10 ;
             String x2 = "10";

             int x = x1 + x2 ;
             System.out.println(x);
      }
}

Resulta em:

Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - incompatible types required: int

 

Não vou dar o exemplo em C++ porque estou sem o compiler aqui.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Às vezes é melhor do que ficar concatenando variáveis, quando se tem uma sentença longa composta de várias variáveis.

 

$t = 'Olá, meu nome é' . $nome . ', tenho ' . $idade . ' anos  e sou ' . $profissao;

ou

$t = sprintf('Olá, meu nome é %s, tenho %d anos e sou %s', $nome, $idade, $profissao);

 

Normalmente, quem teve um pouco de contato com C e os *printf, *scanf da vida prefere esse tipo de sintaxe. Eu uso bastante, odeio ter que ficar abrindo e fechando aspas pra concatenar strings e não uso as aspas duplas por questões de performance:

 

$t = "Olá, meu nome é {$nome}, tenho {$idade} anos  e sou {$profissao}";

O PHP vai ler toooooda essa string aí procurando por variáveis. Quando usamos aspas simples, ele não procura variáveis dentro da string, melhorando o desempenho.

 

Edit: essa questão do desempenho foi o próprio Rasmus Lerdorf que apontou no seu blog pessoal.

Entretanto, aqui diz o contrário:

http://judebert.com/progress/archives/204-PHP-String-Formatting-Performance.html

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fiz alguns testes aqui, obtive outras medidas:

$ php test.php 100 1000

Saída:

Média de 100 repetições para 1000 concatenações
sprintf: 0.001989 s
single-quote: 0.000702 s
double-quote: 0.000783 s
heredoc: 0.000813 s

 

Executei várias vezes os testes. Usando single-quote ou double-quote e heredoc, os valores são bem parecidos e tendem ao mesmo ponto a medida que eu aumento o número de concatenações. O sprintf vem sempre na lanterna.

 

O benchmark usado foi esse:

 

<?php
set_time_limit(0);
$nome = 'Henrique';
$idade = '21';
$profissao = 'Estudante';

$times = array();
$phrase;

$rep = isset($argv[1]) ? $argv[1] : 1000;
$cat = isset($argv[2]) ? $argv[2] : 1000;

printf("Média de %d repetições para %d concatenações\n", $rep, $cat);

for($i = 0; $i < $rep; $i++) {
$ini = microtime(true);
for($j = 0; $j < $cat; $j++) {
	$phrase = sprintf('Olá, meu nome é %s, tenho %d anos e sou %s',
		$nome, $idade, $profissao);
}
$end = microtime(true);
$times[] = $end - $ini;
}

printf("sprintf: %f s\n", array_sum($times)/$rep);
$times = array();

for($i = 0; $i < $rep; $i++) {
$ini = microtime(true);
for($j = 0; $j < $cat; $j++) {
	$phrase = 'Olá, meu nome é '. $nome . ', tenho ' .
		$idade . ' anos e sou ' . $profissao;
}
$end = microtime(true);
$times[] = $end - $ini;
}

printf("single-quote: %f s\n", array_sum($times)/$rep);
$times = array();

for($i = 0; $i < $rep; $i++) {
$ini = microtime(true);
for($j = 0; $j < $cat; $j++) {
	$phrase = "Olá, meu nome é ${nome}, tenho ${idade} anos
		e sou ${profissao}";
}
$end = microtime(true);
$times[] = $end - $ini;
}

printf("double-quote: %f s\n", array_sum($times)/$rep);
$times = array();

for($i = 0; $i < $rep; $i++) {
$ini = microtime(true);
for($j = 0; $j < $cat; $j++) {
	$phrase = <<<HEREDOC
		Olá, meu nome é ${nome}, tenho ${idade} anos
		e sou ${profissao}
HEREDOC;
}
$end = microtime(true);
$times[] = $end - $ini;
}

printf("heredoc: %f s\n", array_sum($times)/$rep);

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Seu teste está correto Henrique. A "precedência de performance" é essa mesma:

 

Single Quotes >> Double Quotes >> Heredoc >> (v)(s)printf (e cia)

 

Usar (v)(s)printf não é o melhor em termos de performance pois você está invocando uma função, que por si só, já tem seu "custo".

 

Além disso,(v)(s)printf tem de analisar toda a string, verificar quantos placeholders foram definidos, verificar se foram informados argumentos suficientes, se são do tipo certo e ainda fazer a conversão.

 

Mas, pelo menos pra mim, o benefício proporcionado é tão grande que ignoro veementemente as outras formas de composição de string. :closedeyes:

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Henrique Barcelos

Só uma consideração. No manual do PHP, há um teste de performance sobre apóstrofo e aspas duplas. Ele foi feito por um usuário na parte de códigos. E acredite, aspas duplas se demonstrou mais performático. A diferença foi mínima, mas em todos os testes feitos, foi superior.

 

Segue o teste, eu adaptei com sprintf e suas variações.

 

Código:

<?php$var = 1;

for( $x=0; $x < 21; $x++ ) {
   echo '<br /><br />var = int( '.$var.' )<br />';


   $tempoInicial = microtime(true);
   for( $i=0; $i<100001; $i++ )
   {
       $string = " {$var} {$var} {$var} {$var} {$var} {$var} {$var} {$var} {$var} {$var} {$var} {$var} {$var} {$var} {$var}";
       unset( $string );
   }
   $tempoFinal = microtime(true);
   echo '<br />One string with 15 $vars was set using one concat 100000 times and took '.number_format(($tempoFinal - $tempoInicial), 3, ',', '.').' seconds to execute ';

   $tempoInicial = microtime(true);
   for( $i=0; $i<100001; $i++ )
   {
       $string = ' '.$var.' '.$var.' '.$var.' '.$var.' '.$var.' '.$var.' '.$var.' '.$var.' '.$var.' '.$var.' '.$var.' '.$var.' '.$var.' '.$var.' '.$var;
       unset( $string );
   }
   $tempoFinal = microtime(true);
   echo '<br />One string with 15 instances of $var was set using multiple concats 100000 times and took '.number_format(($tempoFinal - $tempoInicial), 3, ',', '.').' seconds to execute';

   $tempoInicial = microtime(true);
   for( $i=0; $i<100001; $i++ )
   {
       $string = sprintf( ' %s  %s  %s  %s  %s  %s  %s  %s  %s  %s  %s  %s  %s  %s  %s', $var, $var, $var, $var, $var, $var, $var, $var, $var, $var, $var, $var, $var, $var, $var );
       unset( $string );
   }
   $tempoFinal = microtime(true);
   echo '<br />One string with 15 instances of $var was set using sprintf with 15 tokens variables 100000 times and took'.number_format(($tempoFinal - $tempoInicial), 3, ',', '.').' seconds to execute';

   $tempoInicial = microtime(true);
   for( $i=0; $i<100001; $i++ )
   {
       $string = sprintf( ' %1$s %1$s %1$s %1$s %1$s %1$s %1$s %1$s %1$s %1$s %1$s %1$s %1$s %1$s %1$s', $var );
       unset( $string );
   }
   $tempoFinal = microtime(true);
   echo '<br />One string with 15 instances of $var was set using sprintf with 15 tokens variables 100000 times and took'.number_format(($tempoFinal - $tempoInicial), 3, ',', '.').' seconds to execute';
}

 

Resultado (apenas dois):

var = int( 1 )

 

One string with 15 instances of $var was set using multiple concats 100000 times and took 0,628 seconds to execute

One string with 15 $vars was set using one concat 100000 times and took 0,428 seconds to execute

One string with 15 instances of $var was set using sprintf with 15 tokens variables 100000 times and took0,664 seconds to execute

One string with 15 instances of $var was set using sprintf with 15 tokens variables 100000 times and took0,876 seconds to execute

 

var = int( 1 )

 

One string with 15 instances of $var was set using multiple concats 100000 times and took 0,615 seconds to execute

One string with 15 $vars was set using one concat 100000 times and took 0,424 seconds to execute

One string with 15 instances of $var was set using sprintf with 15 tokens variables 100000 times and took0,665 seconds to execute

One string with 15 instances of $var was set using sprintf with 15 tokens variables 100000 times and took0,841 seconds to execute

 

A diferença foi mínima, mas todos os testes demonstraram que aspas duplas é mais performático. É bem interessante notar a evolução do core do PHP. Lembrando que esse código estava no manual do php.

 

Edit----

 

Tenho de colocar uma consideração.

 

Talvez, apóstrofo, seja mais performático em menos concatenações. O teste do Henrique foi com mil registros, o do manual, foi com 100 mil. Isso também deve ser levado em consideração. A quantidade variáveis também deve ser levada em consideração.

 

Não desconsiderando nenhum teste. Mas isso já ser torna um pouco de mito entre ambos os modos.

 

 

Edit 2----

Link do teste original:

http://www.php.net/manual/pt_BR/language.operators.string.php#71062

 

Encontrei a explicação dada por um desenvolvedor. Segue:

Use double quotes to concat more than two strings instead of multiple '.' operators. PHP is forced to re-concatenate with every '.' operator.

 

O que esclarece uma das minhas considerações. Para 3 ou mais variáveis, aspas duplas se torna mais performático.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pois então, pra dar uma diferença significativa, você tem que fazer algumas mil concatenações... Como provavelmente nem faça desse tanto no sistema inteiro em uma única requisição, aí vai do gosto do cliente mesmo. Eu gosto bastante da sintaxe dos *printf quando vou lançar exceções cuja mensagem tem variáveis.

Normalmente uso aspas simples por causa do agora mito de ser mais rápido, agora vou considerar voltar às aspas duplas também... :grin:

Compartilhar este post


Link para o post
Compartilhar em outros sites

É bem interessante essa evolução. Eu gosto de aspas duplas pois vim do Java. Entretanto, não gosto de não concatenar a variável, fica muito perdido em textos longos.

 

Também uso bastante o printf e sprintf. Se tornou uma função muito útil.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.