From 8c0e38349a2895e8b7677b8e85690d30708b784d Mon Sep 17 00:00:00 2001 From: Fornax Date: Tue, 20 Feb 2024 13:32:38 +0100 Subject: [PATCH] Add logic to end the speed test if the result is stable --- svelte/src/speedtest/Index.svelte | 16 ++++-- svelte/src/speedtest/Speedtest.svelte | 74 ++++++++++++++++++++------- 2 files changed, 68 insertions(+), 22 deletions(-) diff --git a/svelte/src/speedtest/Index.svelte b/svelte/src/speedtest/Index.svelte index c52a786..5531e14 100644 --- a/svelte/src/speedtest/Index.svelte +++ b/svelte/src/speedtest/Index.svelte @@ -18,6 +18,17 @@ import Speedtest from "./Speedtest.svelte"; servers to your computer. This speed is not affected by the daily download limit for free users.

+

+ The speed measured is the maximum speed reached for two continuous + seconds during the test. The normal test has a time limit of 30 + seconds and the long test 60 seconds. When the maximum speed has not + changed for a third of the test duration (10 or 20 seconds) the test + will end and the result will be final. +

+

+ The speed gauge uses a logarithmic scale, which means that each + datapoint is 10 times more than the last one. +

What do the numbers mean?

@@ -46,10 +57,7 @@ import Speedtest from "./Speedtest.svelte";

The last number shows how much data the speedtest was able to - transfer in the duration of the test. The standard test is six - seconds and the long test is twelve seconds. The long test might be - slightly more accurate than the short one, but it uses more - bandwidth. + transfer in the duration of the test.

Why is the speed different from other speed tests?

diff --git a/svelte/src/speedtest/Speedtest.svelte b/svelte/src/speedtest/Speedtest.svelte index 610e373..03c7853 100644 --- a/svelte/src/speedtest/Speedtest.svelte +++ b/svelte/src/speedtest/Speedtest.svelte @@ -33,7 +33,7 @@ const start = async (dur = 6000) => { const reader = req.body.getReader(); - measure_speed(reader, update_interval, test_duration) + measure_speed(() => reader.cancel(), test_duration) while(true) { const {done, value} = await reader.read() @@ -49,17 +49,30 @@ const start = async (dur = 6000) => { // Average speed for the whole test let speed = 0 let result_link = "" -let current_duration = 0 -const measure_speed = (reader, update_interval, test_duration) => { +let progress_duration = 0 +let progress_unchanged = 0 + +const measure_speed = (stop, test_duration) => { speed = 0 result_link = "" - // This slice contains the speed measurements for 1/3 the duration of the - // test. This value is averaged and if the average is higher than the - // previously calculated average then it is saved - const hist = new Uint32Array((test_duration/3)/update_interval) + // Updates per second + const ups = (1000/update_interval) + + // This slice contains the speed measurements for four seconds of the test. + // This value is averaged and if the average is higher than the previously + // calculated average then it is saved. The resulting speed is the highest + // speed that was sustained for four seconds at any point in the test + const hist = new Uint32Array(ups*2) let idx = 0 + + // This var measures for how many ticks the max speed has not changed. When + // the speed has not changed for a third of the test duration the test is + // considered over + let unchanged = 0 + const unchanged_limit = (test_duration/3)/update_interval + let previous_transferred = 0 const start = Date.now() @@ -72,26 +85,44 @@ const measure_speed = (reader, update_interval, test_duration) => { idx++ // Calculate the average of all the speed measurements - const sum = hist.reduce((acc, val) => acc + val, 0) - const new_speed = (sum/hist.length)*(1000/update_interval) + const sum = hist.reduce((acc, val) => { + if (val !== 0) { + acc.sum += val + acc.count++ + } + return acc + }, {sum: 0, count: 0}) + const new_speed = (sum.sum/sum.count)*ups if (new_speed > speed) { speed = new_speed + unchanged = 0 + } else { + unchanged++ } - // Only used for the progress bar - current_duration = Date.now() - start + // Update the duration of the test. Used for calculating progress and + // clock drift + const current_duration = Date.now() - start - if (idx < test_duration/update_interval) { + // Update the progress bar + progress_unchanged = unchanged/unchanged_limit + progress_duration = current_duration/test_duration + + if (idx < test_duration/update_interval && unchanged < unchanged_limit) { // We have to manually calculate and subtract drift, because in my // tests with setInterval the clock would drift like 200ms in a // single test which significantly impacts results setTimeout(measure, update_interval - (current_duration-(idx*update_interval))) } else { // Test is done, break the reader out of the counting loop - await reader.cancel() + await stop() - console.debug("Done! Test ran for", current_duration) - current_duration = 0 + console.debug( + "Done! Test ran for", current_duration, + "result did not change for", unchanged*update_interval, + ) + progress_unchanged = 0 + progress_duration = 0 // Update the URL so the results can be shared history.replaceState( @@ -132,8 +163,8 @@ onMount(() => {
-
- + +
{formatDataVolume(speed, 4)}/s