Last active
November 3, 2020 16:42
-
-
Save julian-klode/e2c33050ffb32cfdcf04f08f4227d5ef to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/gnuplot | |
# | |
# speed - simple speed measuring tool using Debian repository download - plotting | |
# | |
# SPDX-FileCopyrightText: 2020 Julian Andres Klode <[email protected]> | |
# | |
# SPDX-License-Identifier: AGPL-3.0-or-later | |
set datafile separator "," | |
set terminal png size 2560 ,1440 | |
set title "Bandbreitenmessung / Bandwidth measurement - Deutsche Glasfaser" | |
set ylabel "Mbit/s" | |
set xlabel "Uhrzeit / Local time" | |
#set y2label "ms" | |
set timefmt "%s" | |
set xdata time | |
set format x "%d.%m %H:%M" | |
set key left top | |
#set xtics 300 | |
#set y2tics 1 | |
set ytics mirror | |
set grid | |
#set xrange ["2020-10-31T22:35:00Z":] | |
set yrange [0:450] | |
set datafile missing "NaN" | |
plot \ | |
"/home/jak/.tmp/speed.csv" using ($1+3600):(stringcolumn(2) eq "fastly"?$3:1/0) with linespoint ps 2 lw 2 title "Fastly (Mbit/s, via DE-CIX)", \ | |
"/home/jak/.tmp/speed.csv" using ($1+3600):(stringcolumn(2) eq "aws"?$3:1/0) with linespoint ps 2 lw 2 title "AWS (Mbit/s, via Interxion Düsseldorf -> Telia)" | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# | |
# speed - simple speed measuring tool using Debian repository download | |
# | |
# SPDX-FileCopyrightText: 2020 Julian Andres Klode <[email protected]> | |
# | |
# SPDX-License-Identifier: AGPL-3.0-or-later | |
""" | |
Speedtest using CDNs on deb.debian.org | |
speed measures network performance by downloading a ~200 MB file from | |
a Debian repository, using the AWS and Fastly CDNs, to figure out which | |
CDN is faster and if there are any impacts to archive performance on the | |
current connection. | |
It performs two downloads of the file per CDN, and in case those differ | |
in speed by more than 10%, it will retry until it can confirm one of those | |
speeds within a 10% error. | |
""" | |
import urllib.request | |
import time | |
import apt_pkg | |
import subprocess | |
import sys | |
def get_ping(cdn): | |
"""Return average over 5 RTT measurements""" | |
with subprocess.Popen( | |
["ping", "-q", "-c", "5", f"cdn-{cdn}.deb.debian.org"], | |
stdout=subprocess.PIPE, | |
encoding="utf-8", | |
) as proc: | |
for line in proc.stdout: | |
if line.startswith("rtt"): | |
return float(line.split("=")[1].split("/")[1]) | |
def get_speed(cdn): | |
"""Return the speed of the CDN, in Mbit/s""" | |
start = time.time() | |
fetched = 0 | |
with urllib.request.urlopen( | |
f"http://cdn-{cdn}.deb.debian.org/debian/" | |
f"pool/main/m/mysql-8.0/mysql-testsuite-8.0_8.0.21-1_amd64.deb" | |
) as fobj: | |
while True: | |
block = fobj.read(10 * 1024 * 1024) | |
if not block: | |
break | |
fetched += len(block) | |
elapsed = time.time() - start | |
if "-q" not in sys.argv: | |
print(80 * " ", end="\r", file=sys.stderr) | |
speed_human = apt_pkg.size_to_str(fetched / elapsed * 8) | |
print( | |
f"{cdn}: {speed_human}bit/s", end="\r", file=sys.stderr, | |
) | |
if "-q" not in sys.argv: | |
print(file=sys.stderr) | |
return start, fetched / elapsed / (1000 * 1000) * 8 | |
def do_cdn(cdn): | |
"""Measure a single CDN.""" | |
ts0, speed0 = get_speed(cdn) | |
ts1, speed1 = get_speed(cdn) | |
# If we are going to enter the loop, only print the first | |
# measurement. Otherwise, print average speed. | |
if speed1 > 1.1 * speed0 or speed1 < 0.9 * speed0: | |
print(ts0, cdn, speed0, sep=",") | |
else: | |
print(ts0, cdn, (speed0 + speed1) / 2, sep=",") | |
return | |
past_speeds = [speed0] | |
while ( | |
all(speed1 > 1.1 * s or speed1 < 0.9 * s for s in past_speeds) | |
and len(past_speeds) < 5 | |
): | |
past_speeds.append(speed1) | |
print(ts1, cdn, speed1, sep=",") | |
time.sleep(5) | |
ts1, speed1 = get_speed(cdn) | |
if len(past_speeds) > 1: | |
print(ts1, cdn, speed1, sep=",") | |
def main(): | |
"""Main entry point.""" | |
for cdn in ["aws", "fastly"]: | |
do_cdn(cdn) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment