2

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)
Scott Wilton
  • 253
  • 4
  • 11
  • @TessellatingHeckler I guess I don't understand your question. There are all sorts of reasons that my internet can be slow. It's a laptop, so maybe I'm connected to a super slow connection at my grandmother's place for the afternoon, or I'm tethering off of my phone. The point is, if my internet is bad, I just want the script to exit quickly before using up much bandwidth. – Scott Wilton Feb 09 '17 at 07:30
  • Speedtest downloads big file and thus measures download speed. If you wish to minimize impack try to minimize size of file. May be using speedtest options, or as a last resort - download it manually in your script. – Eugene Lisitsky Feb 09 '17 at 07:59
  • @EugeneLisitsky the `speedtest-cli` package doesn't have any file size options. If you can point me towards another package that could help, that would certainly be appreciated. – Scott Wilton Feb 09 '17 at 08:10
  • @TessellatingHeckler Saying I have "given literally nothing to work from" is not a fair comment. I agree that my code is unrelated to my "problem", but it is relevant in that it provides context for what I'm doing. This script is a background script that does something fun. I don't want that fun to get in the way of actual work when my connection is poor. I've updated my question with more information that I hope can help. – Scott Wilton Feb 09 '17 at 19:04
  • Possible duplicate of [How to check network bandwidth with Python?](http://stackoverflow.com/questions/5050405/how-to-check-network-bandwidth-with-python) – Akshat Mahajan Feb 09 '17 at 19:16
  • The ping time might be related to the available bandwidth, especially if low bandwidth is caused by a congested network – BlackBear Feb 09 '17 at 19:23
  • Speed isn't a configuration setting somewhere; it is what you measure it to be. – chepner Feb 09 '17 at 19:30
  • @chepner I'm not sure how that is relevant. – Scott Wilton Feb 09 '17 at 19:36
  • @AkshatMahajan That question looks like useful information, but doesn't seem like a very simple solution. It would also be useful to have a suggestion of what length of ping times are "too slow" as to suggest a connection speed under 1 Mb/s. I do realize that latency and speed are not the same thing. – Scott Wilton Feb 09 '17 at 19:44
  • Ping won't help, you could be on a low latency link with QoS throttled downloads. I can't see that you can test maximum bandwidth with a 'low bandwidth' test anymore than you can test sports car top speed with a low speed test - especially with [TCP slow start](https://www.maxcdn.com/one/visual-glossary/tcp-slow-start/) meaning you need to wait for the connection to ramp up. I still vote for 'download the small image, check filesize after 1 second, if it's >1Mb, cancel and download the large one, otherwise let it run'. – TessellatingHeckler Feb 09 '17 at 20:06

2 Answers2

1

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.

Average ping and UDP RTT from MA to VA

vvvvv
  • 25,404
  • 19
  • 49
  • 81
Dave
  • 39
  • 1
0

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.)

Comcast, MA Upload Packet Loss

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Dave
  • 39
  • 1
  • 2
    A $60/month product is a rather high price to pay for a solution to a very rough python internet test. But more importantly, is there anyway I can use results from a `Firebind` test in a python script so that I can choose which of my images to download? If not, then this answer is spam instead of just unhelpful. – Scott Wilton Feb 24 '17 at 05:22