소스 검색

优化快速排序

陈国伟 3 년 전
부모
커밋
bf3bd5c909
3개의 변경된 파일20개의 추가작업 그리고 14개의 파일을 삭제
  1. 1 1
      Directory.Build.props
  2. 17 11
      FastGithub.DomainResolve/DnsClient.cs
  3. 2 2
      FastGithub.DomainResolve/DomainResolver.cs

+ 1 - 1
Directory.Build.props

@@ -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> 		

+ 17 - 11
FastGithub.DomainResolve/DnsClient.cs

@@ -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));
-            var fastestAddress = await await Task.WhenAny(tasks);
+            using var controlTokenSource = new CancellationTokenSource(connectTimeout);
+            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)

+ 2 - 2
FastGithub.DomainResolve/DomainResolver.cs

@@ -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);
                     }
                     }