Calculating Connection/Download Speed
Asked Answered
U

4

11

I have a client and server program (both in Obj-C) and I am transferring files between two devices using the programs.

The transferring is working fine, but I would like to display to the user what transfer rate they are getting.

So I know the total size of the file, and how much of the file has been transferred, is there a way to figure out the transfer rate from this information, and if not, what information do I need to calculate the transfer rate?

Thanks

Ugric answered 16/12, 2008 at 7:20 Comment(1)
For those coming across this question, this one may also be helpful: https://mcmap.net/q/279195/-how-to-estimate-download-time-remaining-accurately/115730Jovian
T
20

As soon as you start the download, capture the current system time and store it as the "start time". Then, all you need to do to calculate transfer speed at any point during the transfer is to look at the system time again and use it as the "current time" to calculate the total time spent so far:

transfer_speed = bytes_transferred / ( current_time - start_time)

You probably want to use second or millisecond accuracy with the times, and of course can multiply the result by 8 if you want bits/second.

Since you're using Cocoa, you could use the NSDate class to get the timestamps. For example, use the following when you start the transfer:

NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];

Then periodically check the transfer rate by using:

double speed = bytesTransferred / ([NSDate timeIntervalSinceReferenceDate] - start);
Toque answered 16/12, 2008 at 7:27 Comment(3)
Poitner * should not be used with NSTimerInterval. Please correctAbhorrence
Hi Marc. May I know how can we convert that speed into Kbps or mbps.Outstare
Hey - how can i get this value in Mbps ?Willyt
D
40

The naïve way is bytes_downloaded / (now - start_time), but that becomes inaccurate if the connection speed fluctuates wildly, or if the user starts another download (perhaps in another app) halfway through your download. Both of these may happen if the user runs a torrent in the background.

A better way (though harder to implement) is to keep an array of periodic samples and present the average.

Start out with an array containing 0. The array is of samples, and each sample is the number of bytes downloaded since the previous sample. Then start the download.

Every half-second (you can try different intervals), measure how many bytes you've downloaded, then subtract the previous total from this new total. Add the difference as the new last element in the array. If this grows the array beyond a certain size, lop off the first element (oldest sample). Then, present the average of all the samples.

You should keep somewhere between 2–5 seconds' worth of samples, and the interval should be somewhere between 0.5 and 1 seconds (it's a trade-off between currency and performance).

You may also want to remove the first element from the array after retrieving it if it is zero. This makes your starting reportage more accurate and helps you recover more quickly from stalls, since you're not including old zeroes in the average.

Durango answered 16/12, 2008 at 21:12 Comment(3)
Great answer, I've always wondered what the best way to do this would be.Brecher
Hey - how can i get this value in Mbps ?Willyt
How about using the formula suggested in the RFCs? SRTT <- (1 - alpha) * SRTT + alpha * R' where SRTT is smoothed RTT, R` is the latest RTT, and recommended alpha is 1/8. If you're worried about deviation, there's also a formula for that. (Although I'm not sure if it's worth it..)Matamoros
T
20

As soon as you start the download, capture the current system time and store it as the "start time". Then, all you need to do to calculate transfer speed at any point during the transfer is to look at the system time again and use it as the "current time" to calculate the total time spent so far:

transfer_speed = bytes_transferred / ( current_time - start_time)

You probably want to use second or millisecond accuracy with the times, and of course can multiply the result by 8 if you want bits/second.

Since you're using Cocoa, you could use the NSDate class to get the timestamps. For example, use the following when you start the transfer:

NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];

Then periodically check the transfer rate by using:

double speed = bytesTransferred / ([NSDate timeIntervalSinceReferenceDate] - start);
Toque answered 16/12, 2008 at 7:27 Comment(3)
Poitner * should not be used with NSTimerInterval. Please correctAbhorrence
Hi Marc. May I know how can we convert that speed into Kbps or mbps.Outstare
Hey - how can i get this value in Mbps ?Willyt
U
1

You will need to know

  1. Bytes sent from the beginning (To calculate average rate of transfer)

  2. Bytes sent since last second (To calculate current transfer speed.)

    This can be easily done if you know bytes sent from the beginning. (New bytes sent from the beginning - Bytes sent from the beginning 1 second ago)

  3. Total file size (To calculate percentage of progress.)

    (Bytes transfered / Total number of bytes)

Ultra answered 16/12, 2008 at 7:34 Comment(0)
S
0

Keep track of the time that the transfer is taking. The transfer rate is simply bytes transferred/seconds elapsed, in other words bytes per second. You don't need the total size for this. (You can also show % completed, which is bytes transferred/total bytes*100)

Spherical answered 16/12, 2008 at 7:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.