Optimize speed test

This commit is contained in:
2dust 2023-02-08 19:20:44 +08:00
parent dfb6cef364
commit d014724a2d
17 changed files with 285 additions and 53 deletions

View file

@ -0,0 +1,89 @@
using Downloader;
using System.Net;
namespace v2rayN.Base
{
internal class DownloaderHelper
{
private static readonly Lazy<DownloaderHelper> _instance = new Lazy<DownloaderHelper>(() => new());
public static DownloaderHelper Instance => _instance.Value;
public DownloaderHelper()
{
}
public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress<string> progress, int timeout)
{
if (string.IsNullOrEmpty(url))
{
throw new ArgumentNullException("url");
}
var cancellationToken = new CancellationTokenSource();
cancellationToken.CancelAfter(timeout * 1000);
var downloadOpt = new DownloadConfiguration()
{
Timeout = timeout * 1000,
MaxTryAgainOnFailover = 2,
RequestConfiguration =
{
Timeout= timeout * 1000,
Proxy = webProxy
}
};
DateTime totalDatetime = DateTime.Now;
int totalSecond = 0;
var hasValue = false;
double maxSpeed = 0;
var downloader = new DownloadService(downloadOpt);
//downloader.DownloadStarted += (sender, value) =>
//{
// if (progress != null)
// {
// progress.Report("Start download data...");
// }
//};
downloader.DownloadProgressChanged += (sender, value) =>
{
TimeSpan ts = (DateTime.Now - totalDatetime);
if (progress != null && ts.Seconds > totalSecond)
{
hasValue = true;
totalSecond = ts.Seconds;
if (value.BytesPerSecondSpeed > maxSpeed)
{
maxSpeed = value.BytesPerSecondSpeed;
var speed = (maxSpeed / 1000 / 1000).ToString("#0.0");
progress.Report(speed);
}
}
};
downloader.DownloadFileCompleted += (sender, value) =>
{
if (progress != null)
{
if (!hasValue && value.Error != null)
{
progress.Report(value.Error?.Message);
}
}
};
progress.Report("......");
await downloader.DownloadFileTaskAsync(address: url, cancellationToken: cancellationToken.Token);
//var stream = await downloader.DownloadFileTaskAsync(url);
//using (StreamReader reader = new StreamReader(stream))
//{
// string text = reader.ReadToEnd();
// stream.Dispose();
//}
downloader.Dispose();
downloader = null;
downloadOpt = null;
}
}
}

View file

@ -17,7 +17,6 @@
public const string tuicCoreUrl = "https://github.com/EAimTY/tuic/releases";
public const string singboxCoreUrl = "https://github.com/SagerNet/sing-box/releases";
public const string geoUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/{0}.dat";
public const string SpeedTestUrl = @"http://cachefly.cachefly.net/10mb.test";
public const string SpeedPingTestUrl = @"https://www.google.com/generate_204";
public const string CustomRoutingListUrl = @"https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/";
@ -116,6 +115,7 @@
public static readonly List<string> TunMtus = new List<string> { "9000", "1500" };
public static readonly List<string> TunStacks = new List<string> { "gvisor", "system" };
public static readonly List<string> PresetMsgFilters = new List<string> { "^(?!.*proxy).*$", "^(?!.*direct).*$", "" };
public static readonly List<string> SpeedTestUrls = new List<string> { @"http://cachefly.cachefly.net/100mb.test", @"http://cachefly.cachefly.net/10mb.test" };
#endregion

View file

@ -150,14 +150,6 @@ namespace v2rayN.Handler
{
config.constItem = new ConstItem();
}
if (Utils.IsNullOrEmpty(config.constItem.speedTestUrl))
{
config.constItem.speedTestUrl = Global.SpeedTestUrl;
}
if (Utils.IsNullOrEmpty(config.constItem.speedPingTestUrl))
{
config.constItem.speedPingTestUrl = Global.SpeedPingTestUrl;
}
if (Utils.IsNullOrEmpty(config.constItem.defIEProxyExceptions))
{
config.constItem.defIEProxyExceptions = Global.IEProxyExceptions;
@ -167,6 +159,23 @@ namespace v2rayN.Handler
// config.remoteDNS = "1.1.1.1";
//}
if (config.speedTestItem == null)
{
config.speedTestItem = new();
}
if (config.speedTestItem.speedTestTimeout < 10)
{
config.speedTestItem.speedTestTimeout = 10;
}
if (Utils.IsNullOrEmpty(config.speedTestItem.speedTestUrl))
{
config.speedTestItem.speedTestUrl = Global.SpeedTestUrls[0];
}
if (Utils.IsNullOrEmpty(config.speedTestItem.speedPingTestUrl))
{
config.speedTestItem.speedPingTestUrl = Global.SpeedPingTestUrl;
}
if (config.statisticsFreshRate > 100 || config.statisticsFreshRate < 1)
{
config.statisticsFreshRate = 1;

View file

@ -33,20 +33,13 @@ namespace v2rayN.Handler
public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Action<bool, string> update)
{
var hasValue = false;
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
var client = new HttpClient(new SocketsHttpHandler()
{
Proxy = webProxy
});
var progress = new Progress<string>();
progress.ProgressChanged += (sender, value) =>
{
hasValue = true;
if (update != null)
{
string msg = $"{value}";
@ -54,22 +47,17 @@ namespace v2rayN.Handler
}
};
var cancellationToken = new CancellationTokenSource();
cancellationToken.CancelAfter(downloadTimeout * 1000);
await HttpClientHelper.GetInstance().DownloadDataAsync4Speed(client,
await DownloaderHelper.Instance.DownloadDataAsync4Speed(webProxy,
url,
progress,
cancellationToken.Token);
downloadTimeout);
}
catch (Exception ex)
{
if (!hasValue)
update(false, ex.Message);
if (ex.InnerException != null)
{
update(false, ex.Message);
if (ex.InnerException != null)
{
update(false, ex.InnerException.Message);
}
update(false, ex.InnerException.Message);
}
}
return 0;
@ -196,7 +184,7 @@ namespace v2rayN.Handler
try
{
var config = LazyConfig.Instance.GetConfig();
string status = GetRealPingTime(config.constItem.speedPingTestUrl, webProxy, 10, out int responseTime);
string status = GetRealPingTime(config.speedTestItem.speedPingTestUrl, webProxy, 10, out int responseTime);
bool noError = Utils.IsNullOrEmpty(status);
return noError ? responseTime : -1;
}

View file

@ -195,10 +195,10 @@ namespace v2rayN.Handler
private async Task RunSpeedTestAsync()
{
int pid = -1;
if (_actionType == ESpeedActionType.Mixedtest)
{
_selecteds = _selecteds.OrderBy(t => t.delay).ToList();
}
//if (_actionType == ESpeedActionType.Mixedtest)
//{
// _selecteds = _selecteds.OrderBy(t => t.delay).ToList();
//}
pid = _coreHandler.LoadCoreConfigString(_config, _selecteds);
if (pid < 0)
@ -207,10 +207,11 @@ namespace v2rayN.Handler
return;
}
string url = _config.constItem.speedTestUrl;
string url = _config.speedTestItem.speedTestUrl;
var timeout = _config.speedTestItem.speedTestTimeout;
DownloadHandle downloadHandle = new DownloadHandle();
var timeout = 8;
foreach (var it in _selecteds)
{
if (!it.allowTest)
@ -221,11 +222,11 @@ namespace v2rayN.Handler
{
continue;
}
if (it.delay < 0)
{
UpdateFunc(it.indexId, "", ResUI.SpeedtestingSkip);
continue;
}
//if (it.delay < 0)
//{
// UpdateFunc(it.indexId, "", ResUI.SpeedtestingSkip);
// continue;
//}
_ = LazyConfig.Instance.SetTestResult(it.indexId, "", "-1");
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
@ -250,18 +251,71 @@ namespace v2rayN.Handler
}
UpdateFunc("", ResUI.SpeedtestingCompleted);
}
private async Task RunSpeedTestMulti()
{
int pid = -1;
pid = _coreHandler.LoadCoreConfigString(_config, _selecteds);
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
return;
}
string url = _config.speedTestItem.speedTestUrl;
var timeout = _config.speedTestItem.speedTestTimeout;
DownloadHandle downloadHandle = new DownloadHandle();
foreach (var it in _selecteds)
{
if (!it.allowTest)
{
continue;
}
if (it.configType == EConfigType.Custom)
{
continue;
}
_ = LazyConfig.Instance.SetTestResult(it.indexId, "", "-1");
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item is null) continue;
WebProxy webProxy = new WebProxy(Global.Loopback, it.port);
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (bool success, string msg) =>
{
decimal.TryParse(msg, out decimal dec);
if (dec > 0)
{
_ = LazyConfig.Instance.SetTestResult(it.indexId, "", msg);
}
UpdateFunc(it.indexId, "", msg);
});
Thread.Sleep(2000);
}
Thread.Sleep((timeout + 2) * 1000);
if (pid > 0)
{
_coreHandler.CoreStopPid(pid);
}
UpdateFunc("", ResUI.SpeedtestingCompleted);
}
private async Task RunMixedtestAsync()
{
await RunRealPing();
Thread.Sleep(1000);
await RunSpeedTestAsync();
await RunSpeedTestMulti();
}
public string GetRealPingTime(DownloadHandle downloadHandle, WebProxy webProxy)
{
string status = downloadHandle.GetRealPingTime(_config.constItem.speedPingTestUrl, webProxy, 10, out int responseTime);
string status = downloadHandle.GetRealPingTime(_config.speedTestItem.speedPingTestUrl, webProxy, 10, out int responseTime);
//string output = Utils.IsNullOrEmpty(status) ? FormatOut(responseTime, "ms") : status;
return FormatOut(Utils.IsNullOrEmpty(status) ? responseTime : -1, Global.DelayUnit);
}

View file

@ -184,12 +184,12 @@ namespace v2rayN.Base
configStr = configStr.Replace("$ruleProxyIPs$", "");
configStr = configStr.Replace("$ruleProxyProcess$", "");
configStr = configStr.Replace("$ruleFinally$", "");
File.WriteAllText(Utils.GetConfigPath(_tunConfigName), configStr);
return true;
}
}
private void CoreStop()
{

View file

@ -152,6 +152,7 @@
public GrpcItem grpcItem { get; set; }
public UIItem uiItem { get; set; }
public ConstItem constItem { get; set; }
public SpeedTestItem speedTestItem { get; set; }
public List<InItem> inbound { get; set; }
public List<KeyEventItem> globalHotkeys { get; set; }
public List<CoreTypeItem> coreTypeItem { get; set; }

View file

@ -73,8 +73,6 @@ namespace v2rayN.Mode
[Serializable]
public class ConstItem
{
public string speedTestUrl { get; set; }
public string speedPingTestUrl { get; set; }
public string defIEProxyExceptions { get; set; }
}
@ -117,4 +115,14 @@ namespace v2rayN.Mode
public List<string> proxyProcess { get; set; }
}
[Serializable]
public class SpeedTestItem
{
public int speedTestTimeout { get; set; }
public string speedTestUrl { get; set; }
public string speedPingTestUrl { get; set; }
}
}

View file

@ -790,7 +790,7 @@ namespace v2rayN.Resx {
}
/// <summary>
/// 查找类似 One-click test Latency and speed (Ctrl+E) 的本地化字符串。
/// 查找类似 One-click multi test Latency and speed (Ctrl+E) 的本地化字符串。
/// </summary>
public static string menuMixedTestServer {
get {
@ -2689,6 +2689,24 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 SpeedTest Single Timeout Value 的本地化字符串。
/// </summary>
public static string TbSettingsSpeedTestTimeout {
get {
return ResourceManager.GetString("TbSettingsSpeedTestTimeout", resourceCulture);
}
}
/// <summary>
/// 查找类似 SpeedTest Url 的本地化字符串。
/// </summary>
public static string TbSettingsSpeedTestUrl {
get {
return ResourceManager.GetString("TbSettingsSpeedTestUrl", resourceCulture);
}
}
/// <summary>
/// 查找类似 Start on boot 的本地化字符串。
/// </summary>

View file

@ -1022,7 +1022,7 @@
<value>RouteOnly</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve">
<value>One-click test Latency and speed (Ctrl+E)</value>
<value>One-click multi test Latency and speed (Ctrl+E)</value>
</data>
<data name="LvTestDelay" xml:space="preserve">
<value>Delay(ms)</value>
@ -1120,4 +1120,10 @@
<data name="TbSettingsTunModeBypassModeTip" xml:space="preserve">
<value>Enable: If no route matches, the final proxy</value>
</data>
<data name="TbSettingsSpeedTestTimeout" xml:space="preserve">
<value>SpeedTest Single Timeout Value</value>
</data>
<data name="TbSettingsSpeedTestUrl" xml:space="preserve">
<value>SpeedTest Url</value>
</data>
</root>

View file

@ -1022,7 +1022,7 @@
<value>RouteOnly</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve">
<value>一键测试延迟和速度 (Ctrl+E)</value>
<value>一键多线程测试延迟和速度 (Ctrl+E)</value>
</data>
<data name="LvTestDelay" xml:space="preserve">
<value>延迟(ms)</value>
@ -1120,4 +1120,10 @@
<data name="TbSettingsTunModeBypassModeTip" xml:space="preserve">
<value>启用:路由无匹配则最终代理</value>
</data>
<data name="TbSettingsSpeedTestTimeout" xml:space="preserve">
<value>测速单个超时值</value>
</data>
<data name="TbSettingsSpeedTestUrl" xml:space="preserve">
<value>测速文件地址</value>
</data>
</root>

View file

@ -1225,7 +1225,7 @@ namespace v2rayN.ViewModels
}
private void UpdateSubscriptionProcess(string subId, bool blProxy)
{
{
(new UpdateHandle()).UpdateSubscriptionProcess(_config, subId, blProxy, UpdateTaskHandler);
}

View file

@ -63,6 +63,8 @@ namespace v2rayN.ViewModels
[Reactive] public int autoUpdateSubInterval { get; set; }
[Reactive] public int trayMenuServersLimit { get; set; }
[Reactive] public string currentFontFamily { get; set; }
[Reactive] public int SpeedTestTimeout { get; set; }
[Reactive] public string SpeedTestUrl { get; set; }
#endregion
@ -153,6 +155,8 @@ namespace v2rayN.ViewModels
autoUpdateSubInterval = _config.autoUpdateSubInterval;
trayMenuServersLimit = _config.trayMenuServersLimit;
currentFontFamily = _config.uiItem.currentFontFamily;
SpeedTestTimeout = _config.speedTestItem.speedTestTimeout;
SpeedTestUrl = _config.speedTestItem.speedTestUrl;
#endregion
@ -327,6 +331,8 @@ namespace v2rayN.ViewModels
_config.uiItem.doubleClick2Activate = DoubleClick2Activate;
_config.trayMenuServersLimit = trayMenuServersLimit;
_config.uiItem.currentFontFamily = currentFontFamily;
_config.speedTestItem.speedTestTimeout = SpeedTestTimeout;
_config.speedTestItem.speedTestUrl = SpeedTestUrl;
//systemProxy
_config.systemProxyExceptions = systemProxyExceptions;

View file

@ -478,6 +478,8 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@ -660,6 +662,7 @@
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
@ -675,6 +678,7 @@
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
@ -690,6 +694,7 @@
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
@ -714,6 +719,36 @@
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}" />
<TextBlock
Grid.Row="16"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsSpeedTestTimeout}" />
<ComboBox
x:Name="cmbSpeedTestTimeout"
Grid.Row="16"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="17"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsSpeedTestUrl}" />
<ComboBox
x:Name="cmbSpeedTestUrl"
Grid.Row="17"
Grid.Column="1"
Width="300"
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
</Grid>
</ScrollViewer>
</TabItem>

View file

@ -63,12 +63,21 @@ namespace v2rayN.Views
cmbCoreType6.Items.Add(it);
});
for (int i = 2; i <= 6; i++)
{
cmbSpeedTestTimeout.Items.Add(i * 5);
}
Global.SpeedTestUrls.ForEach(it =>
{
cmbSpeedTestUrl.Items.Add(it);
});
//fill fonts
try
{
var dir = new DirectoryInfo(Utils.GetFontsPath());
var files = dir.GetFiles("*.ttf");
var culture = _config.uiItem.currentLanguage.Equals(Global.Languages[0]) ? "zh-cn" : "en-us";
var culture = _config.uiItem.currentLanguage.Equals(Global.Languages[0]) ? "zh-cn" : "en-us";
var culture2 = "en-us";
foreach (var it in files)
{
@ -153,6 +162,8 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.autoUpdateSubInterval, v => v.txtautoUpdateSubInterval.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.trayMenuServersLimit, v => v.txttrayMenuServersLimit.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.currentFontFamily, v => v.cmbcurrentFontFamily.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables);

View file

@ -13,6 +13,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Downloader" Version="3.0.3" />
<PackageReference Include="MaterialDesignThemes" Version="4.7.1" />
<PackageReference Include="Hardcodet.NotifyIcon.Wpf" Version="1.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
@ -22,10 +23,10 @@
<PackageReference Include="sqlite-net-pcl" Version="1.8.116" />
<PackageReference Include="TaskScheduler" Version="2.10.1" />
<PackageReference Include="ZXing.Net.Bindings.Windows.Compatibility" Version="0.16.10" />
<PackageReference Include="ReactiveUI.Fody" Version="18.4.1" />
<PackageReference Include="ReactiveUI.Validation" Version="3.0.22" />
<PackageReference Include="ReactiveUI.WPF" Version="18.4.1" />
<PackageReference Include="Splat.NLog" Version="14.6.1" />
<PackageReference Include="ReactiveUI.Fody" Version="18.4.20" />
<PackageReference Include="ReactiveUI.Validation" Version="3.1.7" />
<PackageReference Include="ReactiveUI.WPF" Version="18.4.20" />
<PackageReference Include="Splat.NLog" Version="14.6.8" />
<PackageReference Include="System.Reactive" Version="5.0.0" />
</ItemGroup>