AS3 Bandwidth Test

Update (05/18/2011): You can fork the source code from github here

A few months back I was talking to a friend who is new to Flash and who was wondering what was the best way to determine a client’s connection speed.  I told him that he could use a bandwidth test to determine the client’s speed and based on the results he could decide what files to serve, we searched(lightly) google and noticed that there was no available AS3 code to determine a user’s bandwidth speed.  Sure we saw that if we used FMS we could use the native bandwidth detection to do our dirty work, but unfortunately not everyone has the resources to host some content on a FMS.

Therefore I decided to write him a little class to perform a basic bandwidth test.  It is not complicated at all, which is probably why nobody bothered posting the code online, to write code to test for speed but I have to admit that is not extremely accurate.  The accuracy of the test depends on the size of the file being downloaded for the test, the larger the file the more accurate the test is but the longer it takes to complete.  This is where one has to decide between accuracy and waiting time,  I find that a file of about 32KB gives a reasonably accurate idea of the speed a client has.  Why? well most, if not all, broadband users will be able to download this in less than a second and the results will most likely be above 100KBps, which should be fast enough for most instances that you want to test for.  Worst case scenario you could write some sort of loop that will keep testing the speed against increasingly larger files until you are satisfied with the results.

So how does it work?

Create an instance of the BandwidthTest class, whose constructor takes one parameter, the URL for the image or swf to test against.  Once you have your instance, you need to attach an EventListener to check when the test is complete and the last step is to call the start() function to start the test.

import com.yeungus.utils.BandwidthTest;

StartButton.addEventListener( MouseEvent.CLICK, startTest );
var test:BandwidthTest = new BandwidthTest( "http://yeungus.com/images/sample_image.jpg" );

function startTest( e:MouseEvent ):void
{
	test.addEventListener( Event.COMPLETE, downloadComplete );
	test.start( );
}

function downloadComplete( e:Event ):void
{
	_results.text = "results: " + Math.round( test.speed ) + "KBps";
}

The Actual Class

Basically we measure the time it takes to download something and we divide the file size by said time.  The formula looks like:

KBps = filesize(in KB) / ( endtime - starttime )(in s)

The rest of the class just takes care of basic things like converting time into seconds and bytes into kilobytes.  The other thing that I would like to point out is that you can use the same image to do your tests.  The class attaches a random number at the end of the target URL in order to avoid caching the image.

package com.yeungus.utils
{
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;

	public class BandwidthTest extends EventDispatcher
	{
		public var URL:String;
		public var debug:Boolean = false;
		private var _speed:Number;
		private var _startTime:Number;
		private var _loader:Loader;

		public function BandwidthTest( testFileLocation:String ):void
		{
			URL = testFileLocation;
		}

		public function get speed( ):Number{ return _speed; }

		public function start( ):void
		{
			URL += "?" + ( Math.random( ) * 100000 );
			_startTime = ( new Date( ) ).getTime( );

			_loader = new Loader( );
			_loader.contentLoaderInfo.addEventListener( Event.COMPLETE, downloadComplete );
			_loader.contentLoaderInfo.addEventListener( IOErrorEvent.IO_ERROR, ioErrorHandler );
			_loader.load( new URLRequest( URL ) );
		}

		private function downloadComplete( e:Event ):void
		{
			var endTime:Number = ( new Date( ) ).getTime( );
			var totalTime:Number = ( endTime - _startTime ) / 1000;
			var totalKB:Number = e.currentTarget.bytesTotal / 1024;
			_speed = totalKB / totalTime;

			if( debug )
				trace( "total time: " + totalTime + " total KB: " + totalKB + " speed: " + speed + "KBps" );

			dispatchEvent( e );
		}

		private function ioErrorHandler( e:IOErrorEvent ):void
		{
			_speed = -1;
			trace( "URL not found" );
		}
	}
}

Demo

15 thoughts on “AS3 Bandwidth Test”

  1. Very nice.

    Just to help me understand how you wrote this… what would you change if you used a different image? Does anything need to change?

    How do you run the Debug mode… I am still trying to learn packages and the proper usage/creation.

    Thanks,
    Jo

  2. Hey Jo,

    you could use any image, you just need to pass the path to the image when you construct the object (line 4 replace http://yeungus.com/images/sample_image.jpg with the image you want to use ).

    To run debug mode, after you construct the object you can do, in this example, test.debug = true;

    The debug mode just traces some info, that’s it. I made the debug mode so that I know some info on what the file size downloaded was and how long it took.

    I hope that helps.

    -Joe

  3. Hi,

    Thank you for this very usefull class, I think it’s a very good start and probably very little left to optimize, maybe the file need to change to some sort of streaming media, I say this because I agree with your code, but from another test, in particurs from VH1 dot com., it has a flash video player, it has a button, (the green signal bars), it tells you how much bandwith available and it is showing about 3 times more the when I use your test.

    1. using filereference class with user interaction or send data to php file and measure how long it take. until script say done;) sory for my english .

  4. Do you believe it would be possible to use this method to construct a code for detecting the bandwidth speed of an individual attempting to load a website, and based on that bandwidth speed, deliver a customized version of the site appropriate for the user's individual bandwidth speed? Say they have a very low bandwidth speed, it would direct the browser to load a pre-composed simpler and smaller version of the site (aka, load different css, html, etc. files), and under the scenario that the user has a fast bandwidth speed, they would automatically load the full version of the site.

    Please email me if you think that it is possible and have an idea of how it could work because I am stumped on this concept. Thank you.

Leave a Reply

Your email address will not be published. Required fields are marked *