From 426038b3fea89c028e86798ef2826d2873ff35e2 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 21 Nov 2025 15:46:09 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IP2Region.Net.BenchMark/Benmarks.cs | 44 +++++++++---------- .../csharp/IP2Region.Net.Test/SearcherTest.cs | 22 +++++----- .../Abstractions/AbstractCacheStrategy.cs | 32 ++++++-------- .../Internal/CacheStrategyFactory.cs | 2 +- .../Internal/ContentCacheStrategy.cs | 10 ++--- .../Internal/VectorIndexCacheStrategy.cs | 11 +++-- binding/csharp/IP2Region.Net/XDB/Searcher.cs | 11 ++--- 7 files changed, 63 insertions(+), 69 deletions(-) diff --git a/binding/csharp/IP2Region.Net.BenchMark/Benmarks.cs b/binding/csharp/IP2Region.Net.BenchMark/Benmarks.cs index f5eb2fd..eabf368 100644 --- a/binding/csharp/IP2Region.Net.BenchMark/Benmarks.cs +++ b/binding/csharp/IP2Region.Net.BenchMark/Benmarks.cs @@ -14,37 +14,37 @@ public class Benchmarks { private static readonly string XdbPathV4 = Path.Combine(AppContext.BaseDirectory, "IP2Region", "ip2region_v4.xdb"); private static readonly string XdbPathV6 = Path.Combine(AppContext.BaseDirectory, "IP2Region", "ip2region_v6.xdb"); - private static readonly Searcher _contentV4Searcher = new Searcher(CachePolicy.Content, XdbPathV4); - private static readonly Searcher _vectorV4Searcher = new Searcher(CachePolicy.VectorIndex, XdbPathV4); - private static readonly Searcher _fileV4Searcher = new Searcher(CachePolicy.File, XdbPathV4); - private static readonly Searcher _contentV6Searcher = new Searcher(CachePolicy.Content, XdbPathV6); - private static readonly Searcher _vectorV6Searcher = new Searcher(CachePolicy.VectorIndex, XdbPathV6); - private static readonly Searcher _fileV6Searcher = new Searcher(CachePolicy.File, XdbPathV6); + private static readonly Searcher _contentV4Searcher = new(CachePolicy.Content, XdbPathV4); + private static readonly Searcher _vectorV4Searcher = new(CachePolicy.VectorIndex, XdbPathV4); + private static readonly Searcher _fileV4Searcher = new(CachePolicy.File, XdbPathV4); + private static readonly Searcher _contentV6Searcher = new(CachePolicy.Content, XdbPathV6); + private static readonly Searcher _vectorV6Searcher = new(CachePolicy.VectorIndex, XdbPathV6); + private static readonly Searcher _fileV6Searcher = new(CachePolicy.File, XdbPathV6); - private readonly string _testIpV4Address = "114.114.114.114"; - private readonly string _testIpV6Address = "240e:3b7:3272:d8d0:db09:c067:8d59:539e"; + private readonly string _testIPv4Address = "114.114.114.114"; + private readonly string _testIPv6Address = "240e:3b7:3272:d8d0:db09:c067:8d59:539e"; [Benchmark] - [BenchmarkCategory(nameof(CachePolicy.Content))] - public void ContentIpV4() => _contentV4Searcher.Search(_testIpV4Address); - - //[Benchmark] - [BenchmarkCategory(nameof(CachePolicy.VectorIndex))] - public void VectorIndexIpV4() => _vectorV4Searcher.Search(_testIpV4Address); + [BenchmarkCategory("IPv4")] + public void ContentIPv4() => _contentV4Searcher.Search(_testIPv4Address); [Benchmark] - [BenchmarkCategory(nameof(CachePolicy.File))] - public void FileIpV4() => _fileV4Searcher.Search(_testIpV4Address); + [BenchmarkCategory("IPv4")] + public void VectorIPv4() => _vectorV4Searcher.Search(_testIPv4Address); [Benchmark] - [BenchmarkCategory(nameof(CachePolicy.Content))] - public void ContentIpV6() => _contentV6Searcher.Search(_testIpV6Address); + [BenchmarkCategory("IPv4")] + public void FileIPv4() => _fileV4Searcher.Search(_testIPv4Address); [Benchmark] - [BenchmarkCategory(nameof(CachePolicy.VectorIndex))] - public void VectorIndexIpV6() => _vectorV6Searcher.Search(_testIpV6Address); + [BenchmarkCategory("IPv6")] + public void ContentIPv6() => _contentV6Searcher.Search(_testIPv6Address); [Benchmark] - [BenchmarkCategory(nameof(CachePolicy.File))] - public void FileIpV6() => _fileV6Searcher.Search(_testIpV6Address); + [BenchmarkCategory("IPv6")] + public void VectorIPv6() => _vectorV6Searcher.Search(_testIPv6Address); + + [Benchmark] + [BenchmarkCategory("IPv6")] + public void FileIPv6() => _fileV6Searcher.Search(_testIPv6Address); } diff --git a/binding/csharp/IP2Region.Net.Test/SearcherTest.cs b/binding/csharp/IP2Region.Net.Test/SearcherTest.cs index ce10a11..da9f840 100644 --- a/binding/csharp/IP2Region.Net.Test/SearcherTest.cs +++ b/binding/csharp/IP2Region.Net.Test/SearcherTest.cs @@ -80,17 +80,6 @@ public class SearcherTest Assert.Equal(3, searcher.IoCount); } - [Fact] - public void IoCount_Content_Ok() - { - var searcher = new Searcher(CachePolicy.Content, _xdbPathV4); - searcher.Search("58.251.27.201"); - Assert.Equal(0, searcher.IoCount); - - searcher.Search("58.251.27.201"); - Assert.Equal(0, searcher.IoCount); - } - [Fact] public void IoCount_Vector_Ok() { @@ -102,6 +91,17 @@ public class SearcherTest Assert.Equal(2, searcher.IoCount); } + [Fact] + public void IoCount_Content_Ok() + { + var searcher = new Searcher(CachePolicy.Content, _xdbPathV4); + searcher.Search("58.251.27.201"); + Assert.Equal(0, searcher.IoCount); + + searcher.Search("58.251.27.201"); + Assert.Equal(0, searcher.IoCount); + } + [Theory] [InlineData("58.251.255.255", "中国|广东省|深圳市|联通")] public void Search_Ip_Ok(string ipStr, string expected) diff --git a/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs index a716382..d94524b 100644 --- a/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs @@ -11,7 +11,11 @@ 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; + private readonly FileStream _xdbFileStream = new(xdbPath, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, FileOptions.RandomAccess); public int IoCount { get; private set; } @@ -20,25 +24,26 @@ internal abstract class AbstractCacheStrategy(string xdbPath) IoCount = 0; } - public virtual ReadOnlyMemory GetVectorIndexStartPos(int offset) - { - return GetData(256 + offset, 8); - } + public virtual ReadOnlyMemory GetVectorIndex(int offset) => GetData(HeaderInfoLength + offset, VectorIndexSize); - public virtual ReadOnlyMemory GetData(int offset, int length) + public virtual ReadOnlyMemory GetData(int offset = 0, int length = 0) { + if (length == 0) + { + length = (int)_xdbFileStream.Length; + } + byte[] buffer = ArrayPool.Shared.Rent(length); int totalBytesRead = 0; try { - var stream = GetXdbFileStream(); - stream.Seek(offset, SeekOrigin.Begin); + _xdbFileStream.Seek(offset, SeekOrigin.Begin); int bytesRead; while (totalBytesRead < length) { int bytesToRead = Math.Min(BufferSize, length - totalBytesRead); - bytesRead = stream.Read(buffer, totalBytesRead, bytesToRead); + bytesRead = _xdbFileStream.Read(buffer, totalBytesRead, bytesToRead); totalBytesRead += bytesRead; IoCount++; @@ -51,15 +56,4 @@ internal abstract class AbstractCacheStrategy(string xdbPath) return new ReadOnlyMemory(buffer, 0, totalBytesRead); } - - FileStream? _xdbFileStream; - - protected FileStream GetXdbFileStream() - { - if (_xdbFileStream == null) - { - _xdbFileStream = new FileStream(xdbPath, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, FileOptions.RandomAccess); - } - return _xdbFileStream; - } } diff --git a/binding/csharp/IP2Region.Net/Internal/CacheStrategyFactory.cs b/binding/csharp/IP2Region.Net/Internal/CacheStrategyFactory.cs index e71f5bd..084a3d0 100644 --- a/binding/csharp/IP2Region.Net/Internal/CacheStrategyFactory.cs +++ b/binding/csharp/IP2Region.Net/Internal/CacheStrategyFactory.cs @@ -10,7 +10,7 @@ using IP2Region.Net.XDB; namespace IP2Region.Net.Internal; -internal class CacheStrategyFactory(string xdbPath) +class CacheStrategyFactory(string xdbPath) { public AbstractCacheStrategy CreateCacheStrategy(CachePolicy cachePolicy) => cachePolicy switch { diff --git a/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs index fad002b..cc88359 100644 --- a/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs @@ -11,16 +11,12 @@ namespace IP2Region.Net.Internal; class ContentCacheStrategy : AbstractCacheStrategy { - readonly ReadOnlyMemory _cacheData = default; + private readonly ReadOnlyMemory _cacheData; public ContentCacheStrategy(string xdbPath) : base(xdbPath) { - using var reader = base.GetXdbFileStream(); - _cacheData = base.GetData(0, (int)reader.Length); + _cacheData = base.GetData(); } - public override ReadOnlyMemory GetData(int offset, int length) - { - return _cacheData.Slice(offset, length); - } + public override ReadOnlyMemory GetData(int offset = 0, int length = 0) => _cacheData.Slice(offset, length); } diff --git a/binding/csharp/IP2Region.Net/Internal/VectorIndexCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/VectorIndexCacheStrategy.cs index 89ff83e..8ea0b01 100644 --- a/binding/csharp/IP2Region.Net/Internal/VectorIndexCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/VectorIndexCacheStrategy.cs @@ -9,14 +9,17 @@ using IP2Region.Net.Internal.Abstractions; namespace IP2Region.Net.Internal; -internal class VectorIndexCacheStrategy : AbstractCacheStrategy +class VectorIndexCacheStrategy : AbstractCacheStrategy { - readonly ReadOnlyMemory _vectorCache = default; + private const int VectorIndexRows = 256; + private const int VectorIndexCols = 256; + + private readonly ReadOnlyMemory _vectorCache; public VectorIndexCacheStrategy(string xdbPath) : base(xdbPath) { - _vectorCache = base.GetData(256, 256 * 256 * 8); + _vectorCache = GetData(HeaderInfoLength, VectorIndexRows * VectorIndexCols * VectorIndexSize); } - public override ReadOnlyMemory GetVectorIndexStartPos(int offset) => _vectorCache.Slice(offset, 8); + 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 adb30d6..2f0eadb 100644 --- a/binding/csharp/IP2Region.Net/XDB/Searcher.cs +++ b/binding/csharp/IP2Region.Net/XDB/Searcher.cs @@ -78,9 +78,9 @@ public class Searcher : ISearcher var il1 = ipBytes[1]; var idx = il0 * vectorIndexCols * vectorIndexSize + il1 * vectorIndexSize; - var data = _cacheStrategy.GetVectorIndexStartPos(idx); - var sPtr = BinaryPrimitives.ReadUInt32LittleEndian(data.Span); - var ePtr = BinaryPrimitives.ReadUInt32LittleEndian(data.Span.Slice(4)); + var vector = _cacheStrategy.GetVectorIndex(idx); + var sPtr = BinaryPrimitives.ReadUInt32LittleEndian(vector.Span); + var ePtr = BinaryPrimitives.ReadUInt32LittleEndian(vector.Span.Slice(4)); var length = ipBytes.Length; var indexSize = length * 2 + 6; @@ -125,11 +125,12 @@ public class Searcher : ISearcher var ret = 0; for (int i = 0; i < ip1.Length; i++) { - if (ip1[i] < ip2[ip1.Length - 1 - i]) + var ip2Index = ip1.Length - 1 - i; + if (ip1[i] < ip2[ip2Index]) { return -1; } - else if (ip1[i] > ip2[ip1.Length - 1 - i]) + else if (ip1[i] > ip2[ip2Index]) { return 1; }