Welcome to Scribd, the world's digital library. Read, publish, and share books and documents. See more
Download
Standard view
Full view
of .
Look up keyword
Like this
9Activity
0 of .
Results for:
No results containing your search query
P. 1
Practical PHP Programming

Practical PHP Programming

Ratings: (0)|Views: 127|Likes:
Published by paraagpandey

More info:

Published by: paraagpandey on Aug 17, 2009
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

09/17/2010

pdf

text

original

 
www.linuxformat.co.uk 74
LXF41 JUNE 2003
TutorialPHP
SPEEDIER SCRIPTS
veryone knows that PHP is faster than a speeding ticket,but can it be made to go faster? C programmers have formany years trumpeted the fact that their language isextremely fast and therefore capable of handlingperformance-critical tasks. However, very often you’ll find thatwhen C programmers
really 
need performance, they use inlineassembly code.Open up your Linux kernel source (you
do
have the kernelsource to hand, right?), and pick what you consider to be a CPU-intensive operation. I chose arch/i386/lib/mmx.c, the code thathandles MMX/3dNow! instructions on compatible chips. Insidethis file you’ll see lots of quite complicated C code, but alsoextended instances of assembly code wherever speed is optimal.In fact, if you change directory to the root of the Linux kerneltree, try this command:
grep “__asm__” ./ -rl | wc -l
That searches all the files in the Linux source distribution forinstances of assembly, and counts the number of files that match.In 2.5.65, the number of files in the kernel source that useassembly once or more is the rather ominous number of 666!So, C programmers using assembly is quite a widespread thing.PHP programmers, although blessed with a naturally fastlanguage, can also use a lower-level language for speed-criticaloperations – although in our case, C is next in the food chain.While it’s possible to use assembly code from PHP (through C, as Cprogrammers do), there’s more than enough speed improvement just switching to C, so that’s what we will be covering here.Please note that, within the extent of the space available, thisis a no-holds-barred article – prior knowledge of C is required,knowledge of assembly would be good, and
very 
goodknowledge of PHP is mandatory. Furthermore, in order to providethe most detailed description of how things work, this tutorial hasbeen split into two parts. I hope you will agree it’s worth it!
The C Perspective
PHP itself is written in C, as are Flex and Bison (see this month’s
 Linux Pro
), the lexer and parser that PHP uses internally. Theprocess of executing PHP code works by matching various parts ofcode against pre-defined lists of acceptable grammar. For example:
T_IF T_LEFTBRACK T_CONDITION T_RIGHTBRACKT_LEFTBRACE T_STATEMENT T_RIGHTBRACE
In that piece of pseudo-grammar, T stands for “Type”. It willmatch a statement that starts with
if,
then an opening bracket,followed by any boolean condition, followed by a close bracket,then an opening brace
{
, a statement, then a closing brace
}
.Sound familiar? PHP uses the same sort of rules – although on amuch more complicated level – to parse your code.PHP has hundreds of such rules, and, when it matches them,it calls appropriate internal C functions to handle the statement.For example, when PHP matches the following rule (this is directfrom the PHP source code):
T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME ‘[‘expr ‘]’ ‘}’
The
 Zend Engine
will, amongst other things, call
fetch_array_begin(&$$, &$2, &$4 TSRMLS_CC)
, which usesitems 2 and 4 of the rule (
T_STRING_VARNAME
and
expr
) toread and return an array item. So, as you should be able toguess, that particular handler is for accessing arrays inside strings,eg:
{$foo[‘bar’]}
Because the code to execute your script is just compiled Ccode, it means that no matter how fast your PHP code is, it stillhas to be interpreted then executed as normal C code. PHP isnot compiled to native machine code at any point, so there isnever any chance of it out-performing C, or generally evencoming close to the performance of C.
Faster and faster
So, the way to make your PHP code faster is to replace chunks ofit with pure, compiled C. In PHP, this can be done in three ways:writing your own module, editing the PHP source code, or editingthe
 Zend Engine
.Writing a module for PHP is the accepted way to addfunctionality, and there are many modules available in PHP to doall sorts of tasks. However, modules are the slowest way to addfunctionality, particularly if calls to
dl()
are required to dynamicallyload the module each time a script needs it.Writing functions directly into the PHP source code is fasterthan using modules, but only really possible if you’re working onyour own server. Finally, writing functions directly into the
 Zend  Engine
provides the biggest performance boost, but basicallyconfines your script to your own machine – not many would bewilling to patch their
 Zend Engine
code to try out your code! Thereis actually a surprising boost for shifting code into the
 Zend Engine
– when Andrei Zmievski converted
strlen()
into a
 ZE 
statement asopposed to a function, he reported a 25% speed boost.With such a big gain to be offered, you’re probably thinking
everything
should be put directly into the
 Zend Engine
. However,it’s important to realise that there’s a big trade-off between speed
Practical PHPProgramming 
For more informationabout Flex and Bison see the first part of our new
 LINUX PRO
 tutorial seriesstarting on page 11.
Flex andBison
What’s faster than PHP code? Surely nothing!
Paul Hudson
shows you how to make your scripts run 326 times faster!
LXF41.tut_php 5/2/03 12:47 PM Page 74
 
www.linuxformat.co.uk 
LXF41 JUNE 2003
75
TutorialPHP
and manageability, and generally modules come out top becausethey operate more than fast enough for most needs.
C vs PHP
To give you an idea of quite how much faster C is compared toPHP, I wrote a very simple C extension and compared it with itsPHP equivalent. Here’s the PHP script:
<?php$start = time();for ($count = 1; $count < 1000000; ++$count) {$j = 0;for ($i = 0; $i < 999; ++$i) {$j += $i;}}echo “PHP time: “, time() - $start, “ (number: $j)\n”;$start = time();for ($count = 1; $count < 1000000; ++$count) {$result = lxf_hardwork();}echo “C time: “, time() - $start, “ (number: $result)\n”;?>
lxf_hardwork()
is the module function I’ve written in C. Don’tworry about how to create and install modules yet – we’ll get tothat later. For the time being, here’s the source code to the
lxf_hardwork()
function:
PHP_FUNCTION(lxf_hardwork){int i = 0;int j = 0;for (i = 0; i < 999; ++i) { j += i;}RETURN_LONG(j);}
PHP_FUNCTION
and
RETURN_LONG
are both C macros toavoid lots of complicated code in source files, and they can beignored for now. The rest of the code simply performs exactly thesame thing as the PHP code, just in C – as you can see, the twoare very similar linguistically.Executing the PHP script first runs through two loops addingup numbers, then runs through another loop and calls our Cfunction. This could have been optimised further by putting theouter loop into the C code also, but leaving it inside PHP allowedme to tweak the number of iterations without a recompile.When the script is run, it outputs how long both PHP and Ctook to execute the loops. If you’re not sitting down, I suggest yougrab onto something before reading on!PHP took a total of total of 1,956 seconds to run through theloops. The C code, in comparison, took just
 five seconds
to doexactly the same. Of course, when you consider the loop is only999,000,000 iterations and that this is an 800MHz PIII abletherefore to do 800,000,000 operations a second, five secondssounds quite a lot. However the loop in
lxf_hardwork()
functioncompiles down to the following assembly:
.L319:addl %eax,%edxincl %eaxcmpl $998,%eax jle .L319
From the label L319, add
i
to
 j
, increment
i
by one, compare itagainst
998
, and if it’s less than or equal to
998
, re-do the loop.So, there’s actually four instructions in there, one of which is a jump, which is a branch instruction and therefore incurs more ofa speed hit than the others. So, albeit somewhat simplified, Ihope you can see that five seconds really isn’t all that much – it’sas fast as the computer could go!In the example code above, we saw a 326x speedimprovement when switching to C. Naturally the example is hardlyfrom a real-world piece of code, but suffice to say that convertingto C is likely to give a huge performance boost no matter whatyou choose to do with it.
Before we begin
If you’re still reading, you’re hopefully all set to write your own PHPextension. Extension writing in PHP is actually fairly easy, becausethe PHP team have put a lot of work into making the process asstreamlined and foolproof as possible. Furthermore, as you’lldiscover, th
 Zend Engine
is a remarkable piece of software thatreally takes much of the hard work away from programmers. Youwill need to have the PHP source code on your system.For the purpose of this tutorial, we’ll be creating an extensionfor PHP that handles tar files. To do this, our extension will usethe
 libtar 
library created by Mark D Roth, available from
http://freshmeat.net/projects/libtar/
.
 libtar 
is available underthe BSD licence, so we’re free to use it for our needs. You’ll needto have the
 libtar 
development files on your system.Just to make sure we’re all reading from the same songsheet,I want to briefly discuss the tar format. TAR (short for TapeARchive) was designed to handle tape backups, but has been ingeneral use for quite some time. Put simply, a tar file is aconcatenation of files that are not compressed. Using tar, manyfiles become one file, which can then be compressed using gzipor bz2. Tar files by themselves are uncompressed, andapproximately equal in size to the sum of the files it holds.
First steps
To get you started with a module, PHP includes
ext_skel 
, whichcreates the skeleton of an extension. To run
ext_skel 
, go into theext directory of the PHP source code, then type:
 
./ext_skel —extame=tar
ext_skel 
creates for you a tar.h file and a tar.c file to contain our
>>
It’s not often you hear me say this, but the PHP manual is
 not 
 the best place to check forinfoon writing extensions. Thereason for this is because theinformation in the online manualis an edited version of one of the chapters from
Web Application Development with  PHP 4.0 
(Ratschiller & Gerken,New Riders ISBN 0-7357-0997-1). Although
WA
is a goodbook in itself, it’s quite old –much of what is in there justdoesn’t apply any more. Theonline version available in thePHP manual has a number ofedits to bring the work up tospeed, but the end result is thatsome information is correct andsome is not – read with caution!
Special Warning
PHP manual – read with care!
LXF41.tut_php 5/2/03 12:47 PM Page 75
 
www.linuxformat.co.uk 76
LXF41 JUNE 2003code, tar.php to test installation of the module has worked,config.m4, which is part of PHP’s automatic build system(explained later), and also a default test file for your extension.First off, open up tar.c and browse around. My version is 183lines, encompassing pre-written code to do all sorts of taskscommon to extensions. As you can see, using
ext_skel 
saves youquite a lot of work!Now, onto the config.m4. This is a pretty horrifying file at first, butit does require changing at least once. The m4 file is used by PHP’sbuildconf script to generate the configure script so that all themodules are configured by end users in one central location. Ourconfig.m4 file needs just one or two minor changes to get it working.Firstly, when running configure, modules are enabled usingeither
--enable-x
or
--with-x
. The difference here is that the
--enable-x
syntax is used when no special headers or librariesare required to compile the extension, whereas
--with-x
is formodules that reference external files. As our tar extensionrequires libtar to compile, we need to use
--with-tar
.To achieve this, look for the line
dnl PHP_ARG_WITH(tar, fortar support 
,. The
dnl
part is a comment, so this line is ignored. Toenable
--with-tar
support, remove the
dnl
from this line. Then,delete the next line altogether (
dln Make sure that...
)andremove the
dnl
on the line after that (
dnl [ --with-tar...
). So,the lines should look like this:
PHP_ARG_WITH(tar, for tar support,[ --with-tar Include tar support])
There are a few other tweaks that need to be made to the filebefore we’re finished with it, but it gets complicated – here’s howyour file should look:
dnl $Id$dnl config.m4 for extension tarPHP_ARG_WITH(tar, for tar support,[ —with-tar Include tar support])if test “$PHP_TAR” != “no”; thenSEARCH_PATH=”/usr/local /usr”SEARCH_FOR=”/include/libtar.h”if test -r $PHP_TAR/; thenTAR_DIR=$PHP_TARelse # search default path list AC_MSG_CHECKING([for tar files in default path])for i in $SEARCH_PATH ; doif test -r $i/$SEARCH_FOR; thenTAR_DIR=$iAC_MSG_RESULT(found in $i)fidonefiif test -z “$TAR_DIR”; thenAC_MSG_RESULT([not found])AC_MSG_ERROR([Please reinstall the tar distribution])fiPHP_ADD_INCLUDE($TAR_DIR/include)LIBNAME=tarLIBSYMBOL=tar_openPHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,[
TutorialPHP
<<
Can optimisation be taken foo far? Reading through the /gcc/man page, you’ll see all sorts of optimisation flags that can bepassed in to theoretically make code run faster. Eg
-ffast-math
will “cheat” on some mathematics calls to make coderun faster, whereas
-funroll-loops
will try to cut down thenumber of fixed loop iterations by increasing the code size.However, these optimisations need to be used with great care.Without wishing to get into to much depth — this article isafter all about PHP – optimisation in programming isgenerally a trade-off between size of code and speed of code– sometimes its faster to use more CPU instructions than it is to use fewer, which results in larger executable size. However,a key exception to this rule is tight loops of code, wherehaving more instructions inside the loop will make the CPU’sinstruction cache overflow causing a speed hit.Optimising compilers such as GCC, when instructed tooptimise with the
-Ox
flag, generally aim to achieve maximumperformance with the least increase in code size. However,with certain flags being used, “optimisation” can result insubstantially slower code. For example, compiling PHP with
-g -O3 -ffast-math -fomit-frame-pointer -fexpensive-optimizations
executed the first script in 51 seconds. Adding
-funroll-loops
 to that actually makes the script take 60seconds to execute.Porting code from PHP to C can often give a hugeperformance boost to your applications, but you need to becareful – switching to C makes it much easier to shootyourself in the foot, or, worse, shoot your whole leg off!
Over-optimisation
There’s a fine line – cross it at your peril!
man gcc
will show you a thousand ways to make your code run faster or slower, dependingon your mother’s maiden name, the colour of your socks and the phase of the moon.
LXF41.tut_php 5/2/03 12:47 PM Page 76

Activity (9)

You've already reviewed this. Edit your review.
1 hundred reads
Adams Ibrahim liked this
Adams Ibrahim liked this
Dax Smith liked this
Sameera Mohammed liked this
Dane Morgan liked this
smauliks liked this

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->