Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26117efcf0 | ||
|
|
30b903d7da |
35
README.md
35
README.md
@@ -10,20 +10,26 @@ and runs great on static hosting.
|
|||||||
You simply upload the `index.html` file and generate
|
You simply upload the `index.html` file and generate
|
||||||
the binary testing files.
|
the binary testing files.
|
||||||
|
|
||||||
> [!TIP]
|
- [Example](#example)
|
||||||
> The number precision can be changed up to 3 decimals using the arrow keys on your keyboard.
|
|
||||||
|
|
||||||
> [!TIP]
|
|
||||||
> The speedtest is at its best when the connection is as
|
|
||||||
> short as possible. For example, on your NAS or RPi to
|
|
||||||
> check on your LAN bandwidth.
|
|
||||||
|
|
||||||
- [Installation](#installation)
|
- [Installation](#installation)
|
||||||
- [Note on testing](#note-on-testing)
|
- [Note on testing](#note-on-testing)
|
||||||
- [Unlicense](#unlicense)
|
- [Unlicense](#unlicense)
|
||||||
- [Author](#author)
|
- [Author](#author)
|
||||||
|
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
The link below has the same HTML file (with stats)
|
||||||
|
and is basic static webhosting with no backend
|
||||||
|
processing. The test files were generated using the
|
||||||
|
`fallocate` command.
|
||||||
|
|
||||||
|
<https://speedtest.fvdm.com/>
|
||||||
|
|
||||||
|
You can change the number precision up to 3 decimals using the arrow
|
||||||
|
keys on your keyboard.
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Just clone the repo:
|
Just clone the repo:
|
||||||
@@ -80,6 +86,15 @@ These commands only create the files in the filesystem.
|
|||||||
No bytes are actually written to the storage.
|
No bytes are actually written to the storage.
|
||||||
The suffix `m` is megabytes and `g` is gigabytes and so on.
|
The suffix `m` is megabytes and `g` is gigabytes and so on.
|
||||||
|
|
||||||
|
Or you can download them from my server.
|
||||||
|
|
||||||
|
**Please don't hotlink!!**
|
||||||
|
|
||||||
|
* [1mb.bin](https://fvdm.com/speedtest/1mb.bin)
|
||||||
|
* [5mb.bin](https://fvdm.com/speedtest/5mb.bin)
|
||||||
|
* [10mb.bin](https://fvdm.com/speedtest/10mb.bin)
|
||||||
|
* [100mb.bin](https://fvdm.com/speedtest/100mb.bin)
|
||||||
|
|
||||||
|
|
||||||
## Note on testing
|
## Note on testing
|
||||||
|
|
||||||
@@ -98,6 +113,10 @@ my provider's speedtest I get double at least. Doing the same to my
|
|||||||
LiquidSky box in Frankfurt I easily get over 900 Mbit. So there is a
|
LiquidSky box in Frankfurt I easily get over 900 Mbit. So there is a
|
||||||
bottleneck somewhere between the web server and my home ISP.
|
bottleneck somewhere between the web server and my home ISP.
|
||||||
|
|
||||||
|
The speedtest is at its best when the connection is as
|
||||||
|
short as possible. For example, on your NAS or RPi to
|
||||||
|
check on your LAN bandwidth.
|
||||||
|
|
||||||
|
|
||||||
Unlicense
|
Unlicense
|
||||||
---------
|
---------
|
||||||
|
|||||||
134
index.html
134
index.html
@@ -139,8 +139,8 @@
|
|||||||
let binaryData;
|
let binaryData;
|
||||||
|
|
||||||
// control precision
|
// control precision
|
||||||
function onKeyDown( ev ) {
|
function onKeyDown (ev) {
|
||||||
switch ( ev.code ) {
|
switch (ev.code) {
|
||||||
case 'ArrowUp':
|
case 'ArrowUp':
|
||||||
case 'ArrowRight':
|
case 'ArrowRight':
|
||||||
decimals++;
|
decimals++;
|
||||||
@@ -155,15 +155,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener( 'keydown', onKeyDown );
|
document.addEventListener ('keydown', onKeyDown);
|
||||||
|
|
||||||
// store <button> tags in array
|
// store <button> tags in array
|
||||||
const btns = Array.from( document.querySelectorAll( 'button' ) );
|
const btns = Array.from (document.querySelectorAll ('button'));
|
||||||
|
|
||||||
// add click handler to buttons
|
// add click handler to buttons
|
||||||
btns.forEach( btn => {
|
btns.forEach (btn => {
|
||||||
btn.addEventListener( 'click', testDownload );
|
btn.addEventListener ('click', testDownload);
|
||||||
} );
|
});
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -174,22 +174,22 @@
|
|||||||
* @return {string} Rounded number with trailing zeros
|
* @return {string} Rounded number with trailing zeros
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function dec ( num, deci ) {
|
function dec (num, deci) {
|
||||||
const int = parseInt( num, 10 );
|
const int = parseInt (num, 10);
|
||||||
const flo = parseFloat( ( num % 1 ).toFixed( deci ) );
|
const flo = parseFloat ((num % 1).toFixed(deci));
|
||||||
const len = ( String( flo ).split( '.' )[1] || '' ).length;
|
const len = (String (flo).split ('.')[1] || '').length;
|
||||||
const diff = deci - len;
|
const diff = deci - len;
|
||||||
let res = String( int + flo );
|
let res = String (int + flo);
|
||||||
|
|
||||||
if ( ! flo && diff ) {
|
if (!flo && diff) {
|
||||||
res += '.';
|
res += '.';
|
||||||
for ( let i = 0; i < diff; i++ ) {
|
for (let i = 0; i < diff; i++) {
|
||||||
res += '0';
|
res += '0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( flo && diff > 0 ) {
|
if (flo && diff > 0) {
|
||||||
for ( let i = 0; i < diff; i++ ) {
|
for (let i = 0; i < diff; i++) {
|
||||||
res += '0';
|
res += '0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,25 +204,25 @@
|
|||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function testDone( updown, evBtn, evReq ) {
|
function testDone (updown, evBtn, evReq) {
|
||||||
const diff = ( Date.now() - start ) / 1000;
|
const diff = (Date.now() - start) / 1000;
|
||||||
|
|
||||||
if ( updown === 'download' ) {
|
if (updown === 'download') {
|
||||||
binaryData = req.response;
|
binaryData = req.response;
|
||||||
testUpload( evBtn );
|
testUpload (evBtn);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
binaryData = null;
|
binaryData = null;
|
||||||
resultString =
|
resultString =
|
||||||
dec( avg.download, 1 )
|
dec (avg.download, 1)
|
||||||
+ ' / ' + dec( avg.upload, 1 )
|
+ ' / ' + dec (avg.upload, 1)
|
||||||
+ ' Mb'
|
+ ' Mb'
|
||||||
;
|
;
|
||||||
|
|
||||||
document.querySelector( 'progress' ).style.visibility = 'hidden';
|
document.querySelector ('progress').style.visibility = 'hidden';
|
||||||
document.querySelector( '#result' ).className = 'resultDone';
|
document.querySelector ('#result').className = 'resultDone';
|
||||||
document.querySelector( '#result' ).innerHTML = resultString;
|
document.querySelector ('#result').innerHTML = resultString;
|
||||||
document.querySelector( '#eta' ).innerHTML = dec( diff, 2 ) + ' sec';
|
document.querySelector ('#eta').innerHTML = dec (diff, 2) + ' sec';
|
||||||
|
|
||||||
req = null;
|
req = null;
|
||||||
}
|
}
|
||||||
@@ -236,8 +236,8 @@
|
|||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function testRunning ( updown, ev ) {
|
function testRunning (updown, ev) {
|
||||||
const now = Date.now();
|
const now = Date.now ();
|
||||||
|
|
||||||
let percent = 0.0;
|
let percent = 0.0;
|
||||||
let Bps = 0;
|
let Bps = 0;
|
||||||
@@ -246,26 +246,26 @@
|
|||||||
let total = ev.total;
|
let total = ev.total;
|
||||||
let diff = 0;
|
let diff = 0;
|
||||||
|
|
||||||
if ( updown === 'upload' ) {
|
if (updown === 'upload') {
|
||||||
total = binaryData.size;
|
total = binaryData.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ev.lengthComputable && total ) {
|
if (ev.lengthComputable && total) {
|
||||||
diff = ( now - start ) / 1000;
|
diff = (now - start) / 1000;
|
||||||
Bps = ev.loaded / diff;
|
Bps = ev.loaded / diff;
|
||||||
mbit = Bps / 1024 / 1024 * 8;
|
mbit = Bps / 1024 / 1024 * 8;
|
||||||
avg[updown] = mbit;
|
avg[updown] = mbit;
|
||||||
percent = ev.loaded / total * 100.0;
|
percent = ev.loaded / total * 100.0;
|
||||||
eta = ( total - ev.loaded ) / Bps;
|
eta = (total - ev.loaded) / Bps;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( updown === 'upload' ) {
|
if (updown === 'upload') {
|
||||||
percent = 100 - percent;
|
percent = 100 - percent;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelector( 'progress' ).value = percent;
|
document.querySelector ('progress').value = percent;
|
||||||
document.querySelector( '#result' ).innerHTML = dec( avg[updown], decimals ) + ' Mbit/s';
|
document.querySelector ('#result').innerHTML = dec (avg[updown], decimals) + ' Mbit/s';
|
||||||
document.querySelector( '#eta' ).innerHTML = dec( eta, decimals ) + ' sec';
|
document.querySelector ('#eta').innerHTML = dec (eta, decimals) + ' sec';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -277,69 +277,69 @@
|
|||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function testDownload ( btnEv ) {
|
function testDownload (btnEv) {
|
||||||
if ( req ) {
|
if (req) {
|
||||||
req.abort();
|
req.abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
req = new XMLHttpRequest;
|
req = new XMLHttpRequest;
|
||||||
start = Date.now();
|
start = Date.now ();
|
||||||
|
|
||||||
btns.forEach( btn => {
|
btns.forEach (btn => {
|
||||||
btn.className = '';
|
btn.className = '';
|
||||||
} );
|
});
|
||||||
|
|
||||||
btnEv.target.className = 'choice';
|
btnEv.target.className = 'choice';
|
||||||
document.querySelector( 'progress' ).value = 0;
|
document.querySelector ('progress').value = 0;
|
||||||
document.querySelector( 'progress' ).style.visibility = 'visible';
|
document.querySelector ('progress').style.visibility = 'visible';
|
||||||
|
|
||||||
req.onprogress = progEv => {
|
req.onprogress = (progEv) => {
|
||||||
testRunning( 'download', progEv );
|
testRunning ('download', progEv);
|
||||||
};
|
};
|
||||||
|
|
||||||
req.onreadystatechange = reqEv => {
|
req.onreadystatechange = (reqEv) => {
|
||||||
if ( req.readyState === 4 ) {
|
if (req.readyState === 4) {
|
||||||
testDone( 'download', btnEv, reqEv );
|
testDone ('download', btnEv, reqEv);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// load file avoiding the cache
|
// load file avoiding the cache
|
||||||
req.open( 'GET', btnEv.target.dataset.file, true );
|
req.open ('GET', btnEv.target.dataset.file, true);
|
||||||
req.responseType = 'blob';
|
req.responseType = 'blob';
|
||||||
req.send( null );
|
req.send (null);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUpload ( btnEv ) {
|
function testUpload (btnEv) {
|
||||||
if ( req ) {
|
if (req) {
|
||||||
req.abort();
|
req.abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
req = new XMLHttpRequest;
|
req = new XMLHttpRequest;
|
||||||
start = Date.now();
|
start = Date.now ();
|
||||||
|
|
||||||
if ( req.upload ) {
|
if (req.upload) {
|
||||||
req.upload.onprogress = progEv => {
|
req.upload.onprogress = (progEv) => {
|
||||||
testRunning( 'upload', progEv );
|
testRunning ('upload', progEv);
|
||||||
};
|
};
|
||||||
|
|
||||||
req.upload.onloadend = reqEv => {
|
req.upload.onloadend = (reqEv) => {
|
||||||
testDone( 'upload', btnEv, reqEv );
|
testDone ('upload', btnEv, reqEv);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
req.onprogress = progEv => {
|
req.onprogress = (progEv) => {
|
||||||
testRunning( 'upload', progEv );
|
testRunning ('upload', progEv);
|
||||||
};
|
};
|
||||||
|
|
||||||
req.onreadystatechange = onreadystatechange = reqEv => {
|
req.onreadystatechange = onreadystatechange = (reqEv) => {
|
||||||
if ( req.readyState === 4 ) {
|
if (req.readyState === 4) {
|
||||||
testDone( 'upload', btnEv, reqEv );
|
testDone ('upload', btnEv, reqEv);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
req.open( 'POST', '?nocache=' + start, true );
|
req.open ('POST', '?nocache=' + start, true);
|
||||||
req.send( binaryData );
|
req.send (binaryData);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user