diff --git a/src/Starward/Pages/Setting/DownloadSettingPage.xaml.cs b/src/Starward/Pages/Setting/DownloadSettingPage.xaml.cs index cffec065c..7ca596111 100644 --- a/src/Starward/Pages/Setting/DownloadSettingPage.xaml.cs +++ b/src/Starward/Pages/Setting/DownloadSettingPage.xaml.cs @@ -71,10 +71,11 @@ partial void OnDefaultInstallPathChanged(string? value) partial void OnSpeedLimitChanged(int value) { InstallGameManager.SpeedLimitBytesPerSecond = value == 0 ? int.MaxValue : value * 1024; + var SpeedLimitBytesPerPeriod = Math.Max((int)Math.Floor((double)InstallGameManager.SpeedLimitBytesPerSecond / 20), 1 << 14); InstallGameManager.rateLimiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions { - TokensPerPeriod = InstallGameManager.SpeedLimitBytesPerSecond, - ReplenishmentPeriod = TimeSpan.FromSeconds(1), + TokensPerPeriod = SpeedLimitBytesPerPeriod, + ReplenishmentPeriod = SpeedLimitBytesPerPeriod == 1 << 14 ? TimeSpan.FromSeconds((1 << 14) / (double)InstallGameManager.SpeedLimitBytesPerSecond) : TimeSpan.FromMilliseconds(50), TokenLimit = InstallGameManager.SpeedLimitBytesPerSecond, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, AutoReplenishment = true diff --git a/src/Starward/Services/Download/InstallGameManager.cs b/src/Starward/Services/Download/InstallGameManager.cs index b24da6a75..2b10d7bdc 100644 --- a/src/Starward/Services/Download/InstallGameManager.cs +++ b/src/Starward/Services/Download/InstallGameManager.cs @@ -22,10 +22,11 @@ private InstallGameManager() _services = new(); int speed = AppConfig.SpeedLimitKBPerSecond * 1024; SpeedLimitBytesPerSecond = speed == 0 ? int.MaxValue : speed; + var SpeedLimitBytesPerPeriod = Math.Max((int)Math.Floor((double)SpeedLimitBytesPerSecond / 20), 1 << 14); rateLimiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions { - TokensPerPeriod = SpeedLimitBytesPerSecond, - ReplenishmentPeriod = TimeSpan.FromSeconds(1), + TokensPerPeriod = SpeedLimitBytesPerPeriod, + ReplenishmentPeriod = SpeedLimitBytesPerPeriod == 1 << 14 ? TimeSpan.FromSeconds((1 << 14) / (double)SpeedLimitBytesPerSecond) : TimeSpan.FromMilliseconds(50), // 这是一个CPU密集型任务,极低间隔会严重影响性能 TokenLimit = SpeedLimitBytesPerSecond, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, AutoReplenishment = true @@ -44,7 +45,7 @@ private InstallGameManager() public static int SpeedLimitBytesPerSecond { get; set; } - public static RateLimiter rateLimiter; + public static TokenBucketRateLimiter rateLimiter; private long _lastTimeStamp; diff --git a/src/Starward/Services/Download/InstallGameService.cs b/src/Starward/Services/Download/InstallGameService.cs index beb6c7a24..2caf02c6d 100644 --- a/src/Starward/Services/Download/InstallGameService.cs +++ b/src/Starward/Services/Download/InstallGameService.cs @@ -1208,10 +1208,10 @@ protected async Task DownloadItemAsync(InstallGameItem item, CancellationToken c do { lease = await InstallGameManager.rateLimiter.AcquireAsync(buffer.Length, cancellationToken).ConfigureAwait(false); - if (!lease.IsAcquired) - { + if (lease.TryGetMetadata(MetadataName.RetryAfter, out TimeSpan retryAfter)) + await Task.Delay(retryAfter, cancellationToken).ConfigureAwait(false); + else if (!lease.IsAcquired) await Task.Delay(1, cancellationToken).ConfigureAwait(false); - } } while (!lease.IsAcquired); await fs.WriteAsync(buffer.AsMemory(0, length), cancellationToken).ConfigureAwait(false); Interlocked.Add(ref _finishBytes, length);