v0.19.0 — Bump default parallel segments 8→16 to shorten end-of-DL tail
Issue : on a 14 GB download with 8 segments, when 7 finish there's only 1 connection left handling its assigned 1.75 GB → apparent throughput collapses to 1/8th of the peak for the final stretch (~5 min visible slowdown at the end). Quick fix : double the default segment count. - 8 segments : last has 1.75 GB to finish alone - 16 segments : last has 875 MB → tail ~halved Tuning surfaced in Settings → Avancés → Serveur as « Connexions parallèles pour les téléchargements (1-32, défaut 16) ». Power users on faster servers can push to 24-32. OVH mutualisé tolerates up to 16-24 ; above that, soft rate-limiting kicks in. Aligned : - LocalConfig default : 8 → 16 - DownloadManager clamp : Math.Clamp(_, 1, 16) → 1, 32 - HttpClient handler MaxConnectionsPerServer : 16 → 32 (matches new ceiling) Versions bumped to 0.19.0. Existing config.json files will keep their previous value (8) untouched ; delete config.json to pick up the new default, or just bump it in Settings → Avancés. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#define MyAppName "PROSERVE Launcher"
|
#define MyAppName "PROSERVE Launcher"
|
||||||
#define MyAppShortName "PS_Launcher"
|
#define MyAppShortName "PS_Launcher"
|
||||||
#define MyAppVersion "0.18.0"
|
#define MyAppVersion "0.19.0"
|
||||||
#define MyAppPublisher "ASTERION VR"
|
#define MyAppPublisher "ASTERION VR"
|
||||||
#define MyAppURL "https://asterionvr.com"
|
#define MyAppURL "https://asterionvr.com"
|
||||||
#define MyAppExeName "PS_Launcher.exe"
|
#define MyAppExeName "PS_Launcher.exe"
|
||||||
|
|||||||
@@ -112,16 +112,16 @@ public partial class App : Application
|
|||||||
services.AddSingleton(sp =>
|
services.AddSingleton(sp =>
|
||||||
{
|
{
|
||||||
// Handler tuné pour les gros téléchargements parallèles :
|
// Handler tuné pour les gros téléchargements parallèles :
|
||||||
// - MaxConnectionsPerServer=16 pour autoriser le multi-segment (8 par défaut).
|
// - MaxConnectionsPerServer=32 pour aligner avec le clamp DownloadManager (8-32).
|
||||||
// - AutomaticDecompression sur l'API JSON uniquement (None ici car les builds
|
// Default WPF = 8 → trop bas pour notre multi-segment.
|
||||||
// sont des ZIPs déjà compressés ; éviter la CPU+RAM gaspillée par un éventuel
|
// - AutomaticDecompression=None : les builds sont des ZIPs déjà compressés ;
|
||||||
// wrapping gzip côté serveur).
|
// éviter la CPU+RAM gaspillée par un éventuel wrapping gzip côté serveur.
|
||||||
// - PooledConnectionLifetime court pour éviter qu'OVH ferme nos sockets sous nous.
|
// - PooledConnectionLifetime court pour éviter qu'OVH ferme nos sockets sous nous.
|
||||||
var handler = new SocketsHttpHandler
|
var handler = new SocketsHttpHandler
|
||||||
{
|
{
|
||||||
PooledConnectionLifetime = TimeSpan.FromMinutes(5),
|
PooledConnectionLifetime = TimeSpan.FromMinutes(5),
|
||||||
PooledConnectionIdleTimeout = TimeSpan.FromSeconds(60),
|
PooledConnectionIdleTimeout = TimeSpan.FromSeconds(60),
|
||||||
MaxConnectionsPerServer = 16,
|
MaxConnectionsPerServer = 32,
|
||||||
EnableMultipleHttp2Connections = true,
|
EnableMultipleHttp2Connections = true,
|
||||||
AutomaticDecompression = System.Net.DecompressionMethods.None,
|
AutomaticDecompression = System.Net.DecompressionMethods.None,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
<Product>PROSERVE Launcher</Product>
|
<Product>PROSERVE Launcher</Product>
|
||||||
<Copyright>© 2026 ASTERION VR — All rights reserved</Copyright>
|
<Copyright>© 2026 ASTERION VR — All rights reserved</Copyright>
|
||||||
<RootNamespace>PSLauncher.App</RootNamespace>
|
<RootNamespace>PSLauncher.App</RootNamespace>
|
||||||
<Version>0.18.0</Version>
|
<Version>0.19.0</Version>
|
||||||
<AssemblyVersion>0.18.0.0</AssemblyVersion>
|
<AssemblyVersion>0.19.0.0</AssemblyVersion>
|
||||||
<FileVersion>0.18.0.0</FileVersion>
|
<FileVersion>0.19.0.0</FileVersion>
|
||||||
|
|
||||||
<!-- Single-file self-contained publish profile (used by `dotnet publish`) -->
|
<!-- Single-file self-contained publish profile (used by `dotnet publish`) -->
|
||||||
<PublishSingleFile>true</PublishSingleFile>
|
<PublishSingleFile>true</PublishSingleFile>
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ public sealed partial class SettingsViewModel : ObservableObject
|
|||||||
[ObservableProperty] private string _language;
|
[ObservableProperty] private string _language;
|
||||||
[ObservableProperty] private string _reportUrl;
|
[ObservableProperty] private string _reportUrl;
|
||||||
[ObservableProperty] private string _documentationUrl;
|
[ObservableProperty] private string _documentationUrl;
|
||||||
|
[ObservableProperty] private int _parallelSegments;
|
||||||
|
|
||||||
// ----- DB Migration settings -----
|
// ----- DB Migration settings -----
|
||||||
[ObservableProperty] private string _dbHost;
|
[ObservableProperty] private string _dbHost;
|
||||||
@@ -173,6 +174,7 @@ public sealed partial class SettingsViewModel : ObservableObject
|
|||||||
_language = string.IsNullOrWhiteSpace(config.Language) ? "auto" : config.Language;
|
_language = string.IsNullOrWhiteSpace(config.Language) ? "auto" : config.Language;
|
||||||
_reportUrl = config.ReportUrl;
|
_reportUrl = config.ReportUrl;
|
||||||
_documentationUrl = config.DocumentationUrl;
|
_documentationUrl = config.DocumentationUrl;
|
||||||
|
_parallelSegments = config.ParallelDownloadSegments;
|
||||||
|
|
||||||
_dbHost = config.Database.Host;
|
_dbHost = config.Database.Host;
|
||||||
_dbPort = config.Database.Port;
|
_dbPort = config.Database.Port;
|
||||||
@@ -303,6 +305,7 @@ public sealed partial class SettingsViewModel : ObservableObject
|
|||||||
_config.Language = Language ?? "auto";
|
_config.Language = Language ?? "auto";
|
||||||
_config.ReportUrl = ReportUrl?.Trim() ?? "";
|
_config.ReportUrl = ReportUrl?.Trim() ?? "";
|
||||||
_config.DocumentationUrl = DocumentationUrl?.Trim() ?? "";
|
_config.DocumentationUrl = DocumentationUrl?.Trim() ?? "";
|
||||||
|
_config.ParallelDownloadSegments = Math.Clamp(ParallelSegments, 1, 32);
|
||||||
|
|
||||||
// DB settings
|
// DB settings
|
||||||
_config.Database.Host = DbHost.Trim();
|
_config.Database.Host = DbHost.Trim();
|
||||||
|
|||||||
@@ -230,6 +230,19 @@
|
|||||||
Background="#1A1A20" Foreground="{StaticResource Brush.Text.Primary}"
|
Background="#1A1A20" Foreground="{StaticResource Brush.Text.Primary}"
|
||||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1" Padding="8"
|
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1" Padding="8"
|
||||||
FontFamily="Consolas" />
|
FontFamily="Consolas" />
|
||||||
|
|
||||||
|
<!-- Connexions parallèles : tuning de la queue de fin de DL -->
|
||||||
|
<TextBlock Text="{x:Static loc:Strings.SettingsParallelSegments}"
|
||||||
|
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||||
|
FontSize="12" Margin="0,16,0,4" />
|
||||||
|
<TextBox Text="{Binding ParallelSegments, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Background="#1A1A20" Foreground="{StaticResource Brush.Text.Primary}"
|
||||||
|
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1" Padding="8"
|
||||||
|
Width="80" HorizontalAlignment="Left" />
|
||||||
|
<TextBlock Text="{x:Static loc:Strings.SettingsParallelSegmentsHint}"
|
||||||
|
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||||
|
FontSize="11" FontStyle="Italic" Margin="0,4,0,0"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
|||||||
@@ -176,7 +176,10 @@ public sealed class DownloadManager : IDownloadManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Choix single vs multi-segment
|
// 2. Choix single vs multi-segment
|
||||||
var requestedSegments = Math.Clamp(_config.ParallelDownloadSegments, 1, 16);
|
// Hard-cap à 32 : au-delà OVH mutualisé risque le rate-limit per-IP et le
|
||||||
|
// gain marginal devient négatif. 16 = défaut, 24-32 OK pour les serveurs
|
||||||
|
// qui le supportent. 1 = comportement single-segment legacy.
|
||||||
|
var requestedSegments = Math.Clamp(_config.ParallelDownloadSegments, 1, 32);
|
||||||
var useMultiSegment = requestedSegments > 1
|
var useMultiSegment = requestedSegments > 1
|
||||||
&& job.ExpectedSize >= MultiSegmentMinSize
|
&& job.ExpectedSize >= MultiSegmentMinSize
|
||||||
&& (existing is null || existing.Segments.Count > 0);
|
&& (existing is null || existing.Segments.Count > 0);
|
||||||
|
|||||||
@@ -177,6 +177,21 @@ public static class Strings
|
|||||||
$"تعذر تحميل {url}\n\n{detail}\n\nتأكد من تشغيل XAMPP وأن العنوان صحيح (الإعدادات → متقدم)."
|
$"تعذر تحميل {url}\n\n{detail}\n\nتأكد من تشغيل XAMPP وأن العنوان صحيح (الإعدادات → متقدم)."
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static string SettingsParallelSegments => T(
|
||||||
|
"Connexions parallèles pour les téléchargements (1-32, défaut 16)",
|
||||||
|
"Parallel connections for downloads (1-32, default 16)",
|
||||||
|
"下载的并行连接数 (1-32,默认 16)",
|
||||||
|
"การเชื่อมต่อแบบขนานสำหรับการดาวน์โหลด (1-32, ค่าเริ่มต้น 16)",
|
||||||
|
"اتصالات متوازية للتنزيلات (1-32، الافتراضي 16)"
|
||||||
|
);
|
||||||
|
public static string SettingsParallelSegmentsHint => T(
|
||||||
|
"Plus de connexions = débit pic plus élevé et queue de fin de DL plus courte. Au-delà de 16 le serveur peut throttler.",
|
||||||
|
"More connections = higher peak throughput and shorter end-of-DL tail. Above 16 the server may throttle.",
|
||||||
|
"更多连接 = 更高的峰值吞吐量和更短的下载尾部。超过 16 服务器可能会限速。",
|
||||||
|
"การเชื่อมต่อมากขึ้น = ปริมาณงานสูงสุดมากขึ้นและส่วนท้ายของการดาวน์โหลดสั้นลง สูงกว่า 16 เซิร์ฟเวอร์อาจจำกัด",
|
||||||
|
"اتصالات أكثر = إنتاجية ذروة أعلى وذيل تنزيل أقصر. فوق 16 قد يقيّد الخادم."
|
||||||
|
);
|
||||||
|
|
||||||
public static string SettingsAdvanced => T(
|
public static string SettingsAdvanced => T(
|
||||||
"▸ PARAMÈTRES AVANCÉS (serveur, installation, base de données, logs)",
|
"▸ PARAMÈTRES AVANCÉS (serveur, installation, base de données, logs)",
|
||||||
"▸ ADVANCED SETTINGS (server, installation, database, logs)",
|
"▸ ADVANCED SETTINGS (server, installation, database, logs)",
|
||||||
|
|||||||
@@ -16,9 +16,13 @@ public sealed class LocalConfig
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Nombre de connexions HTTP parallèles utilisées pour télécharger un build.
|
/// Nombre de connexions HTTP parallèles utilisées pour télécharger un build.
|
||||||
/// 1 = comportement legacy single-connection. 4-8 contourne le throttling
|
/// 1 = comportement legacy single-connection. 4-8 contourne le throttling
|
||||||
/// per-connection d'Apache/OVH mutualisé. 8 est un bon défaut.
|
/// per-connection d'Apache/OVH mutualisé. 16 = défaut depuis v0.19 pour
|
||||||
|
/// raccourcir la « queue » en fin de DL : avec 8 segments sur 14 Go, le
|
||||||
|
/// dernier segment doit finir seul ~1.75 Go (visible comme un effondrement
|
||||||
|
/// du débit en fin de course) ; avec 16, c'est ~875 Mo. Push à 24/32 si
|
||||||
|
/// ton serveur l'accepte (OVH mutualisé tient bien jusqu'à 16-24).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int ParallelDownloadSegments { get; set; } = 8;
|
public int ParallelDownloadSegments { get; set; } = 16;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Si false, ignore la vérification SHA-256 même si le manifest l'exige.
|
/// Si false, ignore la vérification SHA-256 même si le manifest l'exige.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<AssemblyName>PS_Launcher.Updater</AssemblyName>
|
<AssemblyName>PS_Launcher.Updater</AssemblyName>
|
||||||
<RootNamespace>PSLauncher.Updater</RootNamespace>
|
<RootNamespace>PSLauncher.Updater</RootNamespace>
|
||||||
<Version>0.18.0</Version>
|
<Version>0.19.0</Version>
|
||||||
<ApplicationIcon>..\PSLauncher.App\Resources\favicon.ico</ApplicationIcon>
|
<ApplicationIcon>..\PSLauncher.App\Resources\favicon.ico</ApplicationIcon>
|
||||||
<Company>ASTERION VR</Company>
|
<Company>ASTERION VR</Company>
|
||||||
<Copyright>© 2026 ASTERION VR — All rights reserved</Copyright>
|
<Copyright>© 2026 ASTERION VR — All rights reserved</Copyright>
|
||||||
|
|||||||
Reference in New Issue
Block a user