Made of Everything You're Not

Personal blog of PHP programmer Eric Lamb.
  • Blog
  • Portfolio
« Remember; Not Everyones Smart
lighttpd. use it »

php, sprintf and Memory Usage

I was going through some legacy code for a client and ran across a whole bunch of calls to sprintf(). The calls were all similiar to the below:

$query = sprintf('SELECT * FROM table WHERE field1 = "%s" AND field2 = "%s" LIMIT 1',$var1, $var2);

It seemed an odd use to call the above instead of the straight forward, and low impact, way of declaring the variable.

$query = "SELECT * FROM table WHERE field1 = '$var1' AND field2 = '$var2' LIMIT 1";

I've never really had the need to use sprintf() so I'm not familiar with it enough to know much so I asked a colleague of mine, Devin, "What process would require the use of sprintf?". According to Devin, sprintf is used for complicated and dynamic formatting. Here's an example from the php manual on the subject:

<?php
$n =  43951789;
$u = -43951789;
$c = 65; // ASCII 65 is 'A'
 
// notice the double %%, this prints a literal '%' character
printf("%%b = '%b'\n", $n); // binary representation
printf("%%c = '%c'\n", $c); // print the ascii character, same as chr() function
printf("%%d = '%d'\n", $n); // standard integer representation
printf("%%e = '%e'\n", $n); // scientific notation
printf("%%u = '%u'\n", $n); // unsigned integer representation of a positive integer
printf("%%u = '%u'\n", $u); // unsigned integer representation of a negative integer
printf("%%f = '%f'\n", $n); // floating point representation
printf("%%o = '%o'\n", $n); // octal representation
printf("%%s = '%s'\n", $n); // string representation
printf("%%x = '%x'\n", $n); // hexadecimal representation (lower-case)
printf("%%X = '%X'\n", $n); // hexadecimal representation (upper-case)
 
printf("%%+d = '%+d'\n", $n); // sign specifier on a positive integer
printf("%%+d = '%+d'\n", $u); // sign specifier on a negative integer
?>

The above outputs:

%b = '10100111101010011010101101'
%c = 'A'
%d = '43951789'
%e = '4.39518e+7'
%u = '43951789'
%u = '4251015507'
%f = '43951789.000000'
%o = '247523255'
%s = '43951789'
%x = '29ea6ad'
%X = '29EA6AD'
%+d = '+43951789'
%+d = '-43951789'

Pretty cool, but I'm not still not sure what the purpose of using sprintf() like the first example demonstrated would accomplish. Surely, there must be some sort of performance penalty, right? According to a programmer Devin used to work, there's a HUGE penalty for using sprintf. To find out I wrote a simple test script, that's the farthest thing from scientific, to just get a generic baseline on memory usage and sprintf().

<?php
 
for($i=0;$i<100000;$i++){
	//Call sprintf
}
 
echo filesize_format(memory_get_usage());
echo '<br>';
echo filesize_format(memory_get_peak_usage());
 
function filesize_format($bytes, $format = '%01.5lf %s', $force = '')
{
	$force = strtoupper($force);
	$defaultFormat = '%01d %s';
	if (strlen($format) == 0)
			$format = $defaultFormat;
 
	$bytes = max(0, (int) $bytes);
 
	$units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
 
	$power = array_search($force, $units);
 
	if ($power === false) {
		$power = $bytes > 0 ? floor(log($bytes, 1024)) : 0;
	}
 
	return sprintf($format, $bytes / pow(1024, $power), $units);
}
?>

First the baseline. This is without running the loop.

/*
Baseline of 0 loops just php start stop:
Total: 71.39062 KB
Peak: 76.84375 KB
*/

Next, I did a run of sprintf() calls like the below:

/*
Total: 73.76562 KB
Peak: 77.22656 KB
*/
for($i=0;$i<100000;$i++){
	$t = 'SELECT col1,col2,col3 FROM table WHERE col1="1" AND col2="2" LIMIT 1';
}

Followed by a straight variable declaration:

/*
Total: 72.82812 KB
Peak: 77.17969 KB
*/
for($i=0;$i<100000;$i++){
	$t = 'SELECT col1,col2,col3 FROM table WHERE col1="1" AND col2="2"  LIMIT 1';
}

Huh... the numbers don't really add up to all that much. I really thought it'd be more of a difference than that. Well, just to be sure I ran two more tests like the above, except with 4 variables being created instead of 1.

/*
Peak: 76.69531 KB
Peak: 78.28125 KB
*/
for($i=0;$i<100000;$i++){
	$t = sprintf('SELECT col1,col2,col3 FROM table WHERE col1="%s" AND col2="%s" LIMIT 1','1', '2');
	$r = sprintf('SELECT col1,col2,col3 FROM table WHERE col1="%s" AND col2="%s" LIMIT 1','1', '2');
	$k = sprintf('SELECT col1,col2,col3 FROM table WHERE col1="%s" AND col2="%s" LIMIT 1','1', '2');
	$o = sprintf('SELECT col1,col2,col3 FROM table WHERE col1="%s" AND col2="%s" LIMIT 1','1', '2');
 
}

And

/*
Peak: 73.95312 KB
Peak: 77.48438 KB
*/
for($i=0;$i<100000;$i++){
	$t = 'SELECT col1,col2,col3 FROM table WHERE col1="1" AND col2="2" LIMIT 1';
	$r = 'SELECT col1,col2,col3 FROM table WHERE col1="1" AND col2="2" LIMIT 1';
	$k = 'SELECT col1,col2,col3 FROM table WHERE col1="1" AND col2="2" LIMIT 1';
	$o = 'SELECT col1,col2,col3 FROM table WHERE col1="1" AND col2="2" LIMIT 1';
}

Look at that; nothing. There doesn't appear to be any significant increase in memory in relation to usage. For a loop that runs 100,000 times compared to a memory increase of only about 1 KB this really isn't bad. Use sprintf if you want to.

Oh yeah, Devin you were lied to smile

Related Posts

ACM Interactions
Stand Alone ExpressionEngine Authentication
MSRC
Importing Legacy Users Into ExpressionEngine
Nesting Platform

Tags: memory usage php sprintf

This entry was written by Eric Lamb and posted on January 22nd, 2009 at 10:52 am and is filed under Code, Programming. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response below.

3 Comments

  1. Devin says:
    February 05, 2009 at 05:56 pm

    I wonder if I was lied to…..appears from your testing that there is not a big hit in memory. Anyone else ?

    Reply | Quote
  2. Alex says:
    April 06, 2010 at 02:12 am

    Using your example as a base I ran a trial using sprintf to format a string that was about nine megs.  Over 1000 loops sprintf wound up using over six more megs than using simple string concatenation. 

    I guess sprintf really shouldn’t be used with data that large.

    Reply | Quote
  3. free cosmetic samples in india 2011 says:
    April 16, 2012 at 12:38 pm

    It undoubtedly does take quite some time to find fantastic data like this. Thanks a lot. Best Regards http://lifecellskin.org/free-cosmetic-samples/

    Reply | Quote

Leave a Reply

Click here to cancel reply.

  • Subscribe: Entries | Comments
  • About Me

    Email Email
    Twitter Twitter
    310.739.3322
  • Categories

    • Brain Dump
    • Business
    • Code
    • IT
    • Programming
    • Rant
    • Servers
  • Archives

    • February 2012
    • October 2011
    • August 2011
    • July 2011
    • June 2011
    • May 2011
    • April 2011
    • March 2011
    • February 2011
    • January 2011
    • December 2010
    • November 2010
    • October 2010
    • September 2010
    • August 2010
    • July 2010
    • June 2010
    • May 2010
    • April 2010
    • March 2010
    • February 2010
    • January 2010
    • December 2009
    • November 2009
    • October 2009
    • September 2009
    • August 2009
    • July 2009
    • June 2009
    • May 2009
    • April 2009
    • March 2009
    • February 2009
    • January 2009
    • December 2008
    • November 2008
    • October 2008
  • Advertisement

Copyright © 2008 - 2013 Eric Lamb - All rights reserved