Reputation:
I'm trying to get the current download speed of a WebClient downloading a file, however when I use a formula that I'm pretty sure should work out:
Stopwatch.Stop();
double msElapsed = Stopwatch.Elapsed.TotalMilliseconds;
int bytesDownloaded = (int)e.BytesReceived - lastBytesDownloaded;
double downloadSpeed = (double)bytesDownloaded / (msElapsed / 1000);
lastBytesDownloaded = (int)e.BytesReceived;
Stopwatch.Restart();
Where Stopwatch is a stopwatch that I've started just as I started the file download, lastBytesDownloaded is a class variable, and this is all inside the downloadProgressChanged event, however the download speed varies wildly off course from what it actually is.
For example if I was downloading a file at 500kb/s, it would rapidly jump from (for example) 10kb/s to 50mb/s completely randomly.
I can get an accurate average download time by making a couple edits to that:
double sElapsed = Stopwatch.Elapsed.TotalSeconds;
int bytesDownloaded = (int)e.BytesReceived;
double downloadSpeed = bytesDownloaded / sElapsed;
But that isn't what I want. How can I get a more stable reading for current download speed?
Upvotes: 2
Views: 2207
Reputation: 437326
You just need to smooth the data over a longer period of time. For example, don't report current download speed only on the basis of the last measurement; use a (perhaps weighted) moving average instead.
Dead simple example:
var measurements = 0, maxDataPoints = 5;
var dataPoints = new double[maxDataPoints];
And then:
Stopwatch.Stop();
double msElapsed = Stopwatch.Elapsed.TotalMilliseconds;
int bytesDownloaded = (int)e.BytesReceived - lastBytesDownloaded;
lastBytesDownloaded = (int)e.BytesReceived;
double dataPoint = (double)bytesDownloaded / (msElapsed / 1000);
dataPoints[measurements++ % maxDataPoints] = dataPoint;
double downloadSpeed = dataPoints.Average();
Stopwatch.Restart();
Upvotes: 2