From 0b3d794738df1e333b1cf2400d56af839a57b975 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 22 Nov 2025 09:14:28 +0800 Subject: [PATCH 1/8] =?UTF-8?q?refactor:=20Search(uint)=20=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E6=A0=87=E8=AE=B0=E8=BF=87=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- binding/csharp/IP2Region.Net/Abstractions/ISearcher.cs | 1 + binding/csharp/IP2Region.Net/XDB/Searcher.cs | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/binding/csharp/IP2Region.Net/Abstractions/ISearcher.cs b/binding/csharp/IP2Region.Net/Abstractions/ISearcher.cs index 89cd5e5..657716f 100644 --- a/binding/csharp/IP2Region.Net/Abstractions/ISearcher.cs +++ b/binding/csharp/IP2Region.Net/Abstractions/ISearcher.cs @@ -30,6 +30,7 @@ public interface ISearcher /// 搜索方法 仅限 IPv4 使用 /// /// IPv4 地址字节数组小端读取 uint 数值 + [Obsolete("已弃用,请改用其他方法;Deprecated; please use Search(string) or Search(IPAddress) method.")] string? Search(uint ipAddress); /// diff --git a/binding/csharp/IP2Region.Net/XDB/Searcher.cs b/binding/csharp/IP2Region.Net/XDB/Searcher.cs index 2f0eadb..c631b31 100644 --- a/binding/csharp/IP2Region.Net/XDB/Searcher.cs +++ b/binding/csharp/IP2Region.Net/XDB/Searcher.cs @@ -9,6 +9,7 @@ using IP2Region.Net.Abstractions; using IP2Region.Net.Internal; using IP2Region.Net.Internal.Abstractions; using System.Buffers.Binary; +using System.Diagnostics.CodeAnalysis; using System.Net; using System.Text; @@ -47,14 +48,13 @@ public class Searcher : ISearcher /// /// /// - public string? Search(IPAddress ipAddress) - { - return SearchCore(ipAddress.GetAddressBytes()); - } + public string? Search(IPAddress ipAddress) => SearchCore(ipAddress.GetAddressBytes()); /// /// /// + [Obsolete("已弃用,请改用其他方法;Deprecated; please use Search(string) or Search(IPAddress) method.")] + [ExcludeFromCodeCoverage] public string? Search(uint ipAddress) { var bytes = BitConverter.GetBytes(ipAddress); From 33f8bf766d1360526f07f3407ec228671280bc5d Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 22 Nov 2025 09:14:34 +0800 Subject: [PATCH 2/8] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- binding/csharp/IP2Region.Net.Test/SearcherTest.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/binding/csharp/IP2Region.Net.Test/SearcherTest.cs b/binding/csharp/IP2Region.Net.Test/SearcherTest.cs index da9f840..1c85420 100644 --- a/binding/csharp/IP2Region.Net.Test/SearcherTest.cs +++ b/binding/csharp/IP2Region.Net.Test/SearcherTest.cs @@ -110,10 +110,6 @@ public class SearcherTest var ipAddress = IPAddress.Parse(ipStr); var region = fileSearcher.Search(ipAddress); Assert.Equal(expected, region); - - var ip = XDB.Util.IpAddressToUInt32(ipAddress); - region = fileSearcher.Search(ip); - Assert.Equal(expected, region); } [Theory] From 0b3635b3c35e1cf6d4112ca55f224c3f058bef63 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 22 Nov 2025 12:53:02 +0800 Subject: [PATCH 3/8] =?UTF-8?q?refactor:=20=E4=BD=BF=E7=94=A8=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E4=BB=A3=E6=9B=BF=E8=99=9A=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Abstractions/AbstractCacheStrategy.cs | 54 ------------------- .../Internal/CacheStrategyFactory.cs | 5 +- .../Internal/ContentCacheStrategy.cs | 8 +-- .../Internal/FileCacheStrategy.cs | 52 +++++++++++++++++- .../IP2Region.Net/Internal/ICacheStrategy.cs | 19 +++++++ .../Internal/VectorIndexCacheStrategy.cs | 9 +--- binding/csharp/IP2Region.Net/XDB/Searcher.cs | 21 +++----- 7 files changed, 82 insertions(+), 86 deletions(-) delete mode 100644 binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs create mode 100644 binding/csharp/IP2Region.Net/Internal/ICacheStrategy.cs diff --git a/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs deleted file mode 100644 index 909f75c..0000000 --- a/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2025 The Ip2Region Authors. All rights reserved. -// Use of this source code is governed by a Apache2.0-style -// license that can be found in the LICENSE file. -// @Author Alan -// @Date 2023/07/25 -// Updated by Argo Zhang at 2025/11/21 - -using System.Buffers; - -namespace IP2Region.Net.Internal.Abstractions; - -internal abstract class AbstractCacheStrategy(string xdbPath) -{ - protected const int HeaderInfoLength = 256; - protected const int VectorIndexSize = 8; - - private const int BufferSize = 64 * 1024; - - public int IoCount { get; private set; } - - protected FileStream XdbFileStream = new(xdbPath, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, FileOptions.RandomAccess); - - public void ResetIoCount() - { - IoCount = 0; - } - - public virtual ReadOnlyMemory GetVectorIndex(int offset) => GetData(HeaderInfoLength + offset, VectorIndexSize); - - public virtual ReadOnlyMemory GetData(long offset, int length) - { - byte[] buffer = ArrayPool.Shared.Rent(length); - int totalBytesRead = 0; - try - { - XdbFileStream.Seek(offset, SeekOrigin.Begin); - - int bytesRead; - while (totalBytesRead < length) - { - bytesRead = XdbFileStream.Read(buffer, totalBytesRead, length); - totalBytesRead += bytesRead; - - IoCount++; - } - } - finally - { - ArrayPool.Shared.Return(buffer); - } - - return new ReadOnlyMemory(buffer, 0, totalBytesRead); - } -} diff --git a/binding/csharp/IP2Region.Net/Internal/CacheStrategyFactory.cs b/binding/csharp/IP2Region.Net/Internal/CacheStrategyFactory.cs index 084a3d0..ae9b01d 100644 --- a/binding/csharp/IP2Region.Net/Internal/CacheStrategyFactory.cs +++ b/binding/csharp/IP2Region.Net/Internal/CacheStrategyFactory.cs @@ -5,14 +5,13 @@ // @Date 2023/07/25 // Updated by Argo Zhang at 2025/11/21 -using IP2Region.Net.Internal.Abstractions; using IP2Region.Net.XDB; namespace IP2Region.Net.Internal; -class CacheStrategyFactory(string xdbPath) +static class CacheStrategyFactory { - public AbstractCacheStrategy CreateCacheStrategy(CachePolicy cachePolicy) => cachePolicy switch + public static ICacheStrategy CreateCacheStrategy(CachePolicy cachePolicy, string xdbPath) => cachePolicy switch { CachePolicy.Content => new ContentCacheStrategy(xdbPath), CachePolicy.VectorIndex => new VectorIndexCacheStrategy(xdbPath), diff --git a/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs index 135751d..693518e 100644 --- a/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs @@ -5,20 +5,16 @@ // @Date 2023/07/25 // Updated by Argo Zhang at 2025/11/21 -using IP2Region.Net.Internal.Abstractions; - namespace IP2Region.Net.Internal; -class ContentCacheStrategy : AbstractCacheStrategy +class ContentCacheStrategy : FileCacheStrategy { private readonly ReadOnlyMemory _cacheData; public ContentCacheStrategy(string xdbPath) : base(xdbPath) { _cacheData = base.GetData(0, (int)XdbFileStream.Length); - XdbFileStream.Close(); - XdbFileStream.Dispose(); } - public override ReadOnlyMemory GetData(long offset = 0, int length = 0) => _cacheData.Slice((int)offset, length); + public override ReadOnlyMemory GetData(long offset, int length) => _cacheData.Slice((int)offset, length); } diff --git a/binding/csharp/IP2Region.Net/Internal/FileCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/FileCacheStrategy.cs index 2a69364..224976a 100644 --- a/binding/csharp/IP2Region.Net/Internal/FileCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/FileCacheStrategy.cs @@ -5,11 +5,59 @@ // @Date 2023/07/25 // Updated by Argo Zhang at 2025/11/21 -using IP2Region.Net.Internal.Abstractions; +using System.Buffers; namespace IP2Region.Net.Internal; -class FileCacheStrategy(string xdbPath) : AbstractCacheStrategy(xdbPath) +class FileCacheStrategy(string xdbPath) : ICacheStrategy { + protected const int HeaderInfoLength = 256; + protected const int VectorIndexSize = 8; + protected const int BufferSize = 64 * 1024; + + protected FileStream XdbFileStream = new(xdbPath, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, FileOptions.RandomAccess); + + public int IoCount { get; set; } + + public void ResetIoCount() + { + IoCount = 0; + } + + public virtual ReadOnlyMemory GetVectorIndex(int offset) => GetData(HeaderInfoLength + offset, VectorIndexSize); + + public virtual ReadOnlyMemory GetData(long offset, int length) + { + var buffer = ArrayPool.Shared.Rent(length); + try + { + int totalBytesRead = 0; + XdbFileStream.Seek(offset, SeekOrigin.Begin); + + int bytesRead; + while (totalBytesRead < length) + { + bytesRead = XdbFileStream.Read(buffer, totalBytesRead, length - totalBytesRead); + if (bytesRead == 0) + { + break; + } + + totalBytesRead += bytesRead; + IoCount++; + } + + var ret = new byte[totalBytesRead]; + if (totalBytesRead > 0) + { + Array.Copy(buffer, 0, ret, 0, totalBytesRead); + } + return ret; + } + finally + { + ArrayPool.Shared.Return(buffer); + } + } } diff --git a/binding/csharp/IP2Region.Net/Internal/ICacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/ICacheStrategy.cs new file mode 100644 index 0000000..0f01d4c --- /dev/null +++ b/binding/csharp/IP2Region.Net/Internal/ICacheStrategy.cs @@ -0,0 +1,19 @@ +// Copyright 2025 The Ip2Region Authors. All rights reserved. +// Use of this source code is governed by a Apache2.0-style +// license that can be found in the LICENSE file. +// @Author Alan +// @Date 2023/07/25 +// Updated by Argo Zhang at 2025/11/21 + +namespace IP2Region.Net.Internal; + +internal interface ICacheStrategy +{ + int IoCount { get; } + + void ResetIoCount(); + + ReadOnlyMemory GetVectorIndex(int offset); + + ReadOnlyMemory GetData(long offset, int length); +} diff --git a/binding/csharp/IP2Region.Net/Internal/VectorIndexCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/VectorIndexCacheStrategy.cs index b5abc17..c7bdaf1 100644 --- a/binding/csharp/IP2Region.Net/Internal/VectorIndexCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/VectorIndexCacheStrategy.cs @@ -5,11 +5,9 @@ // @Date 2023/07/25 // Updated by Argo Zhang at 2025/11/21 -using IP2Region.Net.Internal.Abstractions; - namespace IP2Region.Net.Internal; -class VectorIndexCacheStrategy : AbstractCacheStrategy +class VectorIndexCacheStrategy : FileCacheStrategy { private const int VectorIndexRows = 256; private const int VectorIndexCols = 256; @@ -18,10 +16,7 @@ class VectorIndexCacheStrategy : AbstractCacheStrategy public VectorIndexCacheStrategy(string xdbPath) : base(xdbPath) { - XdbFileStream.Seek(HeaderInfoLength, SeekOrigin.Begin); - var buffer = new byte[VectorIndexRows * VectorIndexCols * VectorIndexSize]; - var length = XdbFileStream.Read(buffer, 0, buffer.Length); - _vectorCache = new ReadOnlyMemory(buffer); + _vectorCache = GetData(HeaderInfoLength, VectorIndexRows * VectorIndexCols * VectorIndexSize); } public override ReadOnlyMemory GetVectorIndex(int offset) => _vectorCache.Slice(offset, VectorIndexSize); diff --git a/binding/csharp/IP2Region.Net/XDB/Searcher.cs b/binding/csharp/IP2Region.Net/XDB/Searcher.cs index c631b31..81186b5 100644 --- a/binding/csharp/IP2Region.Net/XDB/Searcher.cs +++ b/binding/csharp/IP2Region.Net/XDB/Searcher.cs @@ -7,7 +7,6 @@ using IP2Region.Net.Abstractions; using IP2Region.Net.Internal; -using IP2Region.Net.Internal.Abstractions; using System.Buffers.Binary; using System.Diagnostics.CodeAnalysis; using System.Net; @@ -18,24 +17,18 @@ namespace IP2Region.Net.XDB; /// /// 实现类 /// -public class Searcher : ISearcher +/// +/// +/// +public class Searcher(CachePolicy cachePolicy, string xdbPath) : ISearcher { - private readonly AbstractCacheStrategy _cacheStrategy; + private readonly ICacheStrategy _cacheStrategy = CacheStrategyFactory.CreateCacheStrategy(cachePolicy, xdbPath); /// /// /// public int IoCount => _cacheStrategy.IoCount; - /// - /// - /// - public Searcher(CachePolicy cachePolicy, string dbPath) - { - var factory = new CacheStrategyFactory(dbPath); - _cacheStrategy = factory.CreateCacheStrategy(cachePolicy); - } - /// /// /// @@ -93,7 +86,7 @@ public class Searcher : ISearcher { int m = (int)(l + h) >> 1; - var p = (int)sPtr + m * indexSize; + var p = sPtr + m * indexSize; var buff = _cacheStrategy.GetData(p, indexSize); var s = buff.Span.Slice(0, length); @@ -114,7 +107,7 @@ public class Searcher : ISearcher } } - var regionBuff = _cacheStrategy.GetData((int)dataPtr, dataLen); + var regionBuff = _cacheStrategy.GetData(dataPtr, dataLen); return Encoding.UTF8.GetString(regionBuff.Span.ToArray()); } From 5b8b47df5e8eae634ad85460f0054187c907620e Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 22 Nov 2025 12:53:22 +0800 Subject: [PATCH 4/8] =?UTF-8?q?perf:=20=E5=A2=9E=E5=8A=A0=E9=A2=84?= =?UTF-8?q?=E7=83=AD=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- binding/csharp/IP2Region.Net.BenchMark/Benmarks.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/binding/csharp/IP2Region.Net.BenchMark/Benmarks.cs b/binding/csharp/IP2Region.Net.BenchMark/Benmarks.cs index eabf368..c3a23e7 100644 --- a/binding/csharp/IP2Region.Net.BenchMark/Benmarks.cs +++ b/binding/csharp/IP2Region.Net.BenchMark/Benmarks.cs @@ -10,6 +10,7 @@ using IP2Region.Net.XDB; namespace IP2Region.Net.BenchMark; +[MemoryDiagnoser] public class Benchmarks { private static readonly string XdbPathV4 = Path.Combine(AppContext.BaseDirectory, "IP2Region", "ip2region_v4.xdb"); @@ -24,6 +25,17 @@ public class Benchmarks private readonly string _testIPv4Address = "114.114.114.114"; private readonly string _testIPv6Address = "240e:3b7:3272:d8d0:db09:c067:8d59:539e"; + public Benchmarks() + { + _contentV4Searcher.Search(_testIPv4Address); + _vectorV4Searcher.Search(_testIPv4Address); + _fileV4Searcher.Search(_testIPv4Address); + + _contentV6Searcher.Search(_testIPv6Address); + _vectorV6Searcher.Search(_testIPv6Address); + _fileV6Searcher.Search(_testIPv6Address); + } + [Benchmark] [BenchmarkCategory("IPv4")] public void ContentIPv4() => _contentV4Searcher.Search(_testIPv4Address); From 7612e679fb0625464e4021e0cab466761f05cbbc Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 22 Nov 2025 13:04:38 +0800 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20IDispose=20?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=BF=9D=E8=AF=81=E9=87=8A=E6=94=BE=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=8F=A5=E6=9F=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../csharp/IP2Region.Net.Test/SearcherTest.cs | 6 +++++ .../IP2Region.Net/Abstractions/ISearcher.cs | 2 +- .../Internal/ContentCacheStrategy.cs | 7 ++++++ .../Internal/FileCacheStrategy.cs | 22 +++++++++++++++++++ .../IP2Region.Net/Internal/ICacheStrategy.cs | 2 +- binding/csharp/IP2Region.Net/XDB/Searcher.cs | 9 ++++++++ 6 files changed, 46 insertions(+), 2 deletions(-) diff --git a/binding/csharp/IP2Region.Net.Test/SearcherTest.cs b/binding/csharp/IP2Region.Net.Test/SearcherTest.cs index 1c85420..46ba960 100644 --- a/binding/csharp/IP2Region.Net.Test/SearcherTest.cs +++ b/binding/csharp/IP2Region.Net.Test/SearcherTest.cs @@ -78,6 +78,8 @@ public class SearcherTest searcher.Search("58.251.27.201"); Assert.Equal(3, searcher.IoCount); + + searcher.Dispose(); } [Fact] @@ -89,6 +91,8 @@ public class SearcherTest searcher.Search("58.251.27.201"); Assert.Equal(2, searcher.IoCount); + + searcher.Dispose(); } [Fact] @@ -100,6 +104,8 @@ public class SearcherTest searcher.Search("58.251.27.201"); Assert.Equal(0, searcher.IoCount); + + searcher.Dispose(); } [Theory] diff --git a/binding/csharp/IP2Region.Net/Abstractions/ISearcher.cs b/binding/csharp/IP2Region.Net/Abstractions/ISearcher.cs index 657716f..b8cf052 100644 --- a/binding/csharp/IP2Region.Net/Abstractions/ISearcher.cs +++ b/binding/csharp/IP2Region.Net/Abstractions/ISearcher.cs @@ -12,7 +12,7 @@ namespace IP2Region.Net.Abstractions; /// /// IP 转化为地理位置搜索器接口 /// -public interface ISearcher +public interface ISearcher : IDisposable { /// /// 搜索方法 diff --git a/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs index 693518e..020a959 100644 --- a/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs @@ -14,7 +14,14 @@ class ContentCacheStrategy : FileCacheStrategy public ContentCacheStrategy(string xdbPath) : base(xdbPath) { _cacheData = base.GetData(0, (int)XdbFileStream.Length); + XdbFileStream.Close(); + XdbFileStream.Dispose(); } public override ReadOnlyMemory GetData(long offset, int length) => _cacheData.Slice((int)offset, length); + + protected override void Dispose(bool disposing) + { + base.Dispose(false); + } } diff --git a/binding/csharp/IP2Region.Net/Internal/FileCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/FileCacheStrategy.cs index 224976a..00310e1 100644 --- a/binding/csharp/IP2Region.Net/Internal/FileCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/FileCacheStrategy.cs @@ -60,4 +60,26 @@ class FileCacheStrategy(string xdbPath) : ICacheStrategy ArrayPool.Shared.Return(buffer); } } + + /// + /// 释放文件句柄 + /// + /// + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + XdbFileStream.Close(); + XdbFileStream.Dispose(); + } + } + + /// + /// + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } } diff --git a/binding/csharp/IP2Region.Net/Internal/ICacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/ICacheStrategy.cs index 0f01d4c..3d05b31 100644 --- a/binding/csharp/IP2Region.Net/Internal/ICacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/ICacheStrategy.cs @@ -7,7 +7,7 @@ namespace IP2Region.Net.Internal; -internal interface ICacheStrategy +internal interface ICacheStrategy : IDisposable { int IoCount { get; } diff --git a/binding/csharp/IP2Region.Net/XDB/Searcher.cs b/binding/csharp/IP2Region.Net/XDB/Searcher.cs index 81186b5..abccb75 100644 --- a/binding/csharp/IP2Region.Net/XDB/Searcher.cs +++ b/binding/csharp/IP2Region.Net/XDB/Searcher.cs @@ -147,4 +147,13 @@ public class Searcher(CachePolicy cachePolicy, string xdbPath) : ISearcher } return ret; } + + /// + /// + /// + public void Dispose() + { + _cacheStrategy.Dispose(); + GC.SuppressFinalize(this); + } } From b3c2d40588feb00b6016e001c05d32e1ddbaf76b Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 22 Nov 2025 13:10:24 +0800 Subject: [PATCH 6/8] =?UTF-8?q?doc:=20=E5=8E=8B=E5=8A=9B=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=BB=93=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- binding/csharp/README.md | 49 +++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/binding/csharp/README.md b/binding/csharp/README.md index 5f1db40..ab3c1b4 100644 --- a/binding/csharp/README.md +++ b/binding/csharp/README.md @@ -24,6 +24,7 @@ ISearcher searcher = new Searcher(CachePolicy , "your xdb file path"); | CachePolicy.Content | Cache the entire `xdb` data. | Yes | | CachePolicy.VectorIndex | Cache `vecotorIndex` to speed up queries and reduce system io pressure by reducing one fixed IO operation. | Yes | | CachePolicy.File | Completely file-based queries | Yes | + ### XDB File Description Generate using [maker](https://github.com/lionsoul2014/ip2region/tree/master/maker/csharp), or [download](https://github.com/lionsoul2014/ip2region/blob/master/data/ip2region.xdb) pre-generated xdb files @@ -47,15 +48,47 @@ provider.GetRequiredKeyedService("IP2Region.Net"); netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0;net9.0;net10.0 ## Performance +// * Summary * -| Method | Mean | Error | StdDev | Median | -|------------ |------------:|----------:|------------:|------------:| -| ContentIPv4 | 101.5 ns | 2.04 ns | 4.57 ns | 103.1 ns | -| VectorIPv4 | 7,488.1 ns | 222.91 ns | 657.26 ns | 7,819.2 ns | -| FileIPv4 | 11,686.9 ns | 59.81 ns | 55.95 ns | 11,707.6 ns | -| ContentIPv6 | 296.1 ns | 1.84 ns | 1.72 ns | 296.2 ns | -| VectorIPv6 | 15,025.1 ns | 938.17 ns | 2,766.21 ns | 16,642.9 ns | -| FileIPv6 | 19,721.0 ns | 807.55 ns | 2,381.08 ns | 20,905.7 ns | +BenchmarkDotNet v0.15.6, Windows 11 (10.0.26200.7171) +13th Gen Intel Core i7-13700 2.10GHz, 1 CPU, 24 logical and 16 physical cores +.NET SDK 10.0.100 + [Host] : .NET 10.0.0 (10.0.0, 10.0.25.52411), X64 RyuJIT x86-64-v3 + DefaultJob : .NET 10.0.0 (10.0.0, 10.0.25.52411), X64 RyuJIT x86-64-v3 + + +| Method | Mean | Error | StdDev | Gen0 | Allocated | +|------------ |-------------:|-----------:|-----------:|-------:|----------:| +| ContentIPv4 | 53.70 ns | 0.296 ns | 0.277 ns | 0.0086 | 136 B | +| VectorIPv4 | 4,446.04 ns | 18.673 ns | 15.593 ns | 0.0076 | 232 B | +| FileIPv4 | 6,712.40 ns | 15.718 ns | 13.934 ns | 0.0153 | 264 B | +| ContentIPv6 | 145.53 ns | 0.331 ns | 0.277 ns | 0.0126 | 200 B | +| VectorIPv6 | 7,058.39 ns | 125.505 ns | 117.398 ns | 0.0381 | 712 B | +| FileIPv6 | 10,657.97 ns | 53.907 ns | 50.425 ns | 0.0458 | 744 B | + +// * Hints * +Outliers + Benchmarks.VectorIPv4: Default -> 2 outliers were removed (4.55 us, 4.58 us) + Benchmarks.FileIPv4: Default -> 1 outlier was removed (6.79 us) + Benchmarks.ContentIPv6: Default -> 2 outliers were removed (148.08 ns, 152.27 ns) + +// * Legends * + Mean : Arithmetic mean of all measurements + Error : Half of 99.9% confidence interval + StdDev : Standard deviation of all measurements + Gen0 : GC Generation 0 collects per 1000 operations + Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B) + 1 ns : 1 Nanosecond (0.000000001 sec) + +// * Diagnostic Output - MemoryDiagnoser * + + +// ***** BenchmarkRunner: End ***** +Run time: 00:02:06 (126.09 sec), executed benchmarks: 6 + +Global total time: 00:02:13 (133.47 sec), executed benchmarks: 6 +// * Artifacts cleanup * +Artifacts cleanup is finished ## Contributing Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. From c0f0efdb953a48703bae157afc1f1c2a664a560e Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 22 Nov 2025 18:49:40 +0800 Subject: [PATCH 7/8] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7=E4=B8=BA=203.0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- binding/csharp/IP2Region.Net/IP2Region.Net.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/binding/csharp/IP2Region.Net/IP2Region.Net.csproj b/binding/csharp/IP2Region.Net/IP2Region.Net.csproj index 83901fe..4f693d6 100644 --- a/binding/csharp/IP2Region.Net/IP2Region.Net.csproj +++ b/binding/csharp/IP2Region.Net/IP2Region.Net.csproj @@ -2,9 +2,9 @@ IP2Region.Net - 2.1.1 + 3.0.0 IP2Region.Net - Alan Lee + Alan Lee;Argo Zhang(argo@live.ca) Apache-2.0 README.md https://github.com/lionsoul2014/ip2region/tree/master/binding/csharp From 23ae923cff88cda617f22e9fcac99c0c6cd5dde6 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 22 Nov 2025 18:49:57 +0800 Subject: [PATCH 8/8] =?UTF-8?q?doc:=20=E6=9B=B4=E6=96=B0=20CHANGELOG=20?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- binding/csharp/CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/binding/csharp/CHANGELOG.md b/binding/csharp/CHANGELOG.md index 7dd8005..473b68d 100644 --- a/binding/csharp/CHANGELOG.md +++ b/binding/csharp/CHANGELOG.md @@ -2,7 +2,10 @@ All notable changes to this project will be documented in this file. -## [Unreleased] +## [3.0.0] - 2025-11-22 +- 支持 .NET 10.0 +- 增加 IPv6 支持 +- 修复若干 bug ## [2.0.1] - 2023-07-30 @@ -18,4 +21,4 @@ All notable changes to this project will be documented in this file. ### Added - Dependent file query policies CachePolicy.VectorIndex, CachePolicy.File support thread-safe concurrent queries -- Dramatically optimizes overall performance \ No newline at end of file +- Dramatically optimizes overall performance