优化快速排序

This commit is contained in:
陈国伟 2021-11-18 16:02:44 +08:00
parent 9d36677428
commit bf3bd5c909
3 changed files with 20 additions and 14 deletions

View File

@ -1,6 +1,6 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Version>2.0.8</Version> <Version>2.0.9</Version>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<IsWebConfigTransformDisabled>true</IsWebConfigTransformDisabled> <IsWebConfigTransformDisabled>true</IsWebConfigTransformDisabled>

View File

@ -61,14 +61,15 @@ namespace FastGithub.DomainResolve
/// 解析域名 /// 解析域名
/// </summary> /// </summary>
/// <param name="endPoint">远程结节</param> /// <param name="endPoint">远程结节</param>
/// <param name="fastSort">是否使用快速排序</param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
public async IAsyncEnumerable<IPAddress> ResolveAsync(DnsEndPoint endPoint, [EnumeratorCancellation] CancellationToken cancellationToken) public async IAsyncEnumerable<IPAddress> ResolveAsync(DnsEndPoint endPoint, bool fastSort, [EnumeratorCancellation] CancellationToken cancellationToken)
{ {
var hashSet = new HashSet<IPAddress>(); var hashSet = new HashSet<IPAddress>();
foreach (var dns in this.GetDnsServers()) foreach (var dns in this.GetDnsServers())
{ {
var addresses = await this.LookupAsync(dns, endPoint, cancellationToken); var addresses = await this.LookupAsync(dns, endPoint, fastSort, cancellationToken);
foreach (var address in addresses) foreach (var address in addresses)
{ {
if (hashSet.Add(address) == true) if (hashSet.Add(address) == true)
@ -106,9 +107,10 @@ namespace FastGithub.DomainResolve
/// </summary> /// </summary>
/// <param name="dns"></param> /// <param name="dns"></param>
/// <param name="endPoint"></param> /// <param name="endPoint"></param>
/// <param name="fastSort"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
private async Task<IPAddress[]> LookupAsync(IPEndPoint dns, DnsEndPoint endPoint, CancellationToken cancellationToken = default) private async Task<IPAddress[]> LookupAsync(IPEndPoint dns, DnsEndPoint endPoint, bool fastSort, CancellationToken cancellationToken = default)
{ {
var key = $"{dns}/{endPoint}"; var key = $"{dns}/{endPoint}";
var semaphore = this.semaphoreSlims.GetOrAdd(key, _ => new SemaphoreSlim(1, 1)); var semaphore = this.semaphoreSlims.GetOrAdd(key, _ => new SemaphoreSlim(1, 1));
@ -121,7 +123,7 @@ namespace FastGithub.DomainResolve
return value; return value;
} }
var result = await this.LookupCoreAsync(dns, endPoint, cancellationToken); var result = await this.LookupCoreAsync(dns, endPoint, fastSort, cancellationToken);
this.dnsCache.Set(key, result.Addresses, result.TimeToLive); this.dnsCache.Set(key, result.Addresses, result.TimeToLive);
return result.Addresses; return result.Addresses;
} }
@ -146,9 +148,10 @@ namespace FastGithub.DomainResolve
/// </summary> /// </summary>
/// <param name="dns"></param> /// <param name="dns"></param>
/// <param name="endPoint"></param> /// <param name="endPoint"></param>
/// <param name="fastSort"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
private async Task<LookupResult> LookupCoreAsync(IPEndPoint dns, DnsEndPoint endPoint, CancellationToken cancellationToken = default) private async Task<LookupResult> LookupCoreAsync(IPEndPoint dns, DnsEndPoint endPoint, bool fastSort, CancellationToken cancellationToken = default)
{ {
if (endPoint.Host == LOCALHOST) if (endPoint.Host == LOCALHOST)
{ {
@ -170,7 +173,7 @@ namespace FastGithub.DomainResolve
return new LookupResult(addresses, this.minTimeToLive); return new LookupResult(addresses, this.minTimeToLive);
} }
if (addresses.Length > 1) if (fastSort && addresses.Length > 1)
{ {
addresses = await OrderByConnectAnyAsync(addresses, endPoint.Port, cancellationToken); addresses = await OrderByConnectAnyAsync(addresses, endPoint.Port, cancellationToken);
} }
@ -237,8 +240,13 @@ namespace FastGithub.DomainResolve
/// <returns></returns> /// <returns></returns>
private static async Task<IPAddress[]> OrderByConnectAnyAsync(IPAddress[] addresses, int port, CancellationToken cancellationToken) private static async Task<IPAddress[]> OrderByConnectAnyAsync(IPAddress[] addresses, int port, CancellationToken cancellationToken)
{ {
var tasks = addresses.Select(address => ConnectAsync(address, port, cancellationToken)); using var controlTokenSource = new CancellationTokenSource(connectTimeout);
var fastestAddress = await await Task.WhenAny(tasks); using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, controlTokenSource.Token);
var connectTasks = addresses.Select(address => ConnectAsync(address, port, linkedTokenSource.Token));
var fastestAddress = await await Task.WhenAny(connectTasks);
controlTokenSource.Cancel();
if (fastestAddress == null) if (fastestAddress == null)
{ {
return addresses; return addresses;
@ -266,10 +274,8 @@ namespace FastGithub.DomainResolve
{ {
try try
{ {
using var timeoutTokenSource = new CancellationTokenSource(connectTimeout);
using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token);
using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp); using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
await socket.ConnectAsync(address, port, linkedTokenSource.Token); await socket.ConnectAsync(address, port, cancellationToken);
return address; return address;
} }
catch (Exception) catch (Exception)

View File

@ -65,7 +65,7 @@ namespace FastGithub.DomainResolve
else else
{ {
this.dnsEndPointAddressElapseds.TryAdd(endPoint, IPAddressElapsedCollection.Empty); this.dnsEndPointAddressElapseds.TryAdd(endPoint, IPAddressElapsedCollection.Empty);
await foreach (var adddress in this.dnsClient.ResolveAsync(endPoint, cancellationToken)) await foreach (var adddress in this.dnsClient.ResolveAsync(endPoint, fastSort: true, cancellationToken))
{ {
this.logger.LogInformation($"{endPoint.Host}->{adddress}"); this.logger.LogInformation($"{endPoint.Host}->{adddress}");
yield return adddress; yield return adddress;
@ -86,7 +86,7 @@ namespace FastGithub.DomainResolve
{ {
var dnsEndPoint = keyValue.Key; var dnsEndPoint = keyValue.Key;
var addresses = new List<IPAddress>(); var addresses = new List<IPAddress>();
await foreach (var adddress in this.dnsClient.ResolveAsync(dnsEndPoint, cancellationToken)) await foreach (var adddress in this.dnsClient.ResolveAsync(dnsEndPoint, fastSort: false, cancellationToken))
{ {
addresses.Add(adddress); addresses.Add(adddress);
} }