Month: February 2010

Gentoo

Gentoo emerge conflicts: SQLite and dev-perl/DBD-SQLite

I was having issues with my regular update schedule on my Gentoo server where I kept getting the following message:
('ebuild', '/', 'dev-db/sqlite-3.6.22-r2', 'merge') conflicts with
=dev-db/sqlite-3.6.22[extensions] required by ('installed', '/', 'dev-perl/DBD-SQLite-1.29-r2', 'nomerge')

Since I use SQLite fairly regularly and I like to keep it up to date I figured I would focus on getting that updated, then worry about the Perl SQLite. (Had I known that spamassassin relies on the Perl SQLite I may have been a little more hesitant, but it all worked out ok anyway.)

Here is how I managed to update both SQLite and the Perl SQLite. I first unmerged dev-perl/DBD-SQLite with:
emerge --unmerge dev-perl/DBD-SQLite

I then updated SQLite with:
emerge -u sqlite

Which changed the USE settings to “-extensions” which meant that when I tried to emerge DBD-SQLite it failed due to the missing USE requirements. So I took a stab at it and did:
USE="extensions" emerge sqlite
Which built cleanly without any problems, and after which a quick
emerge dev-perl/DBD-SQLite worked great.

So, in a quick and easy cut and paste format the work-around is:
emerge --unmerge DBD-SQLite
emerge -u sqlite
USE="extensions" emerge sqlite
emerge DBD-SQLite

Why the work-around is required I don’t know at the moment as I don’t have the time to dig through the ebuild files and figure out where the issue is, although I am sure if I had waited a bit updated ebuild files will come down the pipeline to correct the issue. (Patience is a virtue, but I have never been all that virtuous.)

Development

Comparing PHP array_shift to array_pop

I noticed a note in the PHP documentation about speed differences between array_shift() (pulling the first element off the array) and array_reverse() followed by array_pop() (resulting in the same data, but got to by pulling the last element off the array).

Since I was working on some code to convert URL pieces to program arguments (like turning /admin/users/1/edit into section=admin, module=users, id=1, action=edit – stuff we tend to do every day) I thought I would take a look at the speed differences since I have always used array_shift() for this (after turning the string into an array via explode()).

My initial tests showed that array_shift was much faster than array_reverse followed by array_pop, and I wondered why someone would say that in the first place. But then I thought about it for a bit. When using array_shift the entire remaining array has to be re-indexed every call. For a very short array (like the one I was using) this is negligible. When you start looking at much larger arrays, however, this overhead adds up quickly.

To find out roughly where the break-even point on these two methods lie I whipped up a quick script to run with arrays sized from 10^1 values up to 10^5 values. What I found is that at less than 100 values you are not really gaining much (if anything) by using array_reverse and array_pop versus array_shift. Once you get to the 1000 value array size, however, the differences really add up (as you can see in the logarithmic scaling of the chart below).

shift_vs_pop.jpg

The code I used to generate the numbers (which are shown in the chart as averages over 3 runs, rounded to the nearest millionth of a second) is:

<?php
$counts = array(10,100,1000,10000,100000);
foreach ($counts as $len)
{
	$m2 = $m1 = array();
	$x = 1;
	while ($x <= $len)
	{
		$m2[] = $m1[] = $x;
		$x++;
	}
	echo "Timing with array_shift() for $len items\n";
	echo "000000";
	$s1 = microtime(true);
	while (!empty($m1))
	{
		$tmp = array_shift($m1);
		if ($tmp % 10 == 0)
		{
			echo chr(8),chr(8),chr(8),chr(8),chr(8),chr(8);
			echo str_pad(''.$tmp,6,'0',STR_PAD_LEFT);
		}
	}
	$s2 = microtime(true);
	echo "\nTook ",$s2 - $s1," seconds\n";
	
	echo "Timing with array_reverse and array_pop() for $len items\n";
	$s1 = microtime(true);
	$m2 = array_reverse($m2);
	while (!empty($m2))
	{
		$tmp = array_pop($m2);
		if ($tmp % 10 == 0)
		{
			echo chr(8),chr(8),chr(8),chr(8),chr(8),chr(8);
			echo str_pad(''.$tmp,6,'0',STR_PAD_LEFT);
		}
	}
	$s2 = microtime(true);
	echo "\nTook ",$s2 - $s1," seconds\n";
	echo "\n";
}
?>