From 87b69e6b5fc931e1e494c84c239db5d727ad0bc8 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 21 Nov 2025 09:42:59 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E6=8F=90=E9=AB=98=20Content=20?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=A8=A1=E5=BC=8F=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Abstractions/AbstractCacheStrategy.cs | 25 +++++++++++-------- .../Internal/ContentCacheStrategy.cs | 17 ++++++------- binding/csharp/IP2Region.Net/XDB/Util.cs | 7 +++++- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs index 3509187..9ba96af 100644 --- a/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs @@ -8,32 +8,26 @@ using System.Buffers; namespace IP2Region.Net.Internal.Abstractions; -internal abstract class AbstractCacheStrategy +internal abstract class AbstractCacheStrategy(string xdbPath) { - protected readonly FileStream XdbFileStream; private const int BufferSize = 4096; internal int IoCount { get; private set; } - protected AbstractCacheStrategy(string xdbPath) - { - XdbFileStream = new FileStream(xdbPath, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, - useAsync: true); - } - internal virtual ReadOnlyMemory GetData(int offset, int length) { byte[] buffer = ArrayPool.Shared.Rent(length); int totalBytesRead = 0; try { - XdbFileStream.Seek(offset, SeekOrigin.Begin); + var stream = GetXdbFileStream(); + stream.Seek(offset, SeekOrigin.Begin); int bytesRead; while (totalBytesRead < length) { int bytesToRead = Math.Min(BufferSize, length - totalBytesRead); - bytesRead = XdbFileStream.Read(buffer, totalBytesRead, bytesToRead); + bytesRead = stream.Read(buffer, totalBytesRead, bytesToRead); totalBytesRead += bytesRead; IoCount++; @@ -46,4 +40,15 @@ internal abstract class AbstractCacheStrategy 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/ContentCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs index c455521..0ef7251 100644 --- a/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs @@ -8,19 +8,18 @@ using IP2Region.Net.Internal.Abstractions; namespace IP2Region.Net.Internal; -class ContentCacheStrategy : AbstractCacheStrategy +class ContentCacheStrategy(string xdbPath) : AbstractCacheStrategy(xdbPath) { - readonly ReadOnlyMemory _cacheData; - - public ContentCacheStrategy(string xdbPath) : base(xdbPath) - { - _cacheData = base.GetData(0, (int)XdbFileStream.Length); - XdbFileStream.Close(); - XdbFileStream.Dispose(); - } + ReadOnlyMemory _cacheData = ReadOnlyMemory.Empty; internal override ReadOnlyMemory GetData(int offset, int length) { + if (_cacheData.IsEmpty) + { + using var reader = base.GetXdbFileStream(); + _cacheData = base.GetData(0, (int)reader.Length); + } + return _cacheData.Slice(offset, length); } } diff --git a/binding/csharp/IP2Region.Net/XDB/Util.cs b/binding/csharp/IP2Region.Net/XDB/Util.cs index f593a9b..5f8673c 100644 --- a/binding/csharp/IP2Region.Net/XDB/Util.cs +++ b/binding/csharp/IP2Region.Net/XDB/Util.cs @@ -38,8 +38,13 @@ public static class Util throw new FileNotFoundException("xdb file not fould.", dbPath); } - XdbVersion ret = default; using var reader = File.OpenRead(dbPath); + return await GetVersionAsync(reader, token); + } + + internal static async Task GetVersionAsync(FileStream reader, CancellationToken token = default) + { + XdbVersion ret = default; var buffer = ArrayPool.Shared.Rent(256); try