From 91249e0f7b4832a207faa3b694bdb83be9bc0f7b Mon Sep 17 00:00:00 2001 From: igor Date: Tue, 2 Jan 2024 12:57:56 +0200 Subject: [PATCH] Use time shift instead of loading intervals. --- .../src/bandwidth-calculator.ts | 77 ++++++------------- .../src/p2p/tracker-client.ts | 5 +- packages/p2p-media-loader-core/src/request.ts | 7 -- 3 files changed, 27 insertions(+), 62 deletions(-) diff --git a/packages/p2p-media-loader-core/src/bandwidth-calculator.ts b/packages/p2p-media-loader-core/src/bandwidth-calculator.ts index 11807c9a..d5657ce0 100644 --- a/packages/p2p-media-loader-core/src/bandwidth-calculator.ts +++ b/packages/p2p-media-loader-core/src/bandwidth-calculator.ts @@ -1,89 +1,62 @@ -import { arrayBackwards } from "./utils/utils"; - -type Interval = { start: number; end?: number }; - const CLEAR_THRESHOLD_MS = 3000; export class BandwidthCalculator { private simultaneousLoadingsCount = 0; private readonly bytes: number[] = []; private readonly timestamps: number[] = []; - private loadingIntervals: Interval[] = []; + private noLoadingsTotalTime = 0; + private allLoadingsStoppedTimestamp = 0; - addBytes(bytesLength: number) { + addBytes(bytesLength: number, now = performance.now()) { this.bytes.push(bytesLength); - this.timestamps.push(performance.now()); + this.timestamps.push(now - this.noLoadingsTotalTime); } - startLoading() { + startLoading(now = performance.now()) { this.clearStale(); if (this.simultaneousLoadingsCount === 0) { - this.loadingIntervals.push({ start: performance.now() }); + this.noLoadingsTotalTime += now - this.allLoadingsStoppedTimestamp; } this.simultaneousLoadingsCount++; } - stopLoading() { - this.clearStale(); + // in bits per second + stopLoading(now = performance.now()) { if (this.simultaneousLoadingsCount <= 0) return; this.simultaneousLoadingsCount--; if (this.simultaneousLoadingsCount !== 0) return; - this.loadingIntervals[this.loadingIntervals.length - 1].end = - performance.now(); + this.allLoadingsStoppedTimestamp = now; } - // in bits per second getBandwidthForLastNSeconds(seconds: number) { - const { bytes, timestamps } = this; - if (!bytes.length) return 0; + if (!this.timestamps.length) return 0; const milliseconds = seconds * 1000; - const now = performance.now(); - let totalTime = 0; - - let firstIntervalStart = Number.POSITIVE_INFINITY; - for (const { start, end = now } of arrayBackwards(this.loadingIntervals)) { - const duration = end - start; - if (totalTime + duration < milliseconds) { - totalTime += duration; - firstIntervalStart = start; - continue; - } - firstIntervalStart = end - (milliseconds - totalTime); - totalTime = milliseconds; - break; - } - if (totalTime === 0) return 0; - + const lastItemTimestamp = this.timestamps[this.timestamps.length - 1]; + let lastCountedTimestamp = lastItemTimestamp; + const threshold = lastItemTimestamp - milliseconds; let totalBytes = 0; - for (let i = bytes.length - 1; i >= 0; i--) { - if (timestamps[i] < firstIntervalStart) break; - totalBytes += bytes[i]; + + for (let i = this.bytes.length - 1; i >= 0; i--) { + const timestamp = this.timestamps[i]; + if (timestamp < threshold) break; + lastCountedTimestamp = timestamp; + totalBytes += this.bytes[i]; } - return (totalBytes * 8000) / totalTime; + return (totalBytes * 8000) / (lastItemTimestamp - lastCountedTimestamp); } clearStale() { - if (!this.loadingIntervals.length) return; - const now = performance.now(); - let totalTime = 0; + if (!this.timestamps.length) return; + const threshold = + this.timestamps[this.timestamps.length - 1] - CLEAR_THRESHOLD_MS; - let intervalsToLeave = 0; - for (const { start, end = now } of arrayBackwards(this.loadingIntervals)) { - const duration = end - start; - intervalsToLeave++; - if (totalTime + duration >= CLEAR_THRESHOLD_MS) break; - totalTime += duration; - } - const intervalsToRemove = this.loadingIntervals.length - intervalsToLeave; - this.loadingIntervals.splice(0, intervalsToRemove); - - const { start: firstIntervalStart } = this.loadingIntervals[0]; let samplesToRemove = 0; for (const timestamp of this.timestamps) { - if (timestamp >= firstIntervalStart) break; + if (timestamp > threshold) break; samplesToRemove++; } + this.bytes.splice(0, samplesToRemove); this.timestamps.splice(0, samplesToRemove); } diff --git a/packages/p2p-media-loader-core/src/p2p/tracker-client.ts b/packages/p2p-media-loader-core/src/p2p/tracker-client.ts index 625b1fe4..6f862655 100644 --- a/packages/p2p-media-loader-core/src/p2p/tracker-client.ts +++ b/packages/p2p-media-loader-core/src/p2p/tracker-client.ts @@ -31,9 +31,8 @@ export class P2PTrackerClient { private readonly settings: Settings ) { const { string: peerId, bytes: peerIdBytes } = PeerUtil.generatePeerId(); - const { bytes: streamIdBytes, string: streamHash } = PeerUtil.getStreamHash( - streamId + "a" - ); + const { bytes: streamIdBytes, string: streamHash } = + PeerUtil.getStreamHash(streamId); this.peerId = peerId; this.streamShortId = LoggerUtils.getStreamString(stream); diff --git a/packages/p2p-media-loader-core/src/request.ts b/packages/p2p-media-loader-core/src/request.ts index 5875b8dc..f7ec5b7a 100644 --- a/packages/p2p-media-loader-core/src/request.ts +++ b/packages/p2p-media-loader-core/src/request.ts @@ -208,7 +208,6 @@ export class Request { resolveEngineCallbacksSuccessfully() { if (!this.finalData) return; const bandwidth = this.bandwidthCalculator.getBandwidthForLastNSeconds(3); - console.log("bandwidth", bandwidth / 1000); this._engineCallbacks?.onSuccess({ data: this.finalData, bandwidth }); this._engineCallbacks = undefined; } @@ -323,11 +322,6 @@ export class Request { class FailedRequestAttempts { private attempts: Required[] = []; - private _lastClearTimestamp = performance.now(); - - get lastClearTimestamp() { - return this._lastClearTimestamp; - } add(attempt: Required) { this.attempts.push(attempt); @@ -346,7 +340,6 @@ class FailedRequestAttempts { clear() { this.attempts = []; - this._lastClearTimestamp = performance.now(); } }