Skip to content

Instantly share code, notes, and snippets.

@julian-klode
Last active November 3, 2020 16:42
Show Gist options
  • Save julian-klode/e2c33050ffb32cfdcf04f08f4227d5ef to your computer and use it in GitHub Desktop.
Save julian-klode/e2c33050ffb32cfdcf04f08f4227d5ef to your computer and use it in GitHub Desktop.
#!/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)"
#!/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