php goodness

Alternative PHP mock object

Posted in Short by phpgoodness on June 7, 2011

I created a small github repo where I publish the project of the weekend, PHPTestDummy.

PHPTestDummy is a framework that creates mock objects of your PHP classes. It is capable to define actions for stubs and giving information of the stub calls to be used for assertions. Is might be an alternative mock object solution for PHPUnit.

See: php-test-dummy.org and github/tcz/PHPTestDummy

PHPTestDummy is in an “alpha” stage and therefore it can be buggy. Please report any problem you encounter in the Github issues section. Quite some improvements are planned to be implemented soon, but please, if you specificly would like to see something, open an issue as well.

Tagged with: ,

PHPTracker

Posted in Short by phpgoodness on February 25, 2011

PHPTracker It took my spare time in the last couple of days to finish the first release of a project called PHPTracker.

It is an all in one Bittorrent creator, tracker server and seed server written in PHP. It creates you the .torrent file, manages peer announcements and initially serves your file. Ideal when your website serves big files with high traffic (for example your software you developed). Good thing about it, when you have enough external seeders, it automatically stops seeding from your server saving you a significant amount of money on bandwidth.

PHPTracker is released under the BSD license and can be downloaded here:

PHPTracker

Simple examples follow.

Creating torrent file

// -----------------------------------------------------------
// This is how to create a .torrent file from a physical file.
// -----------------------------------------------------------

// Registering autoloader, essential to use the library.
require( dirname(__FILE__).'/lib/PHPTracker/Autoloader.php' );
PHPTracker_Autoloader::register();

// Creating a simple config object. You can replace this with your object
// implementing PHPTracker_Config_Interface.
$config = new PHPTracker_Config_Simple( array(
    // Persistense object implementing PHPTracker_Persistence_Interface.
    // We use MySQL here. The object is initialized with its own config.
    'persistence' => new PHPTracker_Persistence_Mysql(
        new PHPTracker_Config_Simple( array(
            'db_host'       => '192.168.1.100',
            'db_user'       => 'misc',
            'db_password'   => 'misc',
            'db_name'       => 'misc',
        ) )
    ),
    // List of public announce URLs on your server.
    'announce'  => array(
        'http://php-tracker.dev/example_announce.php',
    ),
) );

// Core class managing creating the file.
$core = new PHPTracker_Core( $config );

// Setting appropiate HTTP header and sending back the .torrrent file.
// This is VERY inefficient to do! SAVE the .torrent file on your server and
// serve the saved copy!
header( 'Content-Type: application/x-bittorrent' );
header( 'Content-Disposition: attachment; filename="test.torrent"' );

// The first parameters is a path (can be absolute) of the file,
// the second is the piece size in bytes.
echo $core->createTorrent( 'netbeans.exe', 524288 );

Preparing announce URL

// ---------------------------------------
// This is how to set up an announce URL.
// ---------------------------------------

// Registering autoloader, essential to use the library.
require( dirname(__FILE__).'/lib/PHPTracker/Autoloader.php' );
PHPTracker_Autoloader::register();

// Creating a simple config object. You can replace this with your object
// implementing PHPTracker_Config_Interface.
$config = new PHPTracker_Config_Simple( array(
    // Persistense object implementing PHPTracker_Persistence_Interface.
    // We use MySQL here. The object is initialized with its own config.
    'persistence' => new PHPTracker_Persistence_Mysql(
        new PHPTracker_Config_Simple( array(
            'db_host'       => '192.168.1.100',
            'db_user'       => 'misc',
            'db_password'   => 'misc',
            'db_name'       => 'misc',
        ) )
    ),
    // The IP address of the connecting client.
    'ip'        => $_SERVER['REMOTE_ADDR'],
    // Interval of the next announcement in seconds - sent back to the client.
    'interval'  => 60,
) );

// Core class managing the announcements.
$core = new PHPTracker_Core( $config );

// We take the parameters the client is sending and initialize a config
// object with them. Again, you can implement your own Config class to do this.
$get = new PHPTracker_Config_Simple( $_GET );

// We simply send back the results of the announce method to the client.
echo $core->announce( $get )

Starting seed server

// --------------------------------------
// This is how to start a seeding server.
// --------------------------------------

// [!] Run this file in CLI only!
// /usr/bin/php example_seeder.php

// Registering autoloader, essential to use the library.
require( dirname(__FILE__).'/lib/PHPTracker/Autoloader.php' );
PHPTracker_Autoloader::register();

// Persistense object implementing PHPTracker_Persistence_Interface.
// We use MySQL here. The object is initialized with its own config.
$persistence = new PHPTracker_Persistence_Mysql(
    new PHPTracker_Config_Simple( array(
        'db_host'       => '192.168.1.100',
        'db_user'       => 'misc',
        'db_password'   => 'misc',
        'db_name'       => 'misc',
    ) )
);

// Setting up seeder peer. This will listen to connections and serve files.
$peer = new PHPTracker_Seeder_Peer(
    new PHPTracker_Config_Simple( array(
        'persistence'           => $persistence,
        // PUBLIC address of the seeder server. This will be used fr announcements (ie. sent to the clients).
        'seeder_address'        => '192.168.1.100',
        'seeder_port'           => 6881,
        // Number telling how many processes should be forked to listen to incoming connections.
        'peer_forks'            => 10,
        // If specified, gives a number of outsider seeders to make self-seeding stop.
        // This saves you bandwidth - once your file is seeded by others, you can stop serving it.
        // Number of seeders is permanently checked, but probably 1 is too few if you want your file to be available always.
        'seeders_stop_seeding'  => 5,
    )
) );

// We set up a seeding server which starts the seeding peer, and makes regular
// announcements to the database adding itself to the peer list for all
// active torrents.
$server = new PHPTracker_Seeder_Server(
     new PHPTracker_Config_Simple( array(
        'persistence'           => $persistence,
        'peer'                  => $peer,
    )
) );

$server->start();

Do you like it?

Some PHP performance myths

Posted in Short by phpgoodness on July 23, 2010

Let’s do some benchmarking and prove (or disprove) some urban legends.

Echo vs Print

Echo claimed to be quicker, since actually it’s not a function (but a language construct), and therefore it doesn’t return a value. Print is not a real function either, but acts like a function, and always returns 1.

Also, to echo you can pass comma-separated strings and it will output hem right aways, one by one (just like your would have several different echos following each other), that is, PHP doesn’t need to concatenate them first in the memory, they can be written to the output immediately.

Average, relative 1000 10000 1000000
echo, with comma 1,00 700ms 6528ms 583318ms
echo, with concat 1,06 740ms 6425ms 670096ms
print, with concat 1,12 773ms 6841ms 700804ms

As you can see the theory is works in practice, although the difference is not that big. I used 4 separate strings with 4-8 characters. If you code (and if you still use direct output writing at all), try using echo with commas.

Increment

Incrementing (or decrementing) an integer with 1 is a quite common operation again. You can do it (at least) in 4 ways using PHP.

Average, relative 1000 10000 1000000
++$j; 1,00 281ms 2375ms 228295ms
$j++; 1,20 358ms 2759ms 265173ms
$j += 1; 1,20 342ms 2843ms 273779ms
$j = $j + 1; 1,33 368ms 3150ms 307458ms

++$j (pre-increment) is markedly quicker than the others (20%-30%). Why? All the other operations first copy the value of $j to the memory, increment it there (in that temporary register) and then assign it to $j. This is obvious for the last 2 cases, but what about $j++ (post-increment)?

The difference between the two increment operator is that the latter ($j++) first return the original value of $j, and then increments it. That is, it needs the copy of the value. If use increment operation in a void context (that is, you simply want to increment the value), use ++$j.

Instanceof

I think it is a not very well-known performance issue. Apparently PHP uses string comparison to determine is an object is an instance of a class. Though instanceof operator is pretty quick, it’s not all the same, how long is your class name.

Average, relative 1000 10000 1000000
Short classname: (1 char): 1,00 449ms 3615ms 356093ms
Long classname (26 char): 1,84 760ms 6852ms 684316ms
Very long classname (78 char): 3,74 1495ms 14234ms 1405590ms

See? Pretty amazing difference. So readability vs performance? Since instanceof is not a frequently used operation, I vote for long (but readable) class names, but if you use if often, you may consider removing some extra characters.

For the tests I used PHP 5.2.5, command line execution on Debian. On a request I can add the benchmarking scripts to the post.

Late static binding before PHP 5.3

Posted in Short by phpgoodness on July 20, 2010

If you are still lazy (or funk) to upgrade to PHP 5.3 and use the numerous cool new features, or your hands are simply tied because of those nasty backwards compatibility issues, here’s a little trick how to emulate late static binding (or why don’t we call it static dynamic binding).

Let’s start with class constants. Feel free to use this piece of code to access child class constants from the parent:


constant( get_class( $this ) . '::CONSTANT_NAME' );

For static methods:

call_user_func( array( get_class( $this ), 'method_name' ), 'param1' );

And (eeh) for variables:

eval( 'return ' . get_class( $this ) . '::$variable;' );

Finally, putting this all together in one horrible example:

class A
{
	function  __construct()
	{
		call_user_func(
			array( get_class( $this ), 'echoHello' ),
			constant( get_class( $this ) . '::SAYING_HELLO' ),
			eval( 'return ' . get_class( $this ) . '::$name;' )
		);
	}
}
class B extends A
{
	const SAYING_HELLO = 'Hi';
	static $name = 'Mr. Buzz Killington';
	static function echoHello( $saying_hello, $name )
	{
		echo "$saying_hello $name";
	}
}
$b = new B;

What’s the problem here? There are 3 issues why you still have to do that damn upgrade.

  1. Ugly.
  2. Performance; this is simply slow.
  3. This is not real late static binding. In real late static binding you will execute the method that is defined in the latest derived class where the static method is defined. In our case, this class is always the currently executing, final class (the class of $this), so we don’t really talk about inheritance here.To hack “real” static binding, you should iterate through the parents one by one of the class of $this in case the method (or variable or constant) is not defined.

Conclusions? If you really need late static binding, you’d better upgrade, or simply don’t use static methods variables and class constants.