Where did my comment go related to lower/upper bounds for any number and offset?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hey. To anyone that works on the php.net site. I posted this comment:

http://www.php.net/manual/en/language.operators.bitwise.php#107617

And I saw it there shortly after and even sent that link to some colleagues.
Now it's gone on every mirror too. WTF?? :-( It certainly was relevant as it
used & and ~.

This is what it said basically (although this is a much longer
version/explanation. The note post only had the code function and results).

We've started to convert more of our queries to a "wide" mode and take even
more advantage of memcache instead of a "thin" mode where we hit the DB (and
store in memcache too) for each scene. The idea being that if we make the
queries pull more data than needed (in an intelligent way of course) then we
hit the DB less and memcache more. This works great with the concept of a
DVD vs SCENE as one is macro and one is micro. 

I used some bitwise operations to figure out a lower/upper number for any
given number (and offset). 

/**
 * Get the upper and lower boundaries for any given number and 2^n offset
(other offsets give bizarre results)
 *
 * @access	public
 * @return	array
 * @param 	integer $number
 * @param	integer $offset (32) must be a 2^n value [8, 16, 32, 64,
128, ...)
 * @author	Daevid Vincent
 * @date      2012-02-21
 */
function boundaries_ul($number, $offset=32)
{
	if ($offset < 8) return false; //nothing smaller than this makes
practical sense
	if (($offset & ($offset - 1)) != 0) return false; //not a 2^n
	
	$offset = $offset - 1;
	
	//zero out least significant bits. 
	//For example if $offset = 32, then the least 5 bits [16 8 4 2 1] ==
31 == 0xFFE0
	$lowerbound = $number & ~$offset;
	$upperbound = $lowerbound + $offset;
	
	return array('lower_bound'=>$lowerbound,
'upper_bound'=>$upperbound);
}

for ($i = 0; $i < 20; $i++) 
{
	debug_print($i, 'forloop $i decimal');
	$b = boundaries_ul($i, 8);
	var_dump($b); 
	echo "<hr>\n";
}
?>

________________________________________
forloop $i decimal = 3
array
  'lower_bound' => int 0
  'upper_bound' => int 7
________________________________________
forloop $i decimal = 4
array
  'lower_bound' => int 0
  'upper_bound' => int 7
________________________________________
forloop $i decimal = 5
array
  'lower_bound' => int 0
  'upper_bound' => int 7
________________________________________
...
________________________________________
forloop $i decimal = 12
array
  'lower_bound' => int 8
  'upper_bound' => int 15
________________________________________
forloop $i decimal = 13
array
  'lower_bound' => int 8
  'upper_bound' => int 15
________________________________________
forloop $i decimal = 14
array
  'lower_bound' => int 8
  'upper_bound' => int 15
________________________________________


In the get_like()/get_dislike(), we pull in both at the same time from the
same table, which is great. But we can only pull in by scene_id and not a
whole dvd_id (since we don't have the dvd_id in that table) as many of the
other queries I'm converting. That got me thinking of how can I get more
juice for the squeeze. Given that most scenes (if not all) are sequential
that is a clue.

We use the md5($sql) as the hash for memcache so that's why this works,
since the same 128 scene_id's will all result in the same $sql query string
(thanks to upper/lower bounds) and therefore the same hash key is pulled.

Knowing these 'constants', I then fabricate a query for say scene_id = 21269

var_dump(boundaries_ul(21269, 128));

Which would look something like this:

SELECT `scene_id`, `like`, `dislike` FROM `scene_likes` WHERE `scene_id`
BETWEEN 21248 AND 21375;

The MD5 hash = 801206aca6ee8b908095161db8d77585 . Which is now the same for
ANY of 128 scenes from 21248 through 21375 and therefore all in the same
memcache slab.

Now in code, pull up to 128 rows at a time (since a memcache slab can be
upto 1 MB, this should easily fit)

$b = boundaries_ul($this->id, 128);
$result = $con->fetch_query_pair("SELECT `scene_id`,
CONCAT(`like`,'|',`dislike`) FROM `scene_likes` WHERE `scene_id` BETWEEN
".$b['lower_bound']." AND ".$b['upper_bound']);
list($this->like, $this->dislike) = explode('|', $result[$this->id]); 

And with a little clever PHP slicing and dicing, I have an index right to
the scene_id and the dis/likes. fetch_query_pair() does just like it sounds,
it returns a hash/array where the $col[0] is the key and $col[1] is the
value since this is such a common thing to do.



-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux