2

I am trying to perform a downstream bandwidth speed test in PHP. I dunno why wget would download 1 Mbyte data in 400 Mbps while fsockopen does it in 170 Mbps. I am using fsockopen since it is supported on all servers.

Does any one know why? 400 Mbps vs. 170 Mbps is quite a big difference.

Is there a better option for performance?

<?php
      $url = 'http://ftp.sunet.se/pub/Linux/distributions/ubuntu/ubuntu/dists/hardy-backports/Contents-i386.gz';
      $size = 1024*1024; // Get amount of bytes

      $parts = parse_url($url);
      $fp = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 30);

      if (!$fp) throw new Exception("Problem with $url, $errstr");

      $out = "GET " . $parts['path'] ." HTTP/1.1\r\n"
           . "Host: ". $parts['host'] ."\r\n"
           . "Connection: Close\r\n\r\n";

      fwrite($fp, $out);

      $found_body = false;
      $response = '';
      $start = microtime(true);
      $timeout = 30;

      while (!feof($fp)) {
        if ((microtime(true) - $start) > $timeout) break;
        if (strlen($response) > $size) break;
        //$row = fgets($fp, 128); // Grab block of 128
        $row = fgets($fp);
        if ($found_body) {
          $response .= $row;
        } else if ($row == "\r\n") {
          $found_body = true;
          $tsStart = microtime(true);
          continue;
        }
      }

      $time_elapsed = microtime(true) - $tsStart;

      $speed = strlen($response) / $time_elapsed * 8 / 1000000;

      echo round($speed, 2) . ' Mbps ('. strlen($response) .' bytes in '. round($time_elapsed, 3) .' s)<br />';

?>
tim
  • 2,530
  • 3
  • 26
  • 45

2 Answers2

4

It's not fsockopen that's slow - it's PHP in general. Try increasing the buffer size in your fgets() calls and use a regular expression to find the end of the headers. With your current code, you're executing your read loop too many times and network IO is no longer your bottleneck.

Cal
  • 7,067
  • 25
  • 28
  • A great answer however it didn't improve anything. Fact is the most optimal packet size is 64-128. Higher or lower than that changes performance drasticly to the worse. I ran the tests ~10 times and they all turned out the same way. – tim Jan 23 '12 at 20:33
  • since you're not actually using the repsonse, try throwing away the data after you read it to avoid having to constantly re-alloc memory by doing the string concats. that might also be burning time here – Cal Jan 23 '12 at 22:11
  • Instead of storing the response in a buffer I do $response_amount += strlen(row);. I spontanously feel it might have gained 5-10% performance increase. However time to time the performance is slower. That can depend on the individual call itself. Could be a step forward. Good thinking. – tim Jan 23 '12 at 22:55
-2

It would be much easier (and probably faster) to use file_get_contents() for this.

FtDRbwLXw6
  • 27,774
  • 13
  • 70
  • 107
  • Thats not supported by allow_url_fopen = false – tim Jan 23 '12 at 16:23
  • @user1135440: If `allow_url_fopen` was set to `false`, then the OP wouldn't be able to use `fopen()` in this way either. And since he's complaining about the performance, and not a PHP Fatal Error, it's obvious that his `allow_url_fopen` is not set to `false`. – FtDRbwLXw6 Jan 23 '12 at 16:27
  • allow_url_fopen does not apply to fsockopen. – tim May 30 '12 at 09:20