hlarcher HF Staff commited on
Commit
e3d1af9
·
unverified ·
1 Parent(s): 6f6d8a6

feat: add bandwidth and latency testing functionality with progress tracking

Browse files
Files changed (3) hide show
  1. src/app.css +28 -0
  2. src/lib/index.ts +12 -7
  3. src/routes/+page.svelte +54 -10
src/app.css CHANGED
@@ -1,2 +1,30 @@
1
  @import 'tailwindcss';
2
  @plugin '@tailwindcss/typography';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  @import 'tailwindcss';
2
  @plugin '@tailwindcss/typography';
3
+
4
+ .progress-bar {
5
+ height: 9px;
6
+ border-radius: 4px;
7
+ background: linear-gradient(90deg, #4f46e5 0%, #10b981 50%, #f59e0b 100%);
8
+ transition: width 0.3s ease;
9
+ }
10
+ .wave {
11
+ position: relative;
12
+ overflow: hidden;
13
+ }
14
+ .wave::after {
15
+ content: "";
16
+ position: absolute;
17
+ top: 0;
18
+ left: 0;
19
+ right: 0;
20
+ bottom: 0;
21
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
22
+ animation: wave 2s linear infinite;
23
+ }
24
+ @keyframes wave {
25
+ 0% { transform: translateX(-100%); }
26
+ 100% { transform: translateX(100%); }
27
+ }
28
+ .glow {
29
+ box-shadow: 0 0 15px rgba(79, 70, 229, 0.5);
30
+ }
src/lib/index.ts CHANGED
@@ -7,7 +7,7 @@ interface BandwidthCallback {
7
  totalBytes: number,
8
  bytesPerSecond: number,
9
  done: boolean
10
- ): void;
11
  }
12
 
13
  export async function bandwidthTest(
@@ -18,8 +18,8 @@ export async function bandwidthTest(
18
  performance.clearResourceTimings();
19
  // start timer
20
  const startTime = performance.now();
21
- // const url = 'https://cdn-test-cloudfront.hf.co/140gb.safetensors';
22
- const url = 'https://cdn-test-cloudfront.hf.co/15mb.json';
23
  const response = await fetch(url);
24
  if (!response.ok) {
25
  throw new Error(`Network response was not ok: ${response.status}`);
@@ -37,15 +37,15 @@ export async function bandwidthTest(
37
  // }, 2000);
38
  const latency = performance.now() - startTime;
39
  onLatency(latency);
40
- const contentLengthHeader = response.headers.get('Content-Length');
41
- const totalBytes = contentLengthHeader ? parseInt(contentLengthHeader, 10) : 0;
42
  const reader = response.body.getReader();
43
  let loadedBytes = 0;
44
  let lastTimestamp = performance.now();
45
  let lastLoaded = 0;
46
  const REPORT_INTERVAL_MS = 500;
47
  onProgress(latency, loadedBytes, totalBytes, 0, false);
48
- let bytesPerSecond= 0;
49
  while (true) {
50
  const { done, value } = await reader.read();
51
  if (done) {
@@ -71,7 +71,12 @@ export async function bandwidthTest(
71
 
72
  // Invoke callback
73
  const elapsedMs = performance.now() - startTime;
74
- onProgress(elapsedMs, loadedBytes, totalBytes, bytesPerSecond, false);
 
 
 
 
 
75
 
76
  // Reset our “last” markers
77
  lastLoaded = loadedBytes;
 
7
  totalBytes: number,
8
  bytesPerSecond: number,
9
  done: boolean
10
+ ): boolean;
11
  }
12
 
13
  export async function bandwidthTest(
 
18
  performance.clearResourceTimings();
19
  // start timer
20
  const startTime = performance.now();
21
+ const url = 'https://cdn-test-cloudfront.hf.co/5gb.safetensors';
22
+ // const url = 'https://cdn-test-cloudfront.hf.co/15mb.json';
23
  const response = await fetch(url);
24
  if (!response.ok) {
25
  throw new Error(`Network response was not ok: ${response.status}`);
 
37
  // }, 2000);
38
  const latency = performance.now() - startTime;
39
  onLatency(latency);
40
+ const contentLengthHeader = response.headers.get('content-length');
41
+ const totalBytes = contentLengthHeader ? parseInt(contentLengthHeader, 10) : 1e99;
42
  const reader = response.body.getReader();
43
  let loadedBytes = 0;
44
  let lastTimestamp = performance.now();
45
  let lastLoaded = 0;
46
  const REPORT_INTERVAL_MS = 500;
47
  onProgress(latency, loadedBytes, totalBytes, 0, false);
48
+ let bytesPerSecond = 0;
49
  while (true) {
50
  const { done, value } = await reader.read();
51
  if (done) {
 
71
 
72
  // Invoke callback
73
  const elapsedMs = performance.now() - startTime;
74
+ const stop = onProgress(elapsedMs, loadedBytes, totalBytes, bytesPerSecond, false);
75
+ if (stop) {
76
+ // stop the test
77
+ console.log(`Stopping bandwidth test at ${loadedBytes} bytes after ${elapsedMs} ms`);
78
+ break;
79
+ }
80
 
81
  // Reset our “last” markers
82
  lastLoaded = loadedBytes;
src/routes/+page.svelte CHANGED
@@ -5,11 +5,13 @@
5
 
6
  Chart.register(...registerables);
7
 
8
- let currentBandwidth = $state("0");
9
  let currentLatency = $state(0);
 
10
  let bandwidthMeasurements: number[] = $state([]);
11
  let timeMeasurements: string[] = $state([]);
12
- let bandwidthCallback = (elapsedMs: number, totalBytes: number, loadedBytes: number, bw: number) => {
 
13
  let mbps = (bw / 1000000 * 8); // convert Bps to Mbps
14
  // update the bandwidth state
15
  currentBandwidth = mbps.toFixed(2);
@@ -21,14 +23,38 @@
21
  bandwidthMeasurements.shift();
22
  timeMeasurements.shift();
23
  }
 
 
 
 
 
 
 
 
 
 
 
 
24
  };
25
  let latencyCallback = (latency: number) => {
26
  // update the latency state
27
  currentLatency = latency;
28
- console.log('Latency:', latency);
29
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  //counter(callback);
31
- bandwidthTest(bandwidthCallback, latencyCallback);
32
 
33
  let canvas: HTMLCanvasElement;
34
 
@@ -97,6 +123,22 @@
97
  speedChart.destroy();
98
  };
99
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  </script>
101
  <!-- Main Card -->
102
  <div class="bg-white rounded-xl shadow-lg overflow-hidden mb-8 transition-all duration-300 hover:shadow-xl">
@@ -104,8 +146,8 @@
104
  <div class="flex items-center justify-between mb-6">
105
  <h2 class="text-xl font-semibold text-gray-800">Connection Statistics</h2>
106
  <div id="connection-status" class="flex items-center">
107
- <span class="h-3 w-3 rounded-full bg-gray-300 mr-2"></span>
108
- <span class="text-sm text-gray-500">Idle</span>
109
  </div>
110
  </div>
111
 
@@ -132,22 +174,24 @@
132
  <div class="mb-6">
133
  <div class="flex justify-between mb-2">
134
  <span class="text-sm font-medium text-gray-700">Test Progress</span>
135
- <span id="progress-percent" class="text-sm font-medium text-gray-700">0%</span>
136
  </div>
137
  <div class="w-full bg-gray-200 rounded-full h-2.5">
138
- <div id="progress-bar" class="progress-bar h-2.5 rounded-full" style="width: 0%"></div>
 
139
  </div>
140
  </div>
141
  <!-- Test Controls -->
142
  <div class="flex flex-col sm:flex-row justify-center gap-4">
143
  <button id="start-test"
144
- class="bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-3 px-6 rounded-lg transition-all flex items-center justify-center glow">
 
145
  <i class="fas fa-play mr-2"></i>
146
  Start Test
147
  </button>
148
  <button id="stop-test"
149
  class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-3 px-6 rounded-lg transition-all flex items-center justify-center"
150
- disabled>
151
  <i class="fas fa-stop mr-2"></i>
152
  Stop Test
153
  </button>
 
5
 
6
  Chart.register(...registerables);
7
 
8
+ let currentBandwidth = $state('0');
9
  let currentLatency = $state(0);
10
+ let progress = $state(0);
11
  let bandwidthMeasurements: number[] = $state([]);
12
  let timeMeasurements: string[] = $state([]);
13
+ let testStatus = $state('Idle');
14
+ let bandwidthCallback = (elapsedMs: number, loadedBytes: number, totalBytes: number, bw: number, done: boolean) => {
15
  let mbps = (bw / 1000000 * 8); // convert Bps to Mbps
16
  // update the bandwidth state
17
  currentBandwidth = mbps.toFixed(2);
 
23
  bandwidthMeasurements.shift();
24
  timeMeasurements.shift();
25
  }
26
+ // update the progress state
27
+ progress = (loadedBytes / totalBytes) * 100;
28
+ if (testStatus == 'Stopped') {
29
+ return true;
30
+ }
31
+ if (done) {
32
+ testStatus = 'Completed';
33
+ progress = 100;
34
+ } else {
35
+ testStatus = 'Running';
36
+ }
37
+ return false;
38
  };
39
  let latencyCallback = (latency: number) => {
40
  // update the latency state
41
  currentLatency = latency;
 
42
  };
43
+
44
+ const startTest = () => {
45
+ testStatus = 'Running';
46
+ progress = 0;
47
+ bandwidthMeasurements = [];
48
+ timeMeasurements = [];
49
+ currentBandwidth = '0';
50
+ currentLatency = 0;
51
+ bandwidthTest(bandwidthCallback, latencyCallback);
52
+ };
53
+ const stopTest = () => {
54
+ testStatus = 'Stopped';
55
+ }
56
  //counter(callback);
57
+ //bandwidthTest(bandwidthCallback, latencyCallback);
58
 
59
  let canvas: HTMLCanvasElement;
60
 
 
123
  speedChart.destroy();
124
  };
125
  };
126
+ const getStatusClass = () => {
127
+ switch (testStatus) {
128
+ case 'Idle':
129
+ return 'bg-gray-300';
130
+ case 'Running':
131
+ return 'bg-blue-500';
132
+ case 'Completed':
133
+ return 'bg-green-500';
134
+ case 'Error':
135
+ return 'bg-red-500';
136
+ case 'Stopped':
137
+ return 'bg-red-500';
138
+ default:
139
+ return 'bg-gray-300';
140
+ }
141
+ };
142
  </script>
143
  <!-- Main Card -->
144
  <div class="bg-white rounded-xl shadow-lg overflow-hidden mb-8 transition-all duration-300 hover:shadow-xl">
 
146
  <div class="flex items-center justify-between mb-6">
147
  <h2 class="text-xl font-semibold text-gray-800">Connection Statistics</h2>
148
  <div id="connection-status" class="flex items-center">
149
+ <span class="h-3 w-3 rounded-full {getStatusClass()} mr-2"></span>
150
+ <span class="text-sm text-gray-500">{testStatus}</span>
151
  </div>
152
  </div>
153
 
 
174
  <div class="mb-6">
175
  <div class="flex justify-between mb-2">
176
  <span class="text-sm font-medium text-gray-700">Test Progress</span>
177
+ <span id="progress-percent" class="text-sm font-medium text-gray-700">{progress.toFixed(0)}%</span>
178
  </div>
179
  <div class="w-full bg-gray-200 rounded-full h-2.5">
180
+ <div id="progress-bar" class="progress-bar h-2.5 rounded-full {progress<100 && progress >0? 'wave':''}"
181
+ style="width: {progress}%"></div>
182
  </div>
183
  </div>
184
  <!-- Test Controls -->
185
  <div class="flex flex-col sm:flex-row justify-center gap-4">
186
  <button id="start-test"
187
+ class="bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-3 px-6 rounded-lg transition-all flex items-center justify-center glow"
188
+ onclick={startTest}>
189
  <i class="fas fa-play mr-2"></i>
190
  Start Test
191
  </button>
192
  <button id="stop-test"
193
  class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-3 px-6 rounded-lg transition-all flex items-center justify-center"
194
+ disabled={testStatus!=='Running'} onclick={stopTest}>
195
  <i class="fas fa-stop mr-2"></i>
196
  Stop Test
197
  </button>