From d5abbb358486580571e4d5ec92bc17f7ef541602 Mon Sep 17 00:00:00 2001 From: FooIbar <118464521+FooIbar@users.noreply.github.com> Date: Thu, 14 Aug 2025 18:21:08 +0800 Subject: [PATCH] Stop speed tracker immediately if download is done Subsequent disk I/O will make the reported download speed inaccurate. --- .../ehviewer/download/DownloadManager.kt | 4 +--- .../com/hippo/ehviewer/spider/SpeedTracker.kt | 24 +++++++++++-------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/src/main/kotlin/com/hippo/ehviewer/download/DownloadManager.kt b/app/src/main/kotlin/com/hippo/ehviewer/download/DownloadManager.kt index 4c929c91a..988686672 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/download/DownloadManager.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/download/DownloadManager.kt @@ -711,9 +711,7 @@ object DownloadManager : OnSpiderListener, CoroutineScope { fun start() { if (currentJob == null) { currentJob = launch { - tracker.speedFlow().collect { speed -> - updateSpeed(speed.toLong()) - } + tracker.speedFlow().collect(::updateSpeed) } } } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/spider/SpeedTracker.kt b/app/src/main/kotlin/com/hippo/ehviewer/spider/SpeedTracker.kt index 694d8e6e7..551b056e8 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/spider/SpeedTracker.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/spider/SpeedTracker.kt @@ -24,7 +24,7 @@ import kotlin.time.Duration.Companion.seconds import kotlin.time.Instant import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock @@ -47,7 +47,7 @@ class SpeedTracker(val window: Duration = 1.seconds) { } } - fun speedFlow(sample: Duration = 1.seconds) = fixedRate(sample).map { + fun speedFlow(sample: Duration = 1.seconds) = fixedRate(sample).mapNotNull { mutex.withLock { start?.let { start -> val now = Clock.System.now() @@ -55,8 +55,8 @@ class SpeedTracker(val window: Duration = 1.seconds) { val window = passed.coerceIn(10.milliseconds, window) val cutoff = now - window received.removeIf { time, _ -> time < cutoff } - received.fold(0) { total, _, v -> total + v } / (window / 1.seconds) - } ?: 0.0 + (received.fold(0) { total, _, v -> total + v } / (window / 1.seconds)).toLong() + } } } } @@ -80,8 +80,12 @@ suspend inline fun timeoutBySpeed( var prev = 0L onDownload { done, total -> val bytesRead = (done - prev).toInt() - tracker.track(bytesRead) - l(total!!, done, bytesRead) + if (done == total!!) { + tracker.reset() + } else { + tracker.track(bytesRead) + } + l(total, done, bytesRead) prev = done } timeout { reset() } @@ -89,10 +93,10 @@ suspend inline fun timeoutBySpeed( watchdog.cancel() resp.status.ensureSuccess() val speedWatchdog = launch { - val timeoutSpeed = speedLevelToSpeed(Settings.timeoutSpeed.value) * 1024.0 - tracker.speedFlow(1.seconds).collect { speed -> - if (timeoutSpeed != 0.0 && speed < timeoutSpeed) { - onTimeout(LowSpeedException(url, speed.toLong())) + val timeoutSpeed = speedLevelToSpeed(Settings.timeoutSpeed.value) * 1024L + tracker.speedFlow().collect { speed -> + if (speed < timeoutSpeed) { + onTimeout(LowSpeedException(url, speed)) } } }