Add logic to end the speed test if the result is stable
This commit is contained in:
@@ -18,6 +18,17 @@ import Speedtest from "./Speedtest.svelte";
|
|||||||
servers to your computer. This speed is not affected by the daily
|
servers to your computer. This speed is not affected by the daily
|
||||||
download limit for free users.
|
download limit for free users.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The speed gauge uses a logarithmic scale, which means that each
|
||||||
|
datapoint is 10 times more than the last one.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2>What do the numbers mean?</h2>
|
<h2>What do the numbers mean?</h2>
|
||||||
<p>
|
<p>
|
||||||
@@ -46,10 +57,7 @@ import Speedtest from "./Speedtest.svelte";
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The last number shows how much data the speedtest was able to
|
The last number shows how much data the speedtest was able to
|
||||||
transfer in the duration of the test. The standard test is six
|
transfer in the duration of the test.
|
||||||
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.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Why is the speed different from other speed tests?</h2>
|
<h2>Why is the speed different from other speed tests?</h2>
|
||||||
|
@@ -33,7 +33,7 @@ const start = async (dur = 6000) => {
|
|||||||
|
|
||||||
const reader = req.body.getReader();
|
const reader = req.body.getReader();
|
||||||
|
|
||||||
measure_speed(reader, update_interval, test_duration)
|
measure_speed(() => reader.cancel(), test_duration)
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
const {done, value} = await reader.read()
|
const {done, value} = await reader.read()
|
||||||
@@ -49,17 +49,30 @@ const start = async (dur = 6000) => {
|
|||||||
// Average speed for the whole test
|
// Average speed for the whole test
|
||||||
let speed = 0
|
let speed = 0
|
||||||
let result_link = ""
|
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
|
speed = 0
|
||||||
result_link = ""
|
result_link = ""
|
||||||
|
|
||||||
// This slice contains the speed measurements for 1/3 the duration of the
|
// Updates per second
|
||||||
// test. This value is averaged and if the average is higher than the
|
const ups = (1000/update_interval)
|
||||||
// previously calculated average then it is saved
|
|
||||||
const hist = new Uint32Array((test_duration/3)/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
|
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
|
let previous_transferred = 0
|
||||||
const start = Date.now()
|
const start = Date.now()
|
||||||
|
|
||||||
@@ -72,26 +85,44 @@ const measure_speed = (reader, update_interval, test_duration) => {
|
|||||||
idx++
|
idx++
|
||||||
|
|
||||||
// Calculate the average of all the speed measurements
|
// Calculate the average of all the speed measurements
|
||||||
const sum = hist.reduce((acc, val) => acc + val, 0)
|
const sum = hist.reduce((acc, val) => {
|
||||||
const new_speed = (sum/hist.length)*(1000/update_interval)
|
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) {
|
if (new_speed > speed) {
|
||||||
speed = new_speed
|
speed = new_speed
|
||||||
|
unchanged = 0
|
||||||
|
} else {
|
||||||
|
unchanged++
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only used for the progress bar
|
// Update the duration of the test. Used for calculating progress and
|
||||||
current_duration = Date.now() - start
|
// 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
|
// We have to manually calculate and subtract drift, because in my
|
||||||
// tests with setInterval the clock would drift like 200ms in a
|
// tests with setInterval the clock would drift like 200ms in a
|
||||||
// single test which significantly impacts results
|
// single test which significantly impacts results
|
||||||
setTimeout(measure, update_interval - (current_duration-(idx*update_interval)))
|
setTimeout(measure, update_interval - (current_duration-(idx*update_interval)))
|
||||||
} else {
|
} else {
|
||||||
// Test is done, break the reader out of the counting loop
|
// Test is done, break the reader out of the counting loop
|
||||||
await reader.cancel()
|
await stop()
|
||||||
|
|
||||||
console.debug("Done! Test ran for", current_duration)
|
console.debug(
|
||||||
current_duration = 0
|
"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
|
// Update the URL so the results can be shared
|
||||||
history.replaceState(
|
history.replaceState(
|
||||||
@@ -132,8 +163,8 @@ onMount(() => {
|
|||||||
|
|
||||||
<section class="highlight_border">
|
<section class="highlight_border">
|
||||||
<div style="text-align: center">
|
<div style="text-align: center">
|
||||||
<Button icon="speed" label="Start test" click={() => start(6000)} disabled={running} highlight={!running}/>
|
<Button icon="speed" label="Start test" click={() => start(30000)} disabled={running} highlight={!running}/>
|
||||||
<Button icon="speed" label="Long test" click={() => start(12000)} disabled={running}/>
|
<Button icon="speed" label="Long test" click={() => start(60000)} disabled={running}/>
|
||||||
<Button
|
<Button
|
||||||
highlight_on_click
|
highlight_on_click
|
||||||
disabled={result_link === ""}
|
disabled={result_link === ""}
|
||||||
@@ -143,7 +174,14 @@ onMount(() => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ProgressBar animation="linear" speed={update_interval} total={test_duration} used={current_duration}/>
|
<!-- This progress bar shows either the progress for the test duration, or
|
||||||
|
when the test will time out. Whichever is higher -->
|
||||||
|
<ProgressBar
|
||||||
|
animation="linear"
|
||||||
|
speed={update_interval}
|
||||||
|
used={Math.max(progress_unchanged, progress_duration)}
|
||||||
|
total={1}
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="speed_stats">
|
<div class="speed_stats">
|
||||||
<div class="highlight_shaded">{formatDataVolume(speed, 4)}/s</div>
|
<div class="highlight_shaded">{formatDataVolume(speed, 4)}/s</div>
|
||||||
|
Reference in New Issue
Block a user