Reputation: 253
I have a python script which I run as a background process on my mac every 10 minutes. Basically, it downloads the latest image from a server and depending on my internet speed, it downloads a hi-res (20mb on 5Mb/s connections or better) or low-res (6mb on 5 to 1 Mb/s connections) version of the image.
Thus in the beginning of my script, I am using the python package speedtest-cli
to test my internet speed. However, inherent in any speed test is the use of some of my bandwidth.
If possible, what I would like to do before the speed test is some simple and very low bandwidth test just to see if my internet connection is at some baseline level before I do my speed test. That baseline level can be measured in download speed, ping time, or any useful metric that can inform me of the basic quality of my connection. Thus if my internet is too slow, I quit before using up any of the limited bandwidth with the speed test.
Accuracy is not that important here. I'm not concerned with the difference between slow and really slow internet. After the speed test has been run, if the download speed is not at least 1 Mb/s, it exits. Thus this baseline test can be any simple test where baseline is somewhere below 1 Mb/s download speed.
Using ping could be a reasonable solution. Another question provides a solution for pinging which is provided in this gist but that is rather elaborate, and requires root to run, which I would rather avoid if possible.
Below is a simple version of the script I am using:
import requests
import sys
import os
import logging
import socket
import json
# python himawari.py
# stolen from https://gist.github.com/celoyd/39c53f824daef7d363db
# requires speedtest-cli ('pip install speedtest-cli')
# check if we have internet
def internet(host="8.8.8.8", port=53, timeout=3):
try:
socket.setdefaulttimeout(timeout)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
return True
except Exception as ex:
return False
print("Checking internet speed:")
if internet():
print "Internet connection exists..."
os.system("rm -f /Users/scott/git-projects/live-earth-desktop/speedtest.json")
os.system("speedtest-cli --json >> /Users/scott/git-projects/live-earth-desktop/speedtest.json")
else:
print "No internet connection. Quitting..."
os._exit(1)
with open('/Users/scott/git-projects/live-earth-desktop/speedtest.json') as data_file:
try:
data = json.load(data_file)
except ValueError:
print("data was not valid JSON")
os._exit(1)
speed = data["download"]
print_speed = str(round(speed//1000000))
print("Download speed: ~" + print_speed + " Mb/s")
if (speed > 5000000): # 5 Mb/s
print("Internet speed is good. Downloading hi-res image.")
# Download hi-res image here
elif (speed > 1000000): # 1 Mb/s
print("Internet speed is ok. Downloading low-res image.")
# Download low-res image here
else:
print("Internet speed is poor. Quitting.")
os._exit(1)
Upvotes: 2
Views: 2509
Reputation: 39
I'm a co-founder of Firebind.
Firebind's entire reason for existence is to perform continuous, low-impact tests so you can baseline your Internet quality. You can configure and deploy one of our agents in 2 to 3 minutes. The agent then performs a series of 11 tests every 5 minutes to a combination of our fixed test points as well as to destinations you configure, giving you 3,168 measurements/day.
When we built Firebind we realized that high-impact tests like bandwidth tests were too destructive, which led us to develop our flagship simulated VoIP test. Every 5 minutes we send and receive simulated VoIP traffic for 25 seconds. That traffic is 50 pps, 87 Kbps with 218 byte payloads, resulting in 360,000 packets/day in each direction. Our visibility is far superior to ping not only because we're 50x the packets per second, but we're using UDP just like a real VoIP call would. If ping is a magnifying glass, we're a microscope. Other tests include UDP latency, UDP jitter, ping response time, DNS response time, and HTTP response time.
You can set alarm thresholds that will send out an email alert if, for example, your packet loss exceeds 1.5%, or your DNS lookup takes longer than 50ms.
The number one value here is that by baselining your connection, you can see periods of network quality degradation and then based on that timing and severity you can more easily isolate the source (which unfortunately is most often an oversubscribed ISP connection.)
Firebind has a free 2-week trial if you'd like to check it out.
(The pic below is our packet loss chart showing severe upload loss on a Comcast connection in Massachusetts.)
Upvotes: 0
Reputation: 39
Your mentioning "low impact" testing and looking to do a baseline is what caught my attention. What I've learned through Firebind is that TCP bandwidth tests aren't the only way to measure line quality, and performing them can lead to misleading results. Any upload or download operation that isn't somehow being rate-limited either by the application or the network will always try to "max-out" the circuit. Choosing a smaller file can still max out the circuit, but just for a shorter period of time. And of course, fear of using too much bandwidth or spiking the circuit is what leads to trying to limit the frequency, which in turn limits your visibility.
My recommendation would be for you to use iperf instead and simulate something like we do such as a 50 pps VoIP call so you can measure packet loss. You can use the inputs I mentioned above (87 kbps, 218 byte payloads over UDP.) That way you can baseline the line quality but you can do it in a low impact way vs. having to "flood the line" in a TCP bandwidth test. And because the bandwidth is so low, you can afford to do it as often as you'd like. Even on a 5/5 circuit the parameters above would be using less than 1% capacity.
For example, you could run it for 30 seconds in each direction every 2 minutes, giving you a lot more visibility with a lot less data than the TCP approach.
I'd definitely stay away from ping in trying to assess line quality. The picture in the link below shows a Comcast home in Massachusetts doing both 20 ICMP pings to AWS Virginia (yellow line) as well as us simulating ping but using a UDP payload (blue line.) The times are all averages of those 20 pings. On a non-congested circuit, you'd normally see the yellow line very flat (with a 1 ms tolerance) and it would have a value a few ms below the blue line. The reason is that our software in Virginia has to process the UDP whereas ping replies don't have those extra steps. Here however the average pings are bouncing between 28ms and 55ms, whereas the UDP is relatively flat, mostly between 26ms and 30ms. This is a sign of a link with some congestion and if you only had ping data you might think it was worse than it is because the ping is swinging so wildly. It's true there is congestion, but the UDP (user) traffic is still doing relatively ok.
Upvotes: 1