Bandwidth detection -> (Output buffer microtime inaccurate)

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
nunja
Forum Newbie
Posts: 1
Joined: Thu Apr 21, 2011 3:56 am

Bandwidth detection -> (Output buffer microtime inaccurate)

Post by nunja »

Hi all,

I post a strange behavior that could be reproduced (at least on apache2+php5).
I don't know if I am doing wrong but let me explain what I try to achieve.

I need to send chunks of binary data (let's say 30) and analyze the average Kbit/s at the end :

I sum each chunk output time, each chunk size, and perform my Kbit/s calculation at the end.

Code: Select all

<?php
	// this is a dummy script but shows exactly the problem
	
	// build my chunk (binary in real world
	$var= '';
	$o=9000;
	while($o--)
	{
		$var.= "testtest";
	}
	
	// get the size, prepare the memory.
	$size = strlen($var);
	$tt_sent = 0;
	$tt_time = 0;
	
	// I send my chunk 30 times
	for ($i = 0; $i < 30; $i++)
	{
		// start time
		$t = microtime(true);
		echo $var."\n";
		ob_flush();
		flush();
		$e = microtime(true);
		// end time
		// the difference should reprenent what it takes to the server to 
		// transmit chunk to client right ?
		
		// add this chuck bench to the total
		$tt_time += round($e-$t,4);
		$tt_sent += $size;
	}
	
	// total result
	echo "\n total: ".(($tt_sent*8)/($tt_time)/1024)."\n";
	
	?>

In this example above, it works so far ( on localhost, it oscillate from 7000 to 10000 Kbit/s through different tests).

Now, let's say I want to shape the transmission, because I know that the client will have enough of a chunk of data to process for a second.

I decide to use usleep(1000000), to mark a pause between chunk transmission.

Code: Select all

<?php
	// this is a dummy script but shows exactly the problem
	
	// build my chunk (binary in real world
	$var= '';
	$o=9000;
	while($o--)
	{
		$var.= "testtest";
	}
	
	// get the size, prepare the memory.
	$size = strlen($var);
	$tt_sent = 0;
	$tt_time = 0;
	
	// I send my chunk 30 times
	for ($i = 0; $i < 30; $i++)
	{
		// start time
		$t = microtime(true);
		echo $var."\n";
		ob_flush();
		flush();
		$e = microtime(true);
		// end time
		// the difference should reprenent what it takes to the server to 
		// transmit chunk to client right ?
		
		// add this chuck bench to the total
		$tt_time += round($e-$t,4);
		$tt_sent += $size;
	
		usleep(1000000);
	}
	
	// total result
	echo "\n total: ".(($tt_sent*8)/($tt_time)/1024)."\n";
	
	?>
In this last example, I don't know why, the calculated bandwidth can jump from 72000 Kbit/s to 1,200,000, it is totally inaccurate / irrelevant.
Part of the problem is that the time measured to output my chunk is ridiculously low each time a chunk is sent (after the first usleep).

An exemple of the results that I have for the output timer in the first script:

0.152241
0.0001514744
0.41506307856
0.2500698878
0.1329874
0.0189658
...

if I divid the total output size of all my chunks by the total of time it took (adding all the above), according to this formula:

(total_sent*8/(tt_time)/1024

I obtain a good estimate of the average Kbit/s. It tested it successfully against a Net Limiter. If I limit the 80 http port to 64Kbit/s, my results here are more or less accurate.

Now, with the usleep my microtime results are affected in a strange way (I do not want to record the time took by usleep, just want to record the time that the client takes to get a particular flushed chunk).

Kind of results like this:

0.0001514744
0.0005681002
0.000054168
0.00080167
0.00057199
...

That's too low !

For sure, result in Kbit/s is totally wrong then.

I got inspired by this script at first (8th post by Bokeh):
http://www.webdeveloper.com/forum/showt ... hp?t=77891

I am doing something wrong ? Does the buffer output is not synchronous ?

Thanks a Lot
incubi
Forum Contributor
Posts: 119
Joined: Mon Dec 07, 2009 1:47 pm

Re: Bandwidth detection -> (Output buffer microtime inaccura

Post by incubi »

set_time_limit() can have a great effect on usleep. usleep will also eat processor time like mad if set_time_limit() is not set correctly. With that tight of timing I would use microtime and create my own delay I would be sure to use float values to get better accuracy. But that's just a guess :)

Oh, assuming you are in Windows

Lee
Post Reply