Showing preview only (1,210K chars total). Download the full file or copy to clipboard to get everything.
Repository: vla/BloomFilter.NetCore
Branch: main
Commit: c2885f904b7e
Files: 147
Total size: 1.1 MB
Directory structure:
gitextract_745aaz2k/
├── .gitignore
├── BloomFilter.NetCore.sln
├── Directory.Build.props
├── Directory.Packages.props
├── LICENSE
├── README.md
├── README.zh-CN.md
├── VERSION
├── build.cmd
├── build.sh
├── nuget_push.cmd
├── sign.snk
├── src/
│ ├── BloomFilter/
│ │ ├── Annotations.cs
│ │ ├── AsyncLock.cs
│ │ ├── BinaryHelper.cs
│ │ ├── BloomFilter.csproj
│ │ ├── BloomFilterConstValue.cs
│ │ ├── BloomFilterExtensions.cs
│ │ ├── Configurations/
│ │ │ ├── BloomFilterOptions.cs
│ │ │ ├── FilterMemoryOptions.cs
│ │ │ ├── FilterMemoryOptionsExtension.cs
│ │ │ └── IBloomFilterOptionsExtension.cs
│ │ ├── DefaultBloomFilterFactory.cs
│ │ ├── DefaultFilterMemorySerializer.cs
│ │ ├── Filter.cs
│ │ ├── FilterBuilder.cs
│ │ ├── FilterMemory.cs
│ │ ├── FilterMemorySerializerParam.cs
│ │ ├── FilterRedisBase.cs
│ │ ├── HashAlgorithms/
│ │ │ ├── Adler32.cs
│ │ │ ├── Crc32.cs
│ │ │ ├── Crc64.cs
│ │ │ ├── HashCrypto.cs
│ │ │ ├── Internal/
│ │ │ │ ├── Adler32.cs
│ │ │ │ ├── Crc32.Arm.cs
│ │ │ │ ├── Crc32.Table.cs
│ │ │ │ ├── Crc32.Vectorized.cs
│ │ │ │ ├── Crc32.cs
│ │ │ │ ├── Crc64.Table.cs
│ │ │ │ ├── Crc64.Vectorized.cs
│ │ │ │ ├── Crc64.cs
│ │ │ │ ├── FNV1.cs
│ │ │ │ ├── FNV1a.cs
│ │ │ │ ├── ModifiedFNV1.cs
│ │ │ │ ├── Murmur128BitsX64.State.cs
│ │ │ │ ├── Murmur128BitsX64.cs
│ │ │ │ ├── Murmur128BitsX86.State.cs
│ │ │ │ ├── Murmur128BitsX86.cs
│ │ │ │ ├── Murmur32BitsX86.State.cs
│ │ │ │ ├── Murmur32BitsX86.cs
│ │ │ │ ├── NonCryptoHashAlgorithm.cs
│ │ │ │ ├── ThrowHelper.cs
│ │ │ │ ├── VectorHelper.cs
│ │ │ │ ├── XxHash128.cs
│ │ │ │ ├── XxHash3.cs
│ │ │ │ ├── XxHash32.State.cs
│ │ │ │ ├── XxHash32.cs
│ │ │ │ ├── XxHash64.State.cs
│ │ │ │ ├── XxHash64.cs
│ │ │ │ └── XxHashShared.cs
│ │ │ ├── LCGWithFNV.cs
│ │ │ ├── Murmur128BitsX64.cs
│ │ │ ├── Murmur128BitsX86.cs
│ │ │ ├── Murmur32BitsX86.cs
│ │ │ ├── RNGWithFNV.cs
│ │ │ ├── XXHash128.cs
│ │ │ ├── XXHash3.cs
│ │ │ ├── XXHash32.cs
│ │ │ └── XXHash64.cs
│ │ ├── HashFunction.cs
│ │ ├── HashMethod.cs
│ │ ├── IBloomFilter.cs
│ │ ├── IBloomFilterFactory.cs
│ │ ├── IFilterMemorySerializer.cs
│ │ ├── Properties/
│ │ │ └── AssemblyInfo.cs
│ │ ├── ServiceCollectionExtensions.cs
│ │ └── StringSpanExtensions.cs
│ ├── BloomFilter.CSRedis/
│ │ ├── BloomFilter.CSRedis.csproj
│ │ ├── Configurations/
│ │ │ ├── FilterCSRedisOptions.cs
│ │ │ ├── FilterCSRedisOptionsExtension.cs
│ │ │ └── ServiceCollectionExtensions.cs
│ │ ├── FilterCSRedis.cs
│ │ └── FilterCSRedisBuilder.cs
│ ├── BloomFilter.EasyCaching/
│ │ ├── BloomFilter.EasyCaching.csproj
│ │ ├── Configurations/
│ │ │ ├── FilterEasyCachingRedisExtension.cs
│ │ │ ├── FilterEasyCachingRedisOptions.cs
│ │ │ └── ServiceCollectionExtensions.cs
│ │ ├── FilterEasyCachingBuilder.cs
│ │ └── FilterEasyCachingRedis.cs
│ ├── BloomFilter.FreeRedis/
│ │ ├── BloomFilter.FreeRedis.csproj
│ │ ├── Configurations/
│ │ │ ├── FilterFreeRedisOptions.cs
│ │ │ ├── FilterFreeRedisOptionsExtension.cs
│ │ │ └── ServiceCollectionExtensions.cs
│ │ ├── FilterFreeRedis.cs
│ │ └── FilterFreeRedisBuilder.cs
│ └── BloomFilter.Redis/
│ ├── BloomFilter.Redis.csproj
│ ├── Configurations/
│ │ ├── FilterRedisOptions.cs
│ │ ├── FilterRedisOptionsExtension.cs
│ │ └── ServiceCollectionExtensions.cs
│ ├── FilterRedis.cs
│ ├── FilterRedisBuilder.cs
│ ├── IRedisBitOperate.cs
│ └── RedisBitOperate.cs
└── test/
├── BenchmarkTest/
│ ├── BenchmarkTest.csproj
│ ├── FreeRedisBenchmark.cs
│ ├── Helper.cs
│ ├── MemoryBenchmark.cs
│ ├── Program.cs
│ └── RedisBenchmark.cs
├── BloomFilter.Redis.Test/
│ ├── BloomFilter.Redis.Test.csproj
│ ├── BloomFilterCSRedisTest.cs
│ ├── BloomFilterEasyCachingRedisTest.cs
│ ├── BloomFilterFreeRedisTest.cs
│ ├── BloomFilterRedisTest.cs
│ ├── ConfigurationsTest.cs
│ ├── RedisBitOperateTest.cs
│ └── Utilitiy.cs
├── BloomFilterTest/
│ ├── AsyncLockTests.cs
│ ├── BloomFilterTest.cs
│ ├── BloomFilterTest.csproj
│ ├── ConfigurationsTest.cs
│ ├── FluentFilterBuilderTest.cs
│ ├── HashAlgorithms/
│ │ ├── Adler32Test.cs
│ │ ├── CrcTest.cs
│ │ ├── FNVTest.cs
│ │ ├── Murmur3Test.cs
│ │ ├── TestPayloadParameter.cs
│ │ └── XxHashTest.cs
│ ├── ImportExportTest.cs
│ ├── IssuesTest.cs
│ ├── SerializerTest.cs
│ ├── Utilitiy.cs
│ ├── ValueTypeTest.cs
│ └── xunit.runner.json
├── Demo/
│ ├── BloomFilterMemory.cs
│ ├── BloomFilterRedis.cs
│ ├── Demo.csproj
│ ├── Program.cs
│ └── TestExcute.cs
└── PerformanceTest/
├── GeneralPerformance.cs
├── HashErrRate.cs
├── HashSpeed.cs
├── Helper.cs
├── Issues_2.cs
├── PerformanceTest.csproj
├── Program.cs
└── TestExcute.cs
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Build results
[Dd]ebug/
[Rr]elease/
x64/
app.publish/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# Visual Studio
*.suo
*.user
*.sln.docstates
*.sln.ide/
project.lock.json
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
#GhostDoc
*.GhostDoc.xml
# NuGet Packages Directory
packages/
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store
####################
#
# Current Project
#
####################
.vs/
artifacts/
*.log
/test/BenchmarkTest/BenchmarkDotNet.Artifacts
================================================
FILE: BloomFilter.NetCore.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8D22B289-3A76-4399-BDA3-FD1B699B2F13}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{BFDF8E72-A7F7-4894-8782-74BB34438F99}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Demo", "test\Demo\Demo.csproj", "{42A8F6A2-7CE7-493F-B3A7-07A1753F5285}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BloomFilter", "src\BloomFilter\BloomFilter.csproj", "{E9FB2A60-8EFE-49E9-98FE-D75A076CAD0F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BloomFilterTest", "test\BloomFilterTest\BloomFilterTest.csproj", "{24193FBE-88A5-4C26-9996-341DEBE0CA80}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PerformanceTest", "test\PerformanceTest\PerformanceTest.csproj", "{D46EEAAF-36FD-4297-9381-1845C93D13C4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BloomFilter.Redis", "src\BloomFilter.Redis\BloomFilter.Redis.csproj", "{4A858860-7405-43F4-9132-0DF40BADBDAD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BloomFilter.Redis.Test", "test\BloomFilter.Redis.Test\BloomFilter.Redis.Test.csproj", "{C02DC47A-7258-4B59-AAB4-DFA208DE9B36}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkTest", "test\BenchmarkTest\BenchmarkTest.csproj", "{CFB47A7F-580A-4F4B-940D-03D99EE70C41}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BloomFilter.CSRedis", "src\BloomFilter.CSRedis\BloomFilter.CSRedis.csproj", "{903B0A3A-1753-47CA-ADBC-B4379FF8F372}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BloomFilter.EasyCaching", "src\BloomFilter.EasyCaching\BloomFilter.EasyCaching.csproj", "{C4AFDCB8-077D-463A-9EF9-D2F8723F01F4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BloomFilter.FreeRedis", "src\BloomFilter.FreeRedis\BloomFilter.FreeRedis.csproj", "{311303FD-7ABA-4C7D-AA5C-90E265FA04A7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{42A8F6A2-7CE7-493F-B3A7-07A1753F5285}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{42A8F6A2-7CE7-493F-B3A7-07A1753F5285}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42A8F6A2-7CE7-493F-B3A7-07A1753F5285}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42A8F6A2-7CE7-493F-B3A7-07A1753F5285}.Release|Any CPU.Build.0 = Release|Any CPU
{E9FB2A60-8EFE-49E9-98FE-D75A076CAD0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E9FB2A60-8EFE-49E9-98FE-D75A076CAD0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E9FB2A60-8EFE-49E9-98FE-D75A076CAD0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E9FB2A60-8EFE-49E9-98FE-D75A076CAD0F}.Release|Any CPU.Build.0 = Release|Any CPU
{24193FBE-88A5-4C26-9996-341DEBE0CA80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{24193FBE-88A5-4C26-9996-341DEBE0CA80}.Debug|Any CPU.Build.0 = Debug|Any CPU
{24193FBE-88A5-4C26-9996-341DEBE0CA80}.Release|Any CPU.ActiveCfg = Release|Any CPU
{24193FBE-88A5-4C26-9996-341DEBE0CA80}.Release|Any CPU.Build.0 = Release|Any CPU
{D46EEAAF-36FD-4297-9381-1845C93D13C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D46EEAAF-36FD-4297-9381-1845C93D13C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D46EEAAF-36FD-4297-9381-1845C93D13C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D46EEAAF-36FD-4297-9381-1845C93D13C4}.Release|Any CPU.Build.0 = Release|Any CPU
{4A858860-7405-43F4-9132-0DF40BADBDAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A858860-7405-43F4-9132-0DF40BADBDAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A858860-7405-43F4-9132-0DF40BADBDAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A858860-7405-43F4-9132-0DF40BADBDAD}.Release|Any CPU.Build.0 = Release|Any CPU
{C02DC47A-7258-4B59-AAB4-DFA208DE9B36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C02DC47A-7258-4B59-AAB4-DFA208DE9B36}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C02DC47A-7258-4B59-AAB4-DFA208DE9B36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C02DC47A-7258-4B59-AAB4-DFA208DE9B36}.Release|Any CPU.Build.0 = Release|Any CPU
{CFB47A7F-580A-4F4B-940D-03D99EE70C41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CFB47A7F-580A-4F4B-940D-03D99EE70C41}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CFB47A7F-580A-4F4B-940D-03D99EE70C41}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CFB47A7F-580A-4F4B-940D-03D99EE70C41}.Release|Any CPU.Build.0 = Release|Any CPU
{903B0A3A-1753-47CA-ADBC-B4379FF8F372}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{903B0A3A-1753-47CA-ADBC-B4379FF8F372}.Debug|Any CPU.Build.0 = Debug|Any CPU
{903B0A3A-1753-47CA-ADBC-B4379FF8F372}.Release|Any CPU.ActiveCfg = Release|Any CPU
{903B0A3A-1753-47CA-ADBC-B4379FF8F372}.Release|Any CPU.Build.0 = Release|Any CPU
{C4AFDCB8-077D-463A-9EF9-D2F8723F01F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C4AFDCB8-077D-463A-9EF9-D2F8723F01F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4AFDCB8-077D-463A-9EF9-D2F8723F01F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4AFDCB8-077D-463A-9EF9-D2F8723F01F4}.Release|Any CPU.Build.0 = Release|Any CPU
{311303FD-7ABA-4C7D-AA5C-90E265FA04A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{311303FD-7ABA-4C7D-AA5C-90E265FA04A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{311303FD-7ABA-4C7D-AA5C-90E265FA04A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{311303FD-7ABA-4C7D-AA5C-90E265FA04A7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{42A8F6A2-7CE7-493F-B3A7-07A1753F5285} = {BFDF8E72-A7F7-4894-8782-74BB34438F99}
{E9FB2A60-8EFE-49E9-98FE-D75A076CAD0F} = {8D22B289-3A76-4399-BDA3-FD1B699B2F13}
{24193FBE-88A5-4C26-9996-341DEBE0CA80} = {BFDF8E72-A7F7-4894-8782-74BB34438F99}
{D46EEAAF-36FD-4297-9381-1845C93D13C4} = {BFDF8E72-A7F7-4894-8782-74BB34438F99}
{4A858860-7405-43F4-9132-0DF40BADBDAD} = {8D22B289-3A76-4399-BDA3-FD1B699B2F13}
{C02DC47A-7258-4B59-AAB4-DFA208DE9B36} = {BFDF8E72-A7F7-4894-8782-74BB34438F99}
{CFB47A7F-580A-4F4B-940D-03D99EE70C41} = {BFDF8E72-A7F7-4894-8782-74BB34438F99}
{903B0A3A-1753-47CA-ADBC-B4379FF8F372} = {8D22B289-3A76-4399-BDA3-FD1B699B2F13}
{C4AFDCB8-077D-463A-9EF9-D2F8723F01F4} = {8D22B289-3A76-4399-BDA3-FD1B699B2F13}
{311303FD-7ABA-4C7D-AA5C-90E265FA04A7} = {8D22B289-3A76-4399-BDA3-FD1B699B2F13}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {12D6ACDC-31C9-4A69-BE24-76E0F73E48A6}
EndGlobalSection
EndGlobal
================================================
FILE: Directory.Build.props
================================================
<Project>
<PropertyGroup>
<Version>$(Ver)</Version>
<PackageVersion>$(Ver)</PackageVersion>
<Copyright>2019-2023 v.la</Copyright>
<Authors>v.la@live.cn</Authors>
<Description>A bloom filter implementation</Description>
<Product>bloom filter</Product>
<PackageOutputPath>$(MSBuildThisFileDirectory)/artifacts</PackageOutputPath>
<PackageTags>Bloom;Filter;bloom-filter</PackageTags>
<LangVersion>latest</LangVersion>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageIcon>icon.png</PackageIcon>
<PackageProjectUrl>https://github.com/vla/BloomFilter.NetCore</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageLicenseType>MIT</PackageLicenseType>
<RepositoryUrl>git://github.com/vla/BloomFilter.NetCore</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<RepositoryBranch>master</RepositoryBranch>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' != 'Debug' ">
<Optimize>true</Optimize>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>True</SignAssembly>
<DelaySign>False</DelaySign>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)/sign.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)/icon.png" Pack="true" PackagePath=""/>
</ItemGroup>
</Project>
================================================
FILE: Directory.Packages.props
================================================
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>false</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<ItemGroup>
<!-- Core Dependencies -->
<PackageVersion Include="System.Runtime" Version="4.3.1" />
<PackageVersion Include="System.Memory" Version="4.6.3" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
<!-- Redis Clients -->
<PackageVersion Include="StackExchange.Redis" Version="2.9.32" />
<PackageVersion Include="CSRedisCore" Version="3.8.807" />
<PackageVersion Include="FreeRedis" Version="1.5.2" />
<!-- EasyCaching -->
<PackageVersion Include="EasyCaching.Core" Version="1.9.2" />
<PackageVersion Include="EasyCaching.CSRedis" Version="1.9.2" />
<PackageVersion Include="EasyCaching.Serialization.Json" Version="1.9.2" />
<!-- Testing -->
<PackageVersion Include="FluentAssertions" Version="8.8.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
<!-- Benchmarking -->
<PackageVersion Include="BenchmarkDotNet" Version="0.15.6" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0" />
</ItemGroup>
</Project>
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2018 v.la@live.cn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# BloomFilter.NetCore
[](https://opensource.org/licenses/MIT)
[](https://dotnet.microsoft.com/)
A high-performance, feature-complete Bloom filter library for .NET, supporting both in-memory and distributed Redis backends.
[中文文档](README.zh-CN.md)
## Table of Contents
- [Overview](#overview)
- [Key Features](#key-features)
- [Packages & Status](#packages--status)
- [Architecture](#architecture)
- [Core Functionality](#core-functionality)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Usage Examples](#usage-examples)
- [In-Memory Mode](#in-memory-mode)
- [Dependency Injection](#dependency-injection)
- [Redis Distributed Mode](#redis-distributed-mode)
- [Hash Algorithms](#hash-algorithms)
- [Performance Benchmarks](#performance-benchmarks)
- [Advanced Usage](#advanced-usage)
- [API Reference](#api-reference)
- [Contributing](#contributing)
- [License](#license)
## Overview
BloomFilter.NetCore is an enterprise-grade Bloom filter library designed for the .NET ecosystem. A Bloom filter is a space-efficient probabilistic data structure used to test whether an element is a member of a set. Its core characteristics are:
- **Space Efficient**: Extremely small memory footprint compared to traditional HashSets
- **O(1) Time Complexity**: Both add and query operations execute in constant time
- **Probabilistic**: May return false positives but never false negatives
This project provides two major implementation types:
1. **In-Memory Bloom Filter (FilterMemory)**: BitArray-based in-memory implementation, suitable for single-process scenarios
2. **Distributed Bloom Filter (FilterRedis series)**: Redis-backed distributed implementation, supports concurrent access from multiple applications
### Primary Use Cases
- **Cache Penetration Protection**: Prevent malicious queries for non-existent data from bypassing cache
- **Deduplication**: URL deduplication, email deduplication, user ID deduplication, etc.
- **Recommendation Systems**: Check if a user has seen specific content
- **Web Crawlers**: Check if URLs have been crawled
- **Distributed Systems**: Share state checks across multiple service instances
- **Big Data**: Existence checks for massive datasets
## Key Features
### 🎯 Flexible Configuration
- **Fully Configurable Parameters**: Bit array size (m), number of hash functions (k)
- **Automatic Parameter Calculation**: Automatically calculate optimal parameters based on tolerable false positive rate (p) and expected element count (n)
- **20+ Hash Algorithms**: Support for CRC, MD5, SHA, Murmur, LCGs, xxHash, or custom algorithms
### ⚡ High Performance
- **Fast Generation**: Bloom filter generation and operations are extremely fast
- **Optimized Implementation**: Uses Span<T>, ReadOnlyMemory<T> for zero-copy operations
- **Unsafe Code Optimization**: Uses unsafe code blocks in performance-critical paths
- **Rejection Sampling**: Implements rejection sampling and hash chaining, considering avalanche effect for improved hash quality
### 🔒 Concurrency Safe
- **Thread-Safe**: Uses AsyncLock mechanism for safe multi-threaded concurrent access
- **Async Support**: Comprehensive async/await support with async versions of all operations
- **Distributed Locking**: Redis implementations support concurrent access across applications
### 🌐 Multiple Backend Support
- **StackExchange.Redis**: Officially recommended Redis client
- **CSRedisCore**: High-performance Redis client
- **FreeRedis**: Lightweight Redis client
- **EasyCaching**: Supports EasyCaching abstraction layer, switchable cache providers
### 📦 Modern .NET Support
- **Multi-Framework Support**: net462, netstandard2.0, net6.0, net7.0, net8.0, net9.0, net10.0
- **Dependency Injection**: Native support for Microsoft.Extensions.DependencyInjection
- **Nullable Reference Types**: Enabled for improved code safety
## Packages & Status
| Package | NuGet | Description |
|---------|-------|-------------|
|**BloomFilter.NetCore**|[](https://www.nuget.org/packages/BloomFilter.NetCore)| Core package with in-memory Bloom filter |
|**BloomFilter.Redis.NetCore**|[](https://www.nuget.org/packages/BloomFilter.Redis.NetCore)| StackExchange.Redis implementation |
|**BloomFilter.CSRedis.NetCore**|[](https://www.nuget.org/packages/BloomFilter.CSRedis.NetCore)| CSRedisCore implementation |
|**BloomFilter.FreeRedis.NetCore**|[](https://www.nuget.org/packages/BloomFilter.FreeRedis.NetCore)| FreeRedis implementation |
|**BloomFilter.EasyCaching.NetCore**|[](https://www.nuget.org/packages/BloomFilter.EasyCaching.NetCore)| EasyCaching integration |
## Architecture
### Core Interface Layer
```
IBloomFilter (Interface)
├── Add / AddAsync - Add elements
├── Contains / ContainsAsync - Check elements
├── All / AllAsync - Batch check
├── Clear / ClearAsync - Clear filter
└── ComputeHash - Compute hash values
```
### Implementation Hierarchy
```
Filter (Abstract Base Class)
├── FilterMemory (In-Memory)
│ └── Uses BitArray storage
│
└── Redis Series (Distributed)
├── FilterRedis (StackExchange.Redis)
├── FilterCSRedis (CSRedisCore)
├── FilterFreeRedis (FreeRedis)
└── FilterEasyCachingRedis (EasyCaching)
```
### Configuration System
```
BloomFilterOptions
├── FilterMemoryOptions - In-memory mode configuration
├── FilterRedisOptions - StackExchange.Redis configuration
├── FilterCSRedisOptions - CSRedisCore configuration
├── FilterFreeRedisOptions - FreeRedis configuration
└── FilterEasyCachingOptions - EasyCaching configuration
```
## Core Functionality
### Mathematical Model
BloomFilter.NetCore implements the complete Bloom filter mathematical model:
#### 1. Optimal Bit Array Size (m)
Given expected element count `n` and false positive rate `p`, calculate optimal bit array size:
```
m = -(n * ln(p)) / (ln(2)^2)
```
#### 2. Optimal Number of Hash Functions (k)
Given element count `n` and bit array size `m`, calculate optimal number of hash functions:
```
k = (m / n) * ln(2)
```
#### 3. Actual False Positive Rate (p)
Given inserted element count, number of hash functions, and bit array size, calculate actual false positive rate:
```
p = (1 - e^(-k*n/m))^k
```
These calculations are provided by static methods in the `Filter` base class:
```csharp
// Calculate optimal bit array size
long m = Filter.BestM(expectedElements, errorRate);
// Calculate optimal number of hash functions
int k = Filter.BestK(expectedElements, capacity);
// Calculate optimal element count
long n = Filter.BestN(hashes, capacity);
// Calculate actual false positive rate
double p = Filter.BestP(hashes, capacity, insertedElements);
```
### Storage Mechanisms
#### In-Memory Storage
- **BitArray**: Uses .NET's BitArray as underlying storage
- **Bucketing Strategy**: Automatically splits into multiple BitArrays when capacity exceeds 2GB (MaxInt = 2,147,483,640)
- **Serialization Support**: Supports serialization/deserialization for persistence or transfer
#### Redis Storage
- **SETBIT/GETBIT**: Uses Redis bit operation commands
- **Distributed Access**: Multiple application instances can concurrently access the same filter
- **Persistence**: Leverages Redis persistence mechanisms for data safety
### Concurrency Control
```csharp
// AsyncLock ensures thread safety
public class AsyncLock
{
private readonly SemaphoreSlim _semaphore = new(1, 1);
public async ValueTask<IDisposable> LockAsync()
{
await _semaphore.WaitAsync();
return new Release(_semaphore);
}
}
```
## Installation
### Install via NuGet
**In-Memory Mode (Core Package):**
```bash
dotnet add package BloomFilter.NetCore
```
**Redis Distributed Mode (Choose One):**
```bash
# StackExchange.Redis
dotnet add package BloomFilter.Redis.NetCore
# CSRedisCore
dotnet add package BloomFilter.CSRedis.NetCore
# FreeRedis
dotnet add package BloomFilter.FreeRedis.NetCore
# EasyCaching
dotnet add package BloomFilter.EasyCaching.NetCore
```
## Quick Start
### Simplest Example
```csharp
using BloomFilter;
// Create a Bloom filter: expect 10 million elements, 1% false positive rate
var bf = FilterBuilder.Build(10_000_000, 0.01);
// Add elements
bf.Add("user:123");
bf.Add("user:456");
// Check element existence
Console.WriteLine(bf.Contains("user:123")); // True
Console.WriteLine(bf.Contains("user:789")); // False (very small probability of True)
// Clear filter
bf.Clear();
```
### Async Operations
```csharp
// Async add
await bf.AddAsync(Encoding.UTF8.GetBytes("user:123"));
// Async check
bool exists = await bf.ContainsAsync(Encoding.UTF8.GetBytes("user:123"));
// Batch async operations
var users = new[] {
Encoding.UTF8.GetBytes("user:1"),
Encoding.UTF8.GetBytes("user:2"),
Encoding.UTF8.GetBytes("user:3")
};
await bf.AddAsync(users);
var results = await bf.ContainsAsync(users);
```
### Fluent API (New in v3.0)
v3.0 introduces a modern fluent API for building Bloom filters with improved discoverability and expressiveness:
```csharp
// In-Memory Fluent API
var filter = FilterBuilder.Create()
.WithName("UserFilter")
.ExpectingElements(10_000_000)
.WithErrorRate(0.001)
.UsingHashMethod(HashMethod.XXHash3)
.BuildInMemory();
// Redis Fluent API (StackExchange.Redis)
var redisFilter = FilterRedisBuilder.Create()
.WithRedisConnection("localhost:6379")
.WithRedisKey("bloom:users")
.WithName("UserFilter")
.ExpectingElements(10_000_000)
.WithErrorRate(0.001)
.BuildRedis();
// CSRedis Fluent API
var csredisFilter = FilterCSRedisBuilder.Create()
.WithRedisClient(csredisClient)
.WithRedisKey("bloom:users")
.ExpectingElements(10_000_000)
.BuildCSRedis();
// FreeRedis Fluent API
var freeRedisFilter = FilterFreeRedisBuilder.Create()
.WithRedisClient(redisClient)
.WithRedisKey("bloom:users")
.ExpectingElements(10_000_000)
.BuildFreeRedis();
// EasyCaching Fluent API
var easyCachingFilter = FilterEasyCachingBuilder.Create()
.WithRedisCachingProvider(provider)
.WithRedisKey("bloom:users")
.ExpectingElements(10_000_000)
.BuildEasyCaching();
// All common configuration methods:
// - WithName(string) - Set filter name
// - ExpectingElements(long) - Set expected element count
// - WithErrorRate(double) - Set false positive rate (0-1)
// - UsingHashMethod(HashMethod) - Use predefined hash algorithm
// - UsingCustomHash(HashFunction) - Use custom hash function
// - WithSerializer(IFilterMemorySerializer) - Set custom serializer (memory only)
```
**Why use Fluent API?**
- 🔍 Better discoverability with IntelliSense
- 📖 More readable and self-documenting code
- ⛓️ Chainable method calls
- 🎯 Type-safe configuration
- ✅ Backward compatible - old static methods still work!
## Usage Examples
### In-Memory Mode
#### Basic Usage
```csharp
using BloomFilter;
public class UserService
{
// Static shared Bloom filter
private static readonly IBloomFilter _bloomFilter =
FilterBuilder.Build(10_000_000, 0.01);
public void AddUser(string userId)
{
// Add user ID
_bloomFilter.Add(userId);
}
public bool MayExistUser(string userId)
{
// Check if user may exist
return _bloomFilter.Contains(userId);
}
}
```
#### Custom Configuration
```csharp
using BloomFilter;
// Method 1: Specify hash algorithm
var bf1 = FilterBuilder.Build(
expectedElements: 1_000_000,
errorRate: 0.001,
hashMethod: HashMethod.Murmur3
);
// Method 2: Use custom hash function
var hashFunction = new Murmur128BitsX64();
var bf2 = FilterBuilder.Build(
expectedElements: 1_000_000,
errorRate: 0.001,
hashFunction: hashFunction
);
// Method 3: Manually specify parameters (advanced usage)
var bf3 = FilterBuilder.Build(
capacity: 9585059, // Bit array size
hashes: 10, // Number of hash functions
hashMethod: HashMethod.XXHash3
);
// Method 4: Use configuration object
var options = new FilterMemoryOptions
{
Name = "MyFilter",
ExpectedElements = 5_000_000,
ErrorRate = 0.01,
Method = HashMethod.Murmur3
};
var bf4 = FilterBuilder.Build(options);
```
### Dependency Injection
#### ASP.NET Core Integration
```csharp
using BloomFilter;
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Register Bloom filter service
services.AddBloomFilter(setupAction =>
{
setupAction.UseInMemory(options =>
{
options.Name = "MainFilter";
options.ExpectedElements = 10_000_000;
options.ErrorRate = 0.01;
options.Method = HashMethod.Murmur3;
});
});
services.AddControllers();
}
}
// Use in controller or service
public class UserController : ControllerBase
{
private readonly IBloomFilter _bloomFilter;
public UserController(IBloomFilter bloomFilter)
{
_bloomFilter = bloomFilter;
}
[HttpPost("users/{userId}")]
public IActionResult CheckUser(string userId)
{
if (_bloomFilter.Contains(userId))
{
// User may exist, continue to query database
return Ok("User may exist");
}
else
{
// User definitely doesn't exist, no need to query database
return NotFound("User doesn't exist");
}
}
}
```
#### Multiple Filter Instances
```csharp
services.AddBloomFilter(setupAction =>
{
// User filter
setupAction.UseInMemory(options =>
{
options.Name = "UserFilter";
options.ExpectedElements = 10_000_000;
options.ErrorRate = 0.01;
});
// Email filter
setupAction.UseInMemory(options =>
{
options.Name = "EmailFilter";
options.ExpectedElements = 5_000_000;
options.ErrorRate = 0.001;
});
});
// Use factory to get specific filter
public class MyService
{
private readonly IBloomFilter _userFilter;
private readonly IBloomFilter _emailFilter;
public MyService(IBloomFilterFactory factory)
{
_userFilter = factory.Get("UserFilter");
_emailFilter = factory.Get("EmailFilter");
}
}
```
### Redis Distributed Mode
#### StackExchange.Redis
```csharp
using BloomFilter;
// Method 1: Direct build
var bf = FilterRedisBuilder.Build(
redisHost: "localhost:6379",
name: "DistributedFilter",
expectedElements: 5_000_000,
errorRate: 0.001
);
bf.Add("item:123");
Console.WriteLine(bf.Contains("item:123")); // True
// Method 2: Dependency injection
services.AddBloomFilter(setupAction =>
{
setupAction.UseRedis(new FilterRedisOptions
{
Name = "UserFilter",
RedisKey = "BloomFilter:Users",
Endpoints = new List<string> { "localhost:6379" },
Database = 0,
ExpectedElements = 10_000_000,
ErrorRate = 0.01,
Method = HashMethod.Murmur3
});
});
// Method 3: Advanced configuration (master-slave, sentinel, cluster)
services.AddBloomFilter(setupAction =>
{
setupAction.UseRedis(new FilterRedisOptions
{
Name = "ProductFilter",
RedisKey = "BloomFilter:Products",
Endpoints = new List<string>
{
"redis-master:6379",
"redis-slave1:6379",
"redis-slave2:6379"
},
Password = "your-redis-password",
Ssl = true,
ConnectTimeout = 5000,
SyncTimeout = 3000,
ExpectedElements = 20_000_000,
ErrorRate = 0.001
});
});
```
#### CSRedisCore
```csharp
services.AddBloomFilter(setupAction =>
{
setupAction.UseCSRedis(new FilterCSRedisOptions
{
Name = "OrderFilter",
RedisKey = "BloomFilter:Orders",
ConnectionStrings = new List<string>
{
"localhost:6379,password=123456,defaultDatabase=0,poolsize=50,prefix=myapp:"
},
ExpectedElements = 5_000_000,
ErrorRate = 0.01
});
});
```
#### FreeRedis
```csharp
services.AddBloomFilter(setupAction =>
{
setupAction.UseFreeRedis(new FilterFreeRedisOptions
{
Name = "CartFilter",
RedisKey = "BloomFilter:Carts",
ConnectionStrings = new List<string> { "localhost:6379,password=123456" },
ExpectedElements = 1_000_000,
ErrorRate = 0.01
});
});
```
#### EasyCaching Integration
EasyCaching provides a unified caching abstraction layer, allowing you to easily switch underlying cache implementations:
```csharp
using EasyCaching.Core.Configurations;
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
// 1. Configure EasyCaching
services.AddEasyCaching(options =>
{
// Configure Redis provider
options.UseRedis(config =>
{
config.DBConfig.Endpoints.Add(new ServerEndPoint("127.0.0.1", 6379));
config.DBConfig.Database = 0;
}, "redis-provider-1");
// Can configure multiple providers
options.UseRedis(config =>
{
config.DBConfig.Endpoints.Add(new ServerEndPoint("127.0.0.1", 6379));
config.DBConfig.Database = 1;
}, "redis-provider-2");
});
// 2. Configure BloomFilter
services.AddBloomFilter(setupAction =>
{
// Use first Redis provider
setupAction.UseEasyCachingRedis(new FilterEasyCachingRedisOptions
{
Name = "BF1",
RedisKey = "BloomFilter1",
ProviderName = "redis-provider-1",
ExpectedElements = 10_000_000,
ErrorRate = 0.01
});
// Use second Redis provider
setupAction.UseEasyCachingRedis(new FilterEasyCachingRedisOptions
{
Name = "BF2",
RedisKey = "BloomFilter2",
ProviderName = "redis-provider-2",
ExpectedElements = 5_000_000,
ErrorRate = 0.001
});
});
var provider = services.BuildServiceProvider();
// Use default filter
var bf = provider.GetService<IBloomFilter>();
bf.Add("value1");
// Use named filter
var factory = provider.GetService<IBloomFilterFactory>();
var bf1 = factory.Get("BF1");
var bf2 = factory.Get("BF2");
bf1.Add("item1");
bf2.Add("item2");
```
### Real-World Application Scenarios
#### 1. Cache Penetration Protection
```csharp
public class ProductService
{
private readonly IBloomFilter _bloomFilter;
private readonly ICache _cache;
private readonly IProductRepository _repository;
public ProductService(
IBloomFilter bloomFilter,
ICache cache,
IProductRepository repository)
{
_bloomFilter = bloomFilter;
_cache = cache;
_repository = repository;
}
public async Task<Product> GetProductAsync(string productId)
{
// First layer: Bloom filter
if (!_bloomFilter.Contains(productId))
{
// Product definitely doesn't exist, return null directly
return null;
}
// Second layer: Cache
var cached = await _cache.GetAsync<Product>(productId);
if (cached != null)
{
return cached;
}
// Third layer: Database
var product = await _repository.GetByIdAsync(productId);
if (product != null)
{
await _cache.SetAsync(productId, product);
}
return product;
}
public async Task CreateProductAsync(Product product)
{
// Save to database
await _repository.SaveAsync(product);
// Add to Bloom filter
_bloomFilter.Add(product.Id);
// Update cache
await _cache.SetAsync(product.Id, product);
}
}
```
#### 2. URL Deduplication (Web Crawler)
```csharp
public class WebCrawler
{
private readonly IBloomFilter _visitedUrls;
private readonly Queue<string> _urlQueue;
public WebCrawler(IBloomFilter bloomFilter)
{
_visitedUrls = bloomFilter;
_urlQueue = new Queue<string>();
}
public async Task CrawlAsync(string startUrl)
{
_urlQueue.Enqueue(startUrl);
while (_urlQueue.Count > 0)
{
var url = _urlQueue.Dequeue();
// Check if already visited
if (_visitedUrls.Contains(url))
{
continue; // Skip already visited URLs
}
// Mark as visited
_visitedUrls.Add(url);
// Download page
var page = await DownloadPageAsync(url);
// Process page
await ProcessPageAsync(page);
// Extract new URLs
var newUrls = ExtractUrls(page);
foreach (var newUrl in newUrls)
{
if (!_visitedUrls.Contains(newUrl))
{
_urlQueue.Enqueue(newUrl);
}
}
}
}
}
```
#### 3. Distributed Deduplication (Multiple Instances)
```csharp
// Configure distributed Bloom filter
services.AddBloomFilter(setupAction =>
{
setupAction.UseRedis(new FilterRedisOptions
{
Name = "GlobalDeduplication",
RedisKey = "BF:Dedup",
Endpoints = new List<string> { "redis-cluster:6379" },
ExpectedElements = 100_000_000,
ErrorRate = 0.0001
});
});
// Use across multiple service instances
public class MessageProcessor
{
private readonly IBloomFilter _bloomFilter;
public async Task ProcessMessageAsync(Message message)
{
// All instances share the same Redis Bloom filter
if (await _bloomFilter.ContainsAsync(message.Id))
{
// Message already processed by another instance
return;
}
// Mark as processed
await _bloomFilter.AddAsync(message.Id);
// Process message
await HandleMessageAsync(message);
}
}
```
## Hash Algorithms
BloomFilter.NetCore supports 20+ hash algorithms, choose based on performance and accuracy requirements:
### Algorithm Categories
| Category | Algorithms | Characteristics | Use Cases |
|----------|-----------|-----------------|-----------|
| **LCG-based** | LCGWithFNV1<br>LCGWithFNV1a<br>LCGModifiedFNV1 | Extremely fast, lower quality | Extremely high performance requirements, can tolerate high false positive rates |
| **RNG-based** | RNGWithFNV1<br>RNGWithFNV1a<br>RNGModifiedFNV1 | High quality, slower | Scenarios requiring high accuracy |
| **Checksum** | CRC32<br>CRC64<br>Adler32 | Balanced performance and quality | General scenarios |
| **Murmur Family** | Murmur3<br>Murmur32BitsX86<br>Murmur128BitsX64<br>Murmur128BitsX86 | **Recommended**, good performance, high quality | Recommended for production |
| **Cryptographic** | SHA1<br>SHA256<br>SHA384<br>SHA512 | Highest quality, slowest | Scenarios requiring extreme security |
| **XXHash Family** | XXHash32<br>XXHash64<br>XXHash3<br>XXHash128 | **Fastest**, excellent quality | First choice for high performance |
### Selection Recommendations
```csharp
// Recommended: Default Murmur3 for production (balanced performance and quality)
var bf1 = FilterBuilder.Build(10_000_000, 0.01, HashMethod.Murmur3);
// High Performance: Choose XXHash3 for extreme performance requirements
var bf2 = FilterBuilder.Build(10_000_000, 0.01, HashMethod.XXHash3);
// High Precision: Choose SHA256 + lower errorRate for minimal false positive rate
var bf3 = FilterBuilder.Build(10_000_000, 0.0001, HashMethod.SHA256);
// Distributed: Recommend XXHash64 for Redis (fast and good cross-language support)
var bf4 = FilterRedisBuilder.Build(
"localhost:6379",
"MyFilter",
10_000_000,
0.01,
HashMethod.XXHash64
);
```
## Performance Benchmarks
### Test Environment
```
BenchmarkDotNet=v0.13.5
OS: Windows 11 (10.0.22621.1778/22H2)
CPU: AMD Ryzen 7 5800X, 1 CPU, 16 logical cores, 8 physical cores
.NET SDK: 7.0.304
Runtime: .NET 7.0.7 (7.0.723.27404), X64 RyuJIT AVX2
```
### Performance Rankings (64-byte data)
| Rank | Algorithm | Mean Time | Relative Speed |
|------|-----------|-----------|----------------|
| 🥇 1 | XXHash3 | 33.14 ns | Baseline (Fastest) |
| 🥈 2 | XXHash128 | 36.01 ns | 1.09x |
| 🥉 3 | CRC64 | 38.83 ns | 1.17x |
| 4 | XXHash64 | 50.62 ns | 1.53x |
| 5 | Murmur3 | 70.98 ns | 2.14x |
| ... | ... | ... | ... |
| 28 | SHA512 | 1,368.20 ns | 41.28x (Slowest) |
### Complete Performance Data
<details>
<summary>Click to expand full benchmark results</summary>
#### 64-byte Data
| Algorithm | Mean Time | Error | StdDev | Allocated |
|-----------|-----------|-------|--------|-----------|
| XXHash3 | 33.14 ns | 0.295 ns | 0.276 ns | 80 B |
| XXHash128 | 36.01 ns | 0.673 ns | 0.749 ns | 80 B |
| CRC64 | 38.83 ns | 0.399 ns | 0.333 ns | 80 B |
| XXHash64 | 50.62 ns | 0.756 ns | 0.670 ns | 80 B |
| Murmur3 | 70.98 ns | 1.108 ns | 1.036 ns | 80 B |
| XXHash32 | 73.15 ns | 0.526 ns | 0.466 ns | 80 B |
| Murmur128BitsX64 | 80.15 ns | 0.783 ns | 0.653 ns | 120 B |
| Murmur128BitsX86 | 82.73 ns | 1.211 ns | 1.011 ns | 120 B |
| LCGWithFNV1 | 91.27 ns | 1.792 ns | 2.134 ns | 80 B |
| CRC32 | 145.63 ns | 1.528 ns | 1.429 ns | 328 B |
| Adler32 | 150.07 ns | 0.664 ns | 0.589 ns | 336 B |
| RNGWithFNV1 | 445.32 ns | 8.463 ns | 9.747 ns | 384 B |
| SHA256 | 922.30 ns | 4.478 ns | 3.739 ns | 496 B |
| SHA1 | 1,045.67 ns | 6.411 ns | 5.997 ns | 464 B |
| SHA384 | 1,173.67 ns | 5.050 ns | 3.942 ns | 456 B |
| SHA512 | 1,368.20 ns | 10.967 ns | 9.722 ns | 504 B |
#### 1 MB Data
| Algorithm | Mean Time |
|-----------|-----------|
| XXHash3 | 30,258.92 ns (~30 μs) |
| XXHash128 | 33,778.68 ns (~34 μs) |
| CRC64 | 56,321.74 ns (~56 μs) |
| XXHash64 | 100,570.79 ns (~101 μs) |
| Murmur128BitsX64 | 163,915.44 ns (~164 μs) |
| ... | ... |
| SHA1 | 3,381,425.73 ns (~3.4 ms) |
</details>
### Performance Recommendations
1. **General Scenarios**: Use `Murmur3` (default), balanced performance and quality
2. **Extreme Performance**: Use `XXHash3`, 2x faster than Murmur3
3. **Large Data**: Use `XXHash128` or `Murmur128BitsX64`, 128-bit output reduces collisions
4. **Avoid**: LCG series (poor quality), SHA series (too slow)
## Advanced Usage
### Serialization and Deserialization
```csharp
// Export Bloom filter state
var bf = FilterBuilder.Build(1_000_000, 0.01);
bf.Add("item1");
bf.Add("item2");
// Get internal state (for persistence)
var memory = (FilterMemory)bf;
var buckets = memory.Buckets; // BitArray[]
var bucketBytes = memory.BucketBytes; // byte[][]
// Restore Bloom filter from state
var options = new FilterMemoryOptions
{
Name = "RestoredFilter",
ExpectedElements = 1_000_000,
ErrorRate = 0.01,
Buckets = buckets // Or use BucketBytes
};
var restoredBf = FilterBuilder.Build(options);
Console.WriteLine(restoredBf.Contains("item1")); // True
```
### Batch Operations
```csharp
// Batch add
var items = Enumerable.Range(1, 10000)
.Select(i => Encoding.UTF8.GetBytes($"user:{i}"))
.ToArray();
var addResults = bf.Add(items);
Console.WriteLine($"Successfully added: {addResults.Count(r => r)} elements");
// Batch check
var checkResults = bf.Contains(items);
Console.WriteLine($"Exist: {checkResults.Count(r => r)} elements");
// Check if all elements exist
bool allExist = bf.All(items);
// Async batch operations
var asyncAddResults = await bf.AddAsync(items);
var asyncCheckResults = await bf.ContainsAsync(items);
bool asyncAllExist = await bf.AllAsync(items);
```
### Custom Hash Function
```csharp
using BloomFilter.HashAlgorithms;
// Implement custom hash algorithm
public class MyCustomHash : HashFunction
{
public override long ComputeHash(ReadOnlySpan<byte> data)
{
// Custom hash logic
long hash = 0;
foreach (var b in data)
{
hash = hash * 31 + b;
}
return hash;
}
}
// Use custom hash
var customHash = new MyCustomHash();
var bf = FilterBuilder.Build(1_000_000, 0.01, customHash);
```
### Calculate Actual False Positive Rate
```csharp
var bf = FilterBuilder.Build(100_000, 0.01);
// Add 50,000 elements
for (int i = 0; i < 50_000; i++)
{
bf.Add($"item:{i}");
}
// Calculate theoretical false positive rate
var filter = (Filter)bf;
double theoreticalErrorRate = Filter.BestP(
filter.Hashes,
filter.Capacity,
50_000
);
Console.WriteLine($"Theoretical error rate: {theoreticalErrorRate:P4}");
// Test actual false positive rate
int falsePositives = 0;
int testCount = 100_000;
for (int i = 50_000; i < 50_000 + testCount; i++)
{
if (bf.Contains($"item:{i}"))
{
falsePositives++;
}
}
double actualErrorRate = (double)falsePositives / testCount;
Console.WriteLine($"Actual error rate: {actualErrorRate:P4}");
Console.WriteLine($"False positives: {falsePositives} / {testCount}");
```
### Monitoring and Statistics
```csharp
public class BloomFilterMonitor
{
private readonly IBloomFilter _filter;
private long _addCount;
private long _hitCount;
private long _missCount;
public BloomFilterMonitor(IBloomFilter filter)
{
_filter = filter;
}
public bool Add(string item)
{
Interlocked.Increment(ref _addCount);
return _filter.Add(item);
}
public bool Contains(string item)
{
var result = _filter.Contains(item);
if (result)
Interlocked.Increment(ref _hitCount);
else
Interlocked.Increment(ref _missCount);
return result;
}
public void PrintStats()
{
Console.WriteLine($"Total adds: {_addCount}");
Console.WriteLine($"Hits: {_hitCount}");
Console.WriteLine($"Misses: {_missCount}");
Console.WriteLine($"Hit rate: {(double)_hitCount / (_hitCount + _missCount):P2}");
}
}
```
## API Reference
### IBloomFilter Interface
```csharp
public interface IBloomFilter : IDisposable
{
// Properties
string Name { get; }
// Synchronous methods
bool Add(ReadOnlySpan<byte> data);
IList<bool> Add(IEnumerable<byte[]> elements);
bool Contains(ReadOnlySpan<byte> element);
IList<bool> Contains(IEnumerable<byte[]> elements);
bool All(IEnumerable<byte[]> elements);
void Clear();
long[] ComputeHash(ReadOnlySpan<byte> data);
// Asynchronous methods
ValueTask<bool> AddAsync(ReadOnlyMemory<byte> data);
ValueTask<IList<bool>> AddAsync(IEnumerable<byte[]> elements);
ValueTask<bool> ContainsAsync(ReadOnlyMemory<byte> element);
ValueTask<IList<bool>> ContainsAsync(IEnumerable<byte[]> elements);
ValueTask<bool> AllAsync(IEnumerable<byte[]> elements);
ValueTask ClearAsync();
}
```
### Filter Base Class
```csharp
public abstract class Filter : IBloomFilter
{
// Properties
public string Name { get; }
public HashFunction Hash { get; }
public long Capacity { get; }
public int Hashes { get; }
public long ExpectedElements { get; }
public double ErrorRate { get; }
// Static methods (mathematical calculations)
public static long BestM(long n, double p);
public static int BestK(long n, long m);
public static long BestN(int k, long m);
public static double BestP(int k, long m, long insertedElements);
}
```
### FilterBuilder
```csharp
public static class FilterBuilder
{
// Using expected elements and error rate
public static IBloomFilter Build(long expectedElements, double errorRate);
public static IBloomFilter Build(long expectedElements, double errorRate, HashMethod method);
public static IBloomFilter Build(long expectedElements, double errorRate, HashFunction hash);
// Using capacity and number of hash functions
public static IBloomFilter Build(long capacity, int hashes, HashMethod method);
public static IBloomFilter Build(long capacity, int hashes, HashFunction hash);
// Using configuration object
public static IBloomFilter Build(FilterMemoryOptions options);
}
```
### FilterRedisBuilder
```csharp
public static class FilterRedisBuilder
{
public static IBloomFilter Build(
string redisHost,
string name,
long expectedElements,
double errorRate,
HashMethod method = HashMethod.Murmur3);
}
```
### Extension Methods
```csharp
// Service registration
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddBloomFilter(
this IServiceCollection services,
Action<BloomFilterOptions> setupAction);
}
// Configuration extensions
public static class BloomFilterOptionsExtensions
{
public static BloomFilterOptions UseInMemory(
this BloomFilterOptions options,
Action<FilterMemoryOptions> setup = null);
public static BloomFilterOptions UseRedis(
this BloomFilterOptions options,
FilterRedisOptions setup);
public static BloomFilterOptions UseCSRedis(
this BloomFilterOptions options,
FilterCSRedisOptions setup);
public static BloomFilterOptions UseFreeRedis(
this BloomFilterOptions options,
FilterFreeRedisOptions setup);
public static BloomFilterOptions UseEasyCachingRedis(
this BloomFilterOptions options,
FilterEasyCachingRedisOptions setup);
}
```
## Frequently Asked Questions (FAQ)
### 1. What is the false positive rate of a Bloom filter?
The false positive rate is determined by the `errorRate` parameter you specify when creating the filter. For example:
```csharp
// 1% false positive rate
var bf = FilterBuilder.Build(1_000_000, 0.01);
// 0.1% false positive rate (more accurate, but uses more memory)
var bf2 = FilterBuilder.Build(1_000_000, 0.001);
```
**Note**: Lower error rates require more memory space.
### 2. How to choose expectedElements?
`expectedElements` should be set to the number of elements you expect to add. If the actual number exceeds this, the false positive rate will increase.
Recommendations:
- Estimate actual element count
- Add 20%-50% buffer
- Monitor actual false positive rate regularly
### 3. In-Memory vs Redis Mode - How to Choose?
| Scenario | Recommended Mode | Reason |
|----------|-----------------|---------|
| Single-instance application | In-Memory | Highest performance, no network overhead |
| Multi-instance application | Redis | Shared state, distributed support |
| Persistence required | Redis | Redis provides persistence |
| Temporary deduplication | In-Memory | Simple and fast |
| Cross-service sharing | Redis | Multi-language access support |
### 4. How to clear a Bloom filter?
```csharp
// Synchronous clear
bf.Clear();
// Asynchronous clear
await bf.ClearAsync();
```
**Note**: Clear operation deletes all data, use with caution!
### 5. How much memory does a Bloom filter use?
Memory usage depends on capacity (m):
```
Memory (bytes) = m / 8
```
Example calculation:
```csharp
// 10 million elements, 1% false positive rate
var bf = FilterBuilder.Build(10_000_000, 0.01);
var filter = (Filter)bf;
// Calculate memory usage
long bits = filter.Capacity;
long bytes = bits / 8;
double mb = bytes / (1024.0 * 1024.0);
Console.WriteLine($"Bit array size: {bits:N0} bits");
Console.WriteLine($"Memory usage: {bytes:N0} bytes ({mb:F2} MB)");
// Output: approximately 11.4 MB
```
### 6. Can elements be deleted?
**No**. Standard Bloom filters do not support deletion because:
- Multiple elements may map to the same bits
- Deleting one element may affect detection of other elements
If deletion is needed, consider:
- Counting Bloom Filter
- Cuckoo Filter
### 7. Is it thread-safe?
Yes, BloomFilter.NetCore is thread-safe:
```csharp
// Multi-threaded concurrent access
var bf = FilterBuilder.Build(10_000_000, 0.01);
Parallel.For(0, 1000, i =>
{
bf.Add($"item:{i}"); // Thread-safe
});
Parallel.For(0, 1000, i =>
{
var exists = bf.Contains($"item:{i}"); // Thread-safe
});
```
### 8. How to monitor Redis connections?
```csharp
// Use StackExchange.Redis connection monitoring
services.AddBloomFilter(setupAction =>
{
setupAction.UseRedis(new FilterRedisOptions
{
Name = "MyFilter",
RedisKey = "BF:Key",
Endpoints = new List<string> { "localhost:6379" },
// Enable connection logging
AbortOnConnectFail = false,
ConnectTimeout = 5000,
ConnectRetry = 3
});
});
// Get Redis connection information
var bf = serviceProvider.GetService<IBloomFilter>();
if (bf is FilterRedis redisFilter)
{
var connection = redisFilter.Connection;
Console.WriteLine($"Connection status: {connection.IsConnected}");
Console.WriteLine($"Endpoints: {string.Join(", ", connection.GetEndPoints())}");
}
```
## Contributing
We welcome community contributions!
### How to Contribute
1. Fork this repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Create a Pull Request
### Development Guidelines
```bash
# Clone repository
git clone https://github.com/vla/BloomFilter.NetCore.git
cd BloomFilter.NetCore
# Restore dependencies
dotnet restore
# Build project
dotnet build
# Run tests
dotnet test
# Run benchmarks
cd test/BenchmarkTest
dotnet run -c Release
```
### Code Standards
- Follow C# coding conventions
- Add XML documentation comments
- Write unit tests
- Update relevant documentation
## Acknowledgments
Thanks to all developers who contributed to this project!
Special thanks to:
- .NET Foundation
- StackExchange.Redis team
- All dependency library authors
If this project helps you, please give us a ⭐️ Star!
================================================
FILE: README.zh-CN.md
================================================
# BloomFilter.NetCore
[](https://opensource.org/licenses/MIT)
[](https://dotnet.microsoft.com/)
一个高性能、功能完整的 .NET 布隆过滤器实现库,支持内存存储和多种 Redis 分布式后端。
## 目录
- [项目概述](#项目概述)
- [主要特性](#主要特性)
- [包和状态](#包和状态)
- [整体架构](#整体架构)
- [核心功能](#核心功能)
- [安装](#安装)
- [快速开始](#快速开始)
- [使用示例](#使用示例)
- [内存模式](#内存模式)
- [依赖注入配置](#依赖注入配置)
- [Redis 分布式模式](#redis-分布式模式)
- [哈希算法](#哈希算法)
- [性能基准测试](#性能基准测试)
- [高级用法](#高级用法)
- [API 参考](#api-参考)
- [贡献指南](#贡献指南)
- [许可证](#许可证)
## 项目概述
BloomFilter.NetCore 是一个企业级的布隆过滤器库,专为 .NET 生态系统设计。布隆过滤器是一种空间效率极高的概率型数据结构,用于测试一个元素是否属于一个集合。它的核心特点是:
- **空间高效**: 相比传统的 HashSet,占用空间极小
- **时间复杂度 O(1)**: 添加和查询操作都是常数时间
- **允许一定误报率**: 可能返回假阳性(false positive),但绝不会出现假阴性(false negative)
本项目提供了两大类实现:
1. **内存布隆过滤器 (FilterMemory)**: 基于 BitArray 的内存实现,适用于单进程场景
2. **分布式布隆过滤器 (FilterRedis 系列)**: 基于 Redis 的分布式实现,支持多应用程序并发访问
### 主要用途
- **缓存穿透防护**: 防止恶意查询不存在的数据导致缓存击穿
- **去重场景**: URL 去重、邮箱去重、用户 ID 去重等
- **推荐系统**: 判断用户是否已看过某个内容
- **爬虫系统**: 判断 URL 是否已被爬取
- **分布式系统**: 多服务实例间共享状态判断
- **大数据场景**: 海量数据的存在性判断
## 主要特性
### 🎯 灵活配置
- **参数完全可配置**: 位数组大小 (m)、哈希函数数量 (k)
- **自动参数计算**: 根据容忍的误报率 (p) 和预期元素数量 (n) 自动计算最优参数
- **20+ 种哈希算法**: 支持 CRC、MD5、SHA、Murmur、LCGs、xxHash 等或自定义算法
### ⚡ 高性能
- **快速生成**: 布隆过滤器的生成和操作都极快
- **优化实现**: 使用 Span<T>、ReadOnlyMemory<T> 等零拷贝技术
- **不安全代码优化**: 在性能关键路径使用 unsafe 代码块
- **拒绝采样**: 实现了拒绝采样和哈希链,考虑雪崩效应以提高哈希质量
### 🔒 并发安全
- **线程安全**: 使用 AsyncLock 机制确保多线程并发访问安全
- **异步支持**: 全面的 async/await 支持,所有操作都有异步版本
- **分布式锁**: Redis 实现支持跨应用程序的并发访问
### 🌐 多后端支持
- **StackExchange.Redis**: 官方推荐的 Redis 客户端
- **CSRedisCore**: 高性能的 Redis 客户端
- **FreeRedis**: 轻量级 Redis 客户端
- **EasyCaching**: 支持 EasyCaching 抽象层,可切换多种缓存提供程序
### 📦 现代 .NET 支持
- **多框架支持**: net462, netstandard2.0, net6.0, net7.0, net8.0, net9.0, net10.0
- **依赖注入**: 原生支持 Microsoft.Extensions.DependencyInjection
- **可空引用类型**: 启用可空引用类型,提高代码安全性
## 包和状态
| 包名 | NuGet | 说明 |
|------|-------|------|
|**BloomFilter.NetCore**|[](https://www.nuget.org/packages/BloomFilter.NetCore)| 核心包,提供内存布隆过滤器 |
|**BloomFilter.Redis.NetCore**|[](https://www.nuget.org/packages/BloomFilter.Redis.NetCore)| StackExchange.Redis 实现 |
|**BloomFilter.CSRedis.NetCore**|[](https://www.nuget.org/packages/BloomFilter.CSRedis.NetCore)| CSRedisCore 实现 |
|**BloomFilter.FreeRedis.NetCore**|[](https://www.nuget.org/packages/BloomFilter.FreeRedis.NetCore)| FreeRedis 实现 |
|**BloomFilter.EasyCaching.NetCore**|[](https://www.nuget.org/packages/BloomFilter.EasyCaching.NetCore)| EasyCaching 集成 |
## 整体架构
### 核心接口层
```
IBloomFilter (接口)
├── Add / AddAsync - 添加元素
├── Contains / ContainsAsync - 检查元素
├── All / AllAsync - 批量检查
├── Clear / ClearAsync - 清空过滤器
└── ComputeHash - 计算哈希值
```
### 实现层次结构
```
Filter (抽象基类)
├── FilterMemory (内存实现)
│ └── 使用 BitArray 存储
│
└── Redis 系列 (分布式实现)
├── FilterRedis (StackExchange.Redis)
├── FilterCSRedis (CSRedisCore)
├── FilterFreeRedis (FreeRedis)
└── FilterEasyCachingRedis (EasyCaching)
```
### 配置系统
```
BloomFilterOptions
├── FilterMemoryOptions - 内存模式配置
├── FilterRedisOptions - StackExchange.Redis 配置
├── FilterCSRedisOptions - CSRedisCore 配置
├── FilterFreeRedisOptions - FreeRedis 配置
└── FilterEasyCachingOptions - EasyCaching 配置
```
## 核心功能
### 数学模型
BloomFilter.NetCore 实现了完整的布隆过滤器数学模型:
#### 1. 最优位数组大小 (m)
给定预期元素数 `n` 和误报率 `p`,计算最优的位数组大小:
```
m = -(n * ln(p)) / (ln(2)^2)
```
#### 2. 最优哈希函数数量 (k)
给定元素数 `n` 和位数组大小 `m`,计算最优的哈希函数数量:
```
k = (m / n) * ln(2)
```
#### 3. 实际误报率 (p)
给定已插入元素数、哈希函数数量和位数组大小,计算实际误报率:
```
p = (1 - e^(-k*n/m))^k
```
这些计算由 `Filter` 基类提供的静态方法实现:
```csharp
// 计算最优位数组大小
long m = Filter.BestM(expectedElements, errorRate);
// 计算最优哈希函数数量
int k = Filter.BestK(expectedElements, capacity);
// 计算最优元素数量
long n = Filter.BestN(hashes, capacity);
// 计算实际误报率
double p = Filter.BestP(hashes, capacity, insertedElements);
```
### 存储机制
#### 内存存储
- **BitArray**: 使用 .NET 的 BitArray 作为底层存储
- **分桶策略**: 当容量超过 2GB (MaxInt = 2,147,483,640) 时,自动分成多个 BitArray
- **序列化支持**: 支持序列化/反序列化以持久化或传输过滤器状态
#### Redis 存储
- **SETBIT/GETBIT**: 使用 Redis 的位操作命令
- **分布式访问**: 多个应用实例可以并发访问同一个过滤器
- **持久化**: 利用 Redis 的持久化机制保证数据安全
### 并发控制
```csharp
// AsyncLock 确保线程安全
public class AsyncLock
{
private readonly SemaphoreSlim _semaphore = new(1, 1);
public async ValueTask<IDisposable> LockAsync()
{
await _semaphore.WaitAsync();
return new Release(_semaphore);
}
}
```
## 安装
### 通过 NuGet 安装
**内存模式 (核心包):**
```bash
dotnet add package BloomFilter.NetCore
```
**Redis 分布式模式 (选择一个):**
```bash
# StackExchange.Redis
dotnet add package BloomFilter.Redis.NetCore
# CSRedisCore
dotnet add package BloomFilter.CSRedis.NetCore
# FreeRedis
dotnet add package BloomFilter.FreeRedis.NetCore
# EasyCaching
dotnet add package BloomFilter.EasyCaching.NetCore
```
## 快速开始
### 最简单的示例
```csharp
using BloomFilter;
// 创建一个布隆过滤器:预期 1000 万元素,1% 误报率
var bf = FilterBuilder.Build(10_000_000, 0.01);
// 添加元素
bf.Add("user:123");
bf.Add("user:456");
// 检查元素是否存在
Console.WriteLine(bf.Contains("user:123")); // True
Console.WriteLine(bf.Contains("user:789")); // False (可能极小概率为 True)
// 清空过滤器
bf.Clear();
```
### 异步操作
```csharp
// 异步添加
await bf.AddAsync(Encoding.UTF8.GetBytes("user:123"));
// 异步检查
bool exists = await bf.ContainsAsync(Encoding.UTF8.GetBytes("user:123"));
// 批量异步操作
var users = new[] {
Encoding.UTF8.GetBytes("user:1"),
Encoding.UTF8.GetBytes("user:2"),
Encoding.UTF8.GetBytes("user:3")
};
await bf.AddAsync(users);
var results = await bf.ContainsAsync(users);
```
### Fluent API(v3.0 新增)
v3.0 引入了现代化的流式 API,提供更好的可发现性和表达力:
```csharp
// 内存模式 Fluent API
var filter = FilterBuilder.Create()
.WithName("UserFilter")
.ExpectingElements(10_000_000)
.WithErrorRate(0.001)
.UsingHashMethod(HashMethod.XXHash3)
.BuildInMemory();
// Redis Fluent API (StackExchange.Redis)
var redisFilter = FilterRedisBuilder.Create()
.WithRedisConnection("localhost:6379")
.WithRedisKey("bloom:users")
.WithName("UserFilter")
.ExpectingElements(10_000_000)
.WithErrorRate(0.001)
.BuildRedis();
// CSRedis Fluent API
var csredisFilter = FilterCSRedisBuilder.Create()
.WithRedisClient(csredisClient)
.WithRedisKey("bloom:users")
.ExpectingElements(10_000_000)
.BuildCSRedis();
// FreeRedis Fluent API
var freeRedisFilter = FilterFreeRedisBuilder.Create()
.WithRedisClient(redisClient)
.WithRedisKey("bloom:users")
.ExpectingElements(10_000_000)
.BuildFreeRedis();
// EasyCaching Fluent API
var easyCachingFilter = FilterEasyCachingBuilder.Create()
.WithRedisCachingProvider(provider)
.WithRedisKey("bloom:users")
.ExpectingElements(10_000_000)
.BuildEasyCaching();
// 所有通用配置方法:
// - WithName(string) - 设置过滤器名称
// - ExpectingElements(long) - 设置预期元素数量
// - WithErrorRate(double) - 设置误报率 (0-1)
// - UsingHashMethod(HashMethod) - 使用预定义哈希算法
// - UsingCustomHash(HashFunction) - 使用自定义哈希函数
// - WithSerializer(IFilterMemorySerializer) - 设置自定义序列化器(仅内存模式)
```
**为什么使用 Fluent API?**
- 🔍 通过 IntelliSense 更好的可发现性
- 📖 代码更易读、更自文档化
- ⛓️ 可链式调用方法
- 🎯 类型安全的配置
- ✅ 向后兼容 - 旧的静态方法仍然可用!
## 使用示例
### 内存模式
#### 基本用法
```csharp
using BloomFilter;
public class UserService
{
// 静态共享的布隆过滤器
private static readonly IBloomFilter _bloomFilter =
FilterBuilder.Build(10_000_000, 0.01);
public void AddUser(string userId)
{
// 添加用户 ID
_bloomFilter.Add(userId);
}
public bool MayExistUser(string userId)
{
// 检查用户是否可能存在
return _bloomFilter.Contains(userId);
}
}
```
#### 自定义配置
```csharp
using BloomFilter;
// 方式 1: 指定哈希算法
var bf1 = FilterBuilder.Build(
expectedElements: 1_000_000,
errorRate: 0.001,
hashMethod: HashMethod.Murmur3
);
// 方式 2: 使用自定义哈希函数
var hashFunction = new Murmur128BitsX64();
var bf2 = FilterBuilder.Build(
expectedElements: 1_000_000,
errorRate: 0.001,
hashFunction: hashFunction
);
// 方式 3: 手动指定参数 (高级用法)
var bf3 = FilterBuilder.Build(
capacity: 9585059, // 位数组大小
hashes: 10, // 哈希函数数量
hashMethod: HashMethod.XXHash3
);
// 方式 4: 使用配置对象
var options = new FilterMemoryOptions
{
Name = "MyFilter",
ExpectedElements = 5_000_000,
ErrorRate = 0.01,
Method = HashMethod.Murmur3
};
var bf4 = FilterBuilder.Build(options);
```
### 依赖注入配置
#### ASP.NET Core 集成
```csharp
using BloomFilter;
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// 注册布隆过滤器服务
services.AddBloomFilter(setupAction =>
{
setupAction.UseInMemory(options =>
{
options.Name = "MainFilter";
options.ExpectedElements = 10_000_000;
options.ErrorRate = 0.01;
options.Method = HashMethod.Murmur3;
});
});
services.AddControllers();
}
}
// 在控制器或服务中使用
public class UserController : ControllerBase
{
private readonly IBloomFilter _bloomFilter;
public UserController(IBloomFilter bloomFilter)
{
_bloomFilter = bloomFilter;
}
[HttpPost("users/{userId}")]
public IActionResult CheckUser(string userId)
{
if (_bloomFilter.Contains(userId))
{
// 用户可能存在,继续查询数据库
return Ok("用户可能存在");
}
else
{
// 用户一定不存在,无需查询数据库
return NotFound("用户不存在");
}
}
}
```
#### 多个过滤器实例
```csharp
services.AddBloomFilter(setupAction =>
{
// 用户过滤器
setupAction.UseInMemory(options =>
{
options.Name = "UserFilter";
options.ExpectedElements = 10_000_000;
options.ErrorRate = 0.01;
});
// 邮箱过滤器
setupAction.UseInMemory(options =>
{
options.Name = "EmailFilter";
options.ExpectedElements = 5_000_000;
options.ErrorRate = 0.001;
});
});
// 使用工厂获取指定过滤器
public class MyService
{
private readonly IBloomFilter _userFilter;
private readonly IBloomFilter _emailFilter;
public MyService(IBloomFilterFactory factory)
{
_userFilter = factory.Get("UserFilter");
_emailFilter = factory.Get("EmailFilter");
}
}
```
### Redis 分布式模式
#### StackExchange.Redis
```csharp
using BloomFilter;
// 方式 1: 直接构建
var bf = FilterRedisBuilder.Build(
redisHost: "localhost:6379",
name: "DistributedFilter",
expectedElements: 5_000_000,
errorRate: 0.001
);
bf.Add("item:123");
Console.WriteLine(bf.Contains("item:123")); // True
// 方式 2: 依赖注入
services.AddBloomFilter(setupAction =>
{
setupAction.UseRedis(new FilterRedisOptions
{
Name = "UserFilter",
RedisKey = "BloomFilter:Users",
Endpoints = new List<string> { "localhost:6379" },
Database = 0,
ExpectedElements = 10_000_000,
ErrorRate = 0.01,
Method = HashMethod.Murmur3
});
});
// 方式 3: 高级配置 (主从、哨兵、集群)
services.AddBloomFilter(setupAction =>
{
setupAction.UseRedis(new FilterRedisOptions
{
Name = "ProductFilter",
RedisKey = "BloomFilter:Products",
Endpoints = new List<string>
{
"redis-master:6379",
"redis-slave1:6379",
"redis-slave2:6379"
},
Password = "your-redis-password",
Ssl = true,
ConnectTimeout = 5000,
SyncTimeout = 3000,
ExpectedElements = 20_000_000,
ErrorRate = 0.001
});
});
```
#### CSRedisCore
```csharp
services.AddBloomFilter(setupAction =>
{
setupAction.UseCSRedis(new FilterCSRedisOptions
{
Name = "OrderFilter",
RedisKey = "BloomFilter:Orders",
ConnectionStrings = new List<string>
{
"localhost:6379,password=123456,defaultDatabase=0,poolsize=50,prefix=myapp:"
},
ExpectedElements = 5_000_000,
ErrorRate = 0.01
});
});
```
#### FreeRedis
```csharp
services.AddBloomFilter(setupAction =>
{
setupAction.UseFreeRedis(new FilterFreeRedisOptions
{
Name = "CartFilter",
RedisKey = "BloomFilter:Carts",
ConnectionStrings = new List<string> { "localhost:6379,password=123456" },
ExpectedElements = 1_000_000,
ErrorRate = 0.01
});
});
```
#### EasyCaching 集成
EasyCaching 提供了统一的缓存抽象层,允许您轻松切换底层缓存实现:
```csharp
using EasyCaching.Core.Configurations;
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
// 1. 配置 EasyCaching
services.AddEasyCaching(options =>
{
// 配置 Redis 提供程序
options.UseRedis(config =>
{
config.DBConfig.Endpoints.Add(new ServerEndPoint("127.0.0.1", 6379));
config.DBConfig.Database = 0;
}, "redis-provider-1");
// 可以配置多个提供程序
options.UseRedis(config =>
{
config.DBConfig.Endpoints.Add(new ServerEndPoint("127.0.0.1", 6379));
config.DBConfig.Database = 1;
}, "redis-provider-2");
});
// 2. 配置 BloomFilter
services.AddBloomFilter(setupAction =>
{
// 使用第一个 Redis 提供程序
setupAction.UseEasyCachingRedis(new FilterEasyCachingRedisOptions
{
Name = "BF1",
RedisKey = "BloomFilter1",
ProviderName = "redis-provider-1",
ExpectedElements = 10_000_000,
ErrorRate = 0.01
});
// 使用第二个 Redis 提供程序
setupAction.UseEasyCachingRedis(new FilterEasyCachingRedisOptions
{
Name = "BF2",
RedisKey = "BloomFilter2",
ProviderName = "redis-provider-2",
ExpectedElements = 5_000_000,
ErrorRate = 0.001
});
});
var provider = services.BuildServiceProvider();
// 使用默认过滤器
var bf = provider.GetService<IBloomFilter>();
bf.Add("value1");
// 使用指定名称的过滤器
var factory = provider.GetService<IBloomFilterFactory>();
var bf1 = factory.Get("BF1");
var bf2 = factory.Get("BF2");
bf1.Add("item1");
bf2.Add("item2");
```
### 实际应用场景
#### 1. 防止缓存穿透
```csharp
public class ProductService
{
private readonly IBloomFilter _bloomFilter;
private readonly ICache _cache;
private readonly IProductRepository _repository;
public ProductService(
IBloomFilter bloomFilter,
ICache cache,
IProductRepository repository)
{
_bloomFilter = bloomFilter;
_cache = cache;
_repository = repository;
}
public async Task<Product> GetProductAsync(string productId)
{
// 第一层防护: 布隆过滤器
if (!_bloomFilter.Contains(productId))
{
// 商品一定不存在,直接返回 null
return null;
}
// 第二层: 缓存
var cached = await _cache.GetAsync<Product>(productId);
if (cached != null)
{
return cached;
}
// 第三层: 数据库
var product = await _repository.GetByIdAsync(productId);
if (product != null)
{
await _cache.SetAsync(productId, product);
}
return product;
}
public async Task CreateProductAsync(Product product)
{
// 保存到数据库
await _repository.SaveAsync(product);
// 添加到布隆过滤器
_bloomFilter.Add(product.Id);
// 更新缓存
await _cache.SetAsync(product.Id, product);
}
}
```
#### 2. URL 去重 (爬虫系统)
```csharp
public class WebCrawler
{
private readonly IBloomFilter _visitedUrls;
private readonly Queue<string> _urlQueue;
public WebCrawler(IBloomFilter bloomFilter)
{
_visitedUrls = bloomFilter;
_urlQueue = new Queue<string>();
}
public async Task CrawlAsync(string startUrl)
{
_urlQueue.Enqueue(startUrl);
while (_urlQueue.Count > 0)
{
var url = _urlQueue.Dequeue();
// 检查是否已访问
if (_visitedUrls.Contains(url))
{
continue; // 跳过已访问的 URL
}
// 标记为已访问
_visitedUrls.Add(url);
// 抓取页面
var page = await DownloadPageAsync(url);
// 处理页面
await ProcessPageAsync(page);
// 提取新的 URL
var newUrls = ExtractUrls(page);
foreach (var newUrl in newUrls)
{
if (!_visitedUrls.Contains(newUrl))
{
_urlQueue.Enqueue(newUrl);
}
}
}
}
}
```
#### 3. 分布式去重 (多实例)
```csharp
// 配置分布式布隆过滤器
services.AddBloomFilter(setupAction =>
{
setupAction.UseRedis(new FilterRedisOptions
{
Name = "GlobalDeduplication",
RedisKey = "BF:Dedup",
Endpoints = new List<string> { "redis-cluster:6379" },
ExpectedElements = 100_000_000,
ErrorRate = 0.0001
});
});
// 在多个服务实例中使用
public class MessageProcessor
{
private readonly IBloomFilter _bloomFilter;
public async Task ProcessMessageAsync(Message message)
{
// 所有实例共享同一个 Redis 布隆过滤器
if (await _bloomFilter.ContainsAsync(message.Id))
{
// 消息已被其他实例处理
return;
}
// 标记为已处理
await _bloomFilter.AddAsync(message.Id);
// 处理消息
await HandleMessageAsync(message);
}
}
```
## 哈希算法
BloomFilter.NetCore 支持 20+ 种哈希算法,可根据性能和准确性需求选择:
### 算法分类
| 类别 | 算法 | 特点 | 适用场景 |
|------|------|------|----------|
| **LCG 类** | LCGWithFNV1<br>LCGWithFNV1a<br>LCGModifiedFNV1 | 极快,但质量较低 | 性能要求极高,可容忍高误报率 |
| **RNG 类** | RNGWithFNV1<br>RNGWithFNV1a<br>RNGModifiedFNV1 | 质量高,但较慢 | 对准确性要求高的场景 |
| **校验和** | CRC32<br>CRC64<br>Adler32 | 平衡性能和质量 | 通用场景 |
| **Murmur 系列** | Murmur3<br>Murmur32BitsX86<br>Murmur128BitsX64<br>Murmur128BitsX86 | **推荐**,性能好,质量高 | 生产环境推荐 |
| **加密哈希** | SHA1<br>SHA256<br>SHA384<br>SHA512 | 质量最高,但最慢 | 安全性要求极高的场景 |
| **XXHash 系列** | XXHash32<br>XXHash64<br>XXHash3<br>XXHash128 | **最快**,质量优秀 | 高性能场景首选 |
### 选择建议
```csharp
// 推荐: 生产环境默认选择 Murmur3 (平衡性能和质量)
var bf1 = FilterBuilder.Build(10_000_000, 0.01, HashMethod.Murmur3);
// 高性能: 对性能要求极高,选择 XXHash3
var bf2 = FilterBuilder.Build(10_000_000, 0.01, HashMethod.XXHash3);
// 高精度: 对误报率要求极低,选择 SHA256 + 更低的 errorRate
var bf3 = FilterBuilder.Build(10_000_000, 0.0001, HashMethod.SHA256);
// 分布式: Redis 场景推荐 XXHash64 (速度快且跨语言支持好)
var bf4 = FilterRedisBuilder.Build(
"localhost:6379",
"MyFilter",
10_000_000,
0.01,
HashMethod.XXHash64
);
```
## 性能基准测试
### 测试环境
```
BenchmarkDotNet=v0.13.5
OS: Windows 11 (10.0.22621.1778/22H2)
CPU: AMD Ryzen 7 5800X, 1 CPU, 16 logical cores, 8 physical cores
.NET SDK: 7.0.304
Runtime: .NET 7.0.7 (7.0.723.27404), X64 RyuJIT AVX2
```
### 性能排名 (64 字节数据)
| 排名 | 算法 | 平均时间 | 相对速度 |
|------|------|----------|----------|
| 🥇 1 | XXHash3 | 33.14 ns | 基准 (最快) |
| 🥈 2 | XXHash128 | 36.01 ns | 1.09x |
| 🥉 3 | CRC64 | 38.83 ns | 1.17x |
| 4 | XXHash64 | 50.62 ns | 1.53x |
| 5 | Murmur3 | 70.98 ns | 2.14x |
| ... | ... | ... | ... |
| 28 | SHA512 | 1,368.20 ns | 41.28x (最慢) |
### 完整性能数据
<details>
<summary>点击展开完整基准测试结果</summary>
#### 64 字节数据
| 算法 | 平均时间 | 误差 | 标准差 | 内存分配 |
|------|---------|------|--------|---------|
| XXHash3 | 33.14 ns | 0.295 ns | 0.276 ns | 80 B |
| XXHash128 | 36.01 ns | 0.673 ns | 0.749 ns | 80 B |
| CRC64 | 38.83 ns | 0.399 ns | 0.333 ns | 80 B |
| XXHash64 | 50.62 ns | 0.756 ns | 0.670 ns | 80 B |
| Murmur3 | 70.98 ns | 1.108 ns | 1.036 ns | 80 B |
| XXHash32 | 73.15 ns | 0.526 ns | 0.466 ns | 80 B |
| Murmur128BitsX64 | 80.15 ns | 0.783 ns | 0.653 ns | 120 B |
| Murmur128BitsX86 | 82.73 ns | 1.211 ns | 1.011 ns | 120 B |
| LCGWithFNV1 | 91.27 ns | 1.792 ns | 2.134 ns | 80 B |
| CRC32 | 145.63 ns | 1.528 ns | 1.429 ns | 328 B |
| Adler32 | 150.07 ns | 0.664 ns | 0.589 ns | 336 B |
| RNGWithFNV1 | 445.32 ns | 8.463 ns | 9.747 ns | 384 B |
| SHA256 | 922.30 ns | 4.478 ns | 3.739 ns | 496 B |
| SHA1 | 1,045.67 ns | 6.411 ns | 5.997 ns | 464 B |
| SHA384 | 1,173.67 ns | 5.050 ns | 3.942 ns | 456 B |
| SHA512 | 1,368.20 ns | 10.967 ns | 9.722 ns | 504 B |
#### 1 MB 数据
| 算法 | 平均时间 |
|------|---------|
| XXHash3 | 30,258.92 ns (~30 μs) |
| XXHash128 | 33,778.68 ns (~34 μs) |
| CRC64 | 56,321.74 ns (~56 μs) |
| XXHash64 | 100,570.79 ns (~101 μs) |
| Murmur128BitsX64 | 163,915.44 ns (~164 μs) |
| ... | ... |
| SHA1 | 3,381,425.73 ns (~3.4 ms) |
</details>
### 性能建议
1. **通用场景**: 使用 `Murmur3` (默认),性能和质量平衡
2. **极限性能**: 使用 `XXHash3`,比 Murmur3 快 2 倍
3. **大数据**: 使用 `XXHash128` 或 `Murmur128BitsX64`,128 位输出减少碰撞
4. **避免使用**: LCG 系列 (质量差)、SHA 系列 (太慢)
## 高级用法
### 序列化和反序列化
```csharp
// 导出布隆过滤器状态
var bf = FilterBuilder.Build(1_000_000, 0.01);
bf.Add("item1");
bf.Add("item2");
// 获取内部状态 (用于持久化)
var memory = (FilterMemory)bf;
var buckets = memory.Buckets; // BitArray[]
var bucketBytes = memory.BucketBytes; // byte[][]
// 从状态恢复布隆过滤器
var options = new FilterMemoryOptions
{
Name = "RestoredFilter",
ExpectedElements = 1_000_000,
ErrorRate = 0.01,
Buckets = buckets // 或使用 BucketBytes
};
var restoredBf = FilterBuilder.Build(options);
Console.WriteLine(restoredBf.Contains("item1")); // True
```
### 批量操作
```csharp
// 批量添加
var items = Enumerable.Range(1, 10000)
.Select(i => Encoding.UTF8.GetBytes($"user:{i}"))
.ToArray();
var addResults = bf.Add(items);
Console.WriteLine($"成功添加: {addResults.Count(r => r)} 个元素");
// 批量检查
var checkResults = bf.Contains(items);
Console.WriteLine($"存在: {checkResults.Count(r => r)} 个元素");
// 检查所有元素是否都存在
bool allExist = bf.All(items);
// 异步批量操作
var asyncAddResults = await bf.AddAsync(items);
var asyncCheckResults = await bf.ContainsAsync(items);
bool asyncAllExist = await bf.AllAsync(items);
```
### 自定义哈希函数
```csharp
using BloomFilter.HashAlgorithms;
// 实现自定义哈希算法
public class MyCustomHash : HashFunction
{
public override long ComputeHash(ReadOnlySpan<byte> data)
{
// 自定义哈希逻辑
long hash = 0;
foreach (var b in data)
{
hash = hash * 31 + b;
}
return hash;
}
}
// 使用自定义哈希
var customHash = new MyCustomHash();
var bf = FilterBuilder.Build(1_000_000, 0.01, customHash);
```
### 计算实际误报率
```csharp
var bf = FilterBuilder.Build(100_000, 0.01);
// 添加 50,000 个元素
for (int i = 0; i < 50_000; i++)
{
bf.Add($"item:{i}");
}
// 计算理论误报率
var filter = (Filter)bf;
double theoreticalErrorRate = Filter.BestP(
filter.Hashes,
filter.Capacity,
50_000
);
Console.WriteLine($"理论误报率: {theoreticalErrorRate:P4}");
// 测试实际误报率
int falsePositives = 0;
int testCount = 100_000;
for (int i = 50_000; i < 50_000 + testCount; i++)
{
if (bf.Contains($"item:{i}"))
{
falsePositives++;
}
}
double actualErrorRate = (double)falsePositives / testCount;
Console.WriteLine($"实际误报率: {actualErrorRate:P4}");
Console.WriteLine($"误报数量: {falsePositives} / {testCount}");
```
### 监控和统计
```csharp
public class BloomFilterMonitor
{
private readonly IBloomFilter _filter;
private long _addCount;
private long _hitCount;
private long _missCount;
public BloomFilterMonitor(IBloomFilter filter)
{
_filter = filter;
}
public bool Add(string item)
{
Interlocked.Increment(ref _addCount);
return _filter.Add(item);
}
public bool Contains(string item)
{
var result = _filter.Contains(item);
if (result)
Interlocked.Increment(ref _hitCount);
else
Interlocked.Increment(ref _missCount);
return result;
}
public void PrintStats()
{
Console.WriteLine($"总添加: {_addCount}");
Console.WriteLine($"命中: {_hitCount}");
Console.WriteLine($"未命中: {_missCount}");
Console.WriteLine($"命中率: {(double)_hitCount / (_hitCount + _missCount):P2}");
}
}
```
## API 参考
### IBloomFilter 接口
```csharp
public interface IBloomFilter : IDisposable
{
// 属性
string Name { get; }
// 同步方法
bool Add(ReadOnlySpan<byte> data);
IList<bool> Add(IEnumerable<byte[]> elements);
bool Contains(ReadOnlySpan<byte> element);
IList<bool> Contains(IEnumerable<byte[]> elements);
bool All(IEnumerable<byte[]> elements);
void Clear();
long[] ComputeHash(ReadOnlySpan<byte> data);
// 异步方法
ValueTask<bool> AddAsync(ReadOnlyMemory<byte> data);
ValueTask<IList<bool>> AddAsync(IEnumerable<byte[]> elements);
ValueTask<bool> ContainsAsync(ReadOnlyMemory<byte> element);
ValueTask<IList<bool>> ContainsAsync(IEnumerable<byte[]> elements);
ValueTask<bool> AllAsync(IEnumerable<byte[]> elements);
ValueTask ClearAsync();
}
```
### Filter 基类
```csharp
public abstract class Filter : IBloomFilter
{
// 属性
public string Name { get; }
public HashFunction Hash { get; }
public long Capacity { get; }
public int Hashes { get; }
public long ExpectedElements { get; }
public double ErrorRate { get; }
// 静态方法 (数学计算)
public static long BestM(long n, double p);
public static int BestK(long n, long m);
public static long BestN(int k, long m);
public static double BestP(int k, long m, long insertedElements);
}
```
### FilterBuilder
```csharp
public static class FilterBuilder
{
// 使用预期元素数和误报率
public static IBloomFilter Build(long expectedElements, double errorRate);
public static IBloomFilter Build(long expectedElements, double errorRate, HashMethod method);
public static IBloomFilter Build(long expectedElements, double errorRate, HashFunction hash);
// 使用容量和哈希函数数量
public static IBloomFilter Build(long capacity, int hashes, HashMethod method);
public static IBloomFilter Build(long capacity, int hashes, HashFunction hash);
// 使用配置对象
public static IBloomFilter Build(FilterMemoryOptions options);
}
```
### FilterRedisBuilder
```csharp
public static class FilterRedisBuilder
{
public static IBloomFilter Build(
string redisHost,
string name,
long expectedElements,
double errorRate,
HashMethod method = HashMethod.Murmur3);
}
```
### 扩展方法
```csharp
// 服务注册
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddBloomFilter(
this IServiceCollection services,
Action<BloomFilterOptions> setupAction);
}
// 配置扩展
public static class BloomFilterOptionsExtensions
{
public static BloomFilterOptions UseInMemory(
this BloomFilterOptions options,
Action<FilterMemoryOptions> setup = null);
public static BloomFilterOptions UseRedis(
this BloomFilterOptions options,
FilterRedisOptions setup);
public static BloomFilterOptions UseCSRedis(
this BloomFilterOptions options,
FilterCSRedisOptions setup);
public static BloomFilterOptions UseFreeRedis(
this BloomFilterOptions options,
FilterFreeRedisOptions setup);
public static BloomFilterOptions UseEasyCachingRedis(
this BloomFilterOptions options,
FilterEasyCachingRedisOptions setup);
}
```
## 常见问题 (FAQ)
### 1. 布隆过滤器的误报率是多少?
误报率由您在创建时指定的 `errorRate` 参数决定。例如:
```csharp
// 1% 误报率
var bf = FilterBuilder.Build(1_000_000, 0.01);
// 0.1% 误报率 (更准确,但占用更多内存)
var bf2 = FilterBuilder.Build(1_000_000, 0.001);
```
**注意**: 误报率越低,需要的内存空间越大。
### 2. 如何选择 expectedElements?
`expectedElements` 应设置为您预期要添加的元素数量。如果实际添加的元素超过这个数量,误报率会增加。
建议:
- 估算实际元素数量
- 留出 20%-50% 的冗余
- 定期监控实际误报率
### 3. 内存模式 vs Redis 模式如何选择?
| 场景 | 推荐模式 | 原因 |
|------|---------|------|
| 单实例应用 | 内存模式 | 性能最高,无网络开销 |
| 多实例应用 | Redis 模式 | 共享状态,支持分布式 |
| 需要持久化 | Redis 模式 | Redis 提供持久化 |
| 临时去重 | 内存模式 | 简单快速 |
| 跨服务共享 | Redis 模式 | 支持多语言访问 |
### 4. 如何清空布隆过滤器?
```csharp
// 同步清空
bf.Clear();
// 异步清空
await bf.ClearAsync();
```
**注意**: 清空操作会删除所有数据,谨慎使用!
### 5. 布隆过滤器占用多少内存?
内存占用取决于容量 (m):
```
内存 (字节) = m / 8
```
示例计算:
```csharp
// 1000 万元素, 1% 误报率
var bf = FilterBuilder.Build(10_000_000, 0.01);
var filter = (Filter)bf;
// 计算内存占用
long bits = filter.Capacity;
long bytes = bits / 8;
double mb = bytes / (1024.0 * 1024.0);
Console.WriteLine($"位数组大小: {bits:N0} bits");
Console.WriteLine($"内存占用: {bytes:N0} bytes ({mb:F2} MB)");
// 输出: 约 11.4 MB
```
### 6. 可以删除元素吗?
**不可以**。标准布隆过滤器不支持删除操作,因为:
- 多个元素可能映射到相同的位
- 删除一个元素可能影响其他元素的检测
如果需要删除功能,考虑使用:
- Counting Bloom Filter (计数布隆过滤器)
- Cuckoo Filter (布谷鸟过滤器)
### 7. 线程安全吗?
是的,BloomFilter.NetCore 是线程安全的:
```csharp
// 多线程并发访问
var bf = FilterBuilder.Build(10_000_000, 0.01);
Parallel.For(0, 1000, i =>
{
bf.Add($"item:{i}"); // 线程安全
});
Parallel.For(0, 1000, i =>
{
var exists = bf.Contains($"item:{i}"); // 线程安全
});
```
### 8. 如何监控 Redis 连接?
```csharp
// 使用 StackExchange.Redis 的连接监控
services.AddBloomFilter(setupAction =>
{
setupAction.UseRedis(new FilterRedisOptions
{
Name = "MyFilter",
RedisKey = "BF:Key",
Endpoints = new List<string> { "localhost:6379" },
// 启用连接日志
AbortOnConnectFail = false,
ConnectTimeout = 5000,
ConnectRetry = 3
});
});
// 获取 Redis 连接信息
var bf = serviceProvider.GetService<IBloomFilter>();
if (bf is FilterRedis redisFilter)
{
var connection = redisFilter.Connection;
Console.WriteLine($"连接状态: {connection.IsConnected}");
Console.WriteLine($"端点: {string.Join(", ", connection.GetEndPoints())}");
}
```
## 贡献指南
我们欢迎社区贡献!
### 如何贡献
1. Fork 本仓库
2. 创建特性分支 (`git checkout -b feature/amazing-feature`)
3. 提交更改 (`git commit -m 'Add amazing feature'`)
4. 推送到分支 (`git push origin feature/amazing-feature`)
5. 创建 Pull Request
### 开发指南
```bash
# 克隆仓库
git clone https://github.com/vla/BloomFilter.NetCore.git
cd BloomFilter.NetCore
# 还原依赖
dotnet restore
# 构建项目
dotnet build
# 运行测试
dotnet test
# 运行基准测试
cd test/BenchmarkTest
dotnet run -c Release
```
### 代码规范
- 遵循 C# 编码规范
- 添加 XML 文档注释
- 编写单元测试
- 更新相关文档
## 致谢
感谢所有为本项目做出贡献的开发者!
特别感谢:
- .NET Foundation
- StackExchange.Redis 团队
- 所有依赖库的作者
如果这个项目对您有帮助,请给我们一个 ⭐️ Star!
================================================
FILE: VERSION
================================================
3.0.0
================================================
FILE: build.cmd
================================================
set artifacts=%~dp0artifacts
if exist %artifacts% rd /q /s %artifacts%
set /p ver=<VERSION
dotnet restore src/BloomFilter
dotnet restore src/BloomFilter.Redis
dotnet restore src/BloomFilter.CSRedis
dotnet restore src/BloomFilter.FreeRedis
dotnet restore src/BloomFilter.EasyCaching
dotnet pack src/BloomFilter -c release -p:Ver=%ver% -o %artifacts%
dotnet pack src/BloomFilter.Redis -c release -p:Ver=%ver% -o %artifacts%
dotnet pack src/BloomFilter.CSRedis -c release -p:Ver=%ver% -o %artifacts%
dotnet pack src/BloomFilter.FreeRedis -c release -p:Ver=%ver% -o %artifacts%
dotnet pack src/BloomFilter.EasyCaching -c release -p:Ver=%ver% -o %artifacts%
pause
================================================
FILE: build.sh
================================================
#!/usr/bin/env bash
set -e
basepath=$(cd `dirname $0`; pwd)
artifacts=${basepath}/artifacts
if [[ -d ${artifacts} ]]; then
rm -rf ${artifacts}
fi
mkdir -p ${artifacts}
dotnet build src/BloomFilter.Redis -f netstandard2.0 -c Release -o ${artifacts}/netstandard2.0
================================================
FILE: nuget_push.cmd
================================================
set /p ver=<VERSION
set sourceUrl=-s https://www.nuget.org/api/v2/package
dotnet nuget push artifacts/BloomFilter.NetCore.%ver%.nupkg %sourceUrl%
dotnet nuget push artifacts/BloomFilter.Redis.NetCore.%ver%.nupkg %sourceUrl%
dotnet nuget push artifacts/BloomFilter.CSRedis.NetCore.%ver%.nupkg %sourceUrl%
dotnet nuget push artifacts/BloomFilter.FreeRedis.NetCore.%ver%.nupkg %sourceUrl%
dotnet nuget push artifacts/BloomFilter.EasyCaching.NetCore.%ver%.nupkg %sourceUrl%
================================================
FILE: src/BloomFilter/Annotations.cs
================================================
#if NETSTANDARD2_0 || NETFRAMEWORK
namespace System.Diagnostics.CodeAnalysis;
/// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
internal sealed class AllowNullAttribute : Attribute { }
/// <summary>Specifies that null is disallowed as an input even if the corresponding type allows it.</summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
internal sealed class DisallowNullAttribute : Attribute { }
/// <summary>Specifies that an output may be null even if the corresponding type disallows it.</summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
internal sealed class MaybeNullAttribute : Attribute { }
/// <summary>Specifies that an output will not be null even if the corresponding type allows it.</summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
internal sealed class NotNullAttribute : Attribute { }
/// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter may be null even if the corresponding type disallows it.</summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class MaybeNullWhenAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter may be null.
/// </param>
public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
}
/// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter will not be null even if the corresponding type allows it.</summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class NotNullWhenAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
}
/// <summary>Specifies that the output will be non-null if the named parameter is non-null.</summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
internal sealed class NotNullIfNotNullAttribute : Attribute
{
/// <summary>Initializes the attribute with the associated parameter name.</summary>
/// <param name="parameterName">
/// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null.
/// </param>
public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName;
/// <summary>Gets the associated parameter name.</summary>
public string ParameterName { get; }
}
/// <summary>Applied to a method that will never return under any circumstance.</summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
internal sealed class DoesNotReturnAttribute : Attribute { }
/// <summary>Specifies that the method will not return if the associated Boolean parameter is passed the specified value.</summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class DoesNotReturnIfAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified parameter value.</summary>
/// <param name="parameterValue">
/// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to
/// the associated parameter matches this value.
/// </param>
public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue;
/// <summary>Gets the condition parameter value.</summary>
public bool ParameterValue { get; }
}
/// <summary>Specifies that the method or property will ensure that the listed field and property members have not-null values.</summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
internal sealed class MemberNotNullAttribute : Attribute
{
/// <summary>Initializes the attribute with a field or property member.</summary>
/// <param name="member">
/// The field or property member that is promised to be not-null.
/// </param>
public MemberNotNullAttribute(string member) => Members = new[] { member };
/// <summary>Initializes the attribute with the list of field and property members.</summary>
/// <param name="members">
/// The list of field and property members that are promised to be not-null.
/// </param>
public MemberNotNullAttribute(params string[] members) => Members = members;
/// <summary>Gets field or property member names.</summary>
public string[] Members { get; }
}
/// <summary>Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition.</summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
internal sealed class MemberNotNullWhenAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition and a field or property member.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
/// <param name="member">
/// The field or property member that is promised to be not-null.
/// </param>
public MemberNotNullWhenAttribute(bool returnValue, string member)
{
ReturnValue = returnValue;
Members = new[] { member };
}
/// <summary>Initializes the attribute with the specified return value condition and list of field and property members.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
/// <param name="members">
/// The list of field and property members that are promised to be not-null.
/// </param>
public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
{
ReturnValue = returnValue;
Members = members;
}
/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
/// <summary>Gets field or property member names.</summary>
public string[] Members { get; }
}
#endif
#if NETSTANDARD2_1
namespace System.Diagnostics.CodeAnalysis;
/// <summary>Specifies that the method or property will ensure that the listed field and property members have not-null values.</summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
internal sealed class MemberNotNullAttribute : Attribute
{
/// <summary>Initializes the attribute with a field or property member.</summary>
/// <param name="member">
/// The field or property member that is promised to be not-null.
/// </param>
public MemberNotNullAttribute(string member) => Members = new[] { member };
/// <summary>Initializes the attribute with the list of field and property members.</summary>
/// <param name="members">
/// The list of field and property members that are promised to be not-null.
/// </param>
public MemberNotNullAttribute(params string[] members) => Members = members;
/// <summary>Gets field or property member names.</summary>
public string[] Members { get; }
}
/// <summary>Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition.</summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
internal sealed class MemberNotNullWhenAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition and a field or property member.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
/// <param name="member">
/// The field or property member that is promised to be not-null.
/// </param>
public MemberNotNullWhenAttribute(bool returnValue, string member)
{
ReturnValue = returnValue;
Members = new[] { member };
}
/// <summary>Initializes the attribute with the specified return value condition and list of field and property members.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
/// <param name="members">
/// The list of field and property members that are promised to be not-null.
/// </param>
public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
{
ReturnValue = returnValue;
Members = members;
}
/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
/// <summary>Gets field or property member names.</summary>
public string[] Members { get; }
}
#endif
================================================
FILE: src/BloomFilter/AsyncLock.cs
================================================
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace BloomFilter;
/// <summary>
/// AsyncLock
/// </summary>
internal readonly struct AsyncLock : IDisposable
{
private readonly SemaphoreSlim _semaphore;
private readonly Releaser _releaser;
private readonly Task<Releaser> _releaserTask;
public int MaxCount { get; }
public AsyncLock() : this(1)
{
}
public AsyncLock(int maxCount = 1)
{
MaxCount = maxCount;
_semaphore = new SemaphoreSlim(maxCount);
_releaser = new Releaser(_semaphore);
_releaserTask = Task.FromResult(_releaser);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Releaser Acquire()
{
_semaphore.Wait();
return _releaser;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Task<Releaser> AcquireAsync(bool continueOnCapturedContext = false)
{
var acquireAsync = _semaphore.WaitAsync();
return Return(acquireAsync, continueOnCapturedContext);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose() => _semaphore.Dispose();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Task<Releaser> Return(Task acquireAsync, bool continueOnCapturedContext)
{
return acquireAsync.Status == TaskStatus.RanToCompletion
? _releaserTask
: WaitForAcquireAsync(acquireAsync, continueOnCapturedContext);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private async Task<Releaser> WaitForAcquireAsync(Task acquireAsync, bool continueOnCapturedContext)
{
await acquireAsync.ConfigureAwait(continueOnCapturedContext);
return _releaser;
}
public readonly struct Releaser(SemaphoreSlim? semaphore) : IDisposable
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose() => semaphore?.Release();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetRemainingCount()
{
return MaxCount - _semaphore.CurrentCount;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetCurrentCount()
{
return _semaphore.CurrentCount;
}
}
================================================
FILE: src/BloomFilter/BinaryHelper.cs
================================================
using System;
using System.Collections;
using System.Numerics;
using System.Runtime.CompilerServices;
#if NET6_0_OR_GREATER
using System.Buffers.Binary;
#endif
namespace BloomFilter;
internal class BinaryHelper
{
public static int BitToIntOne(BitArray bit, int from, int to)
{
const int size = 32;
int len = to - from;
int bitCount = bit.Count;
int result = 0;
for (int i = 0; i < len && i < bitCount && i < size; i++)
{
result = bit[i + from] ? result + (1 << i) : result;
}
return result;
}
/// <summary>
/// Perform rejection sampling on a 32-bit,
/// https://en.wikipedia.org/wiki/Rejection_sampling
/// </summary>
/// <param name="random">The random.</param>
/// <param name="m">integer output range.</param>
/// <returns></returns>
public static long Rejection(long random, long m)
{
var intMax = (long)uint.MaxValue;
random = Math.Abs(random);
if (random > (intMax - intMax % m) || random == uint.MinValue)
return -1;
return random % m;
}
public static uint NumberOfTrailingZeros(uint i)
{
// HD, Figure 5-14
uint y;
if (i == 0) return 32;
uint n = 31;
y = i << 16; if (y != 0) { n -= 16; i = y; }
y = i << 8; if (y != 0) { n -= 8; i = y; }
y = i << 4; if (y != 0) { n -= 4; i = y; }
y = i << 2; if (y != 0) { n -= 2; i = y; }
return n - ((i << 1) >> 31);
}
public static uint NumberOfLeadingZeros(uint i)
{
// HD, Figure 5-6
if (i == 0)
return 32;
uint n = 1;
if (i >> 16 == 0) { n += 16; i <<= 16; }
if (i >> 24 == 0) { n += 8; i <<= 8; }
if (i >> 28 == 0) { n += 4; i <<= 4; }
if (i >> 30 == 0) { n += 2; i <<= 2; }
n -= i >> 31;
return n;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int RotateLeft(int i, int distance)
{
#if NET6_0_OR_GREATER
return (int)BitOperations.RotateLeft((uint)i, distance);
#else
return (i << distance) | (int)((uint)i >> -distance);
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint RotateLeft(uint i, int distance)
{
#if NET6_0_OR_GREATER
return BitOperations.RotateLeft(i, distance);
#else
return (i << distance) | (i >> -distance);
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int RotateRight(int i, int distance)
{
#if NET6_0_OR_GREATER
return (int)BitOperations.RotateRight((uint)i, distance);
#else
return (int)((uint)i >> distance) | (i << -distance);
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint RotateRight(uint i, int distance)
{
#if NET6_0_OR_GREATER
return BitOperations.RotateRight(i, distance);
#else
return (i >> distance) | (i << -distance);
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long RotateLeft(long i, int distance)
{
#if NET6_0_OR_GREATER
return (long)BitOperations.RotateLeft((ulong)i, distance);
#else
return (i << distance) | (long)((ulong)i >> -distance);
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong RotateLeft(ulong i, int distance)
{
#if NET6_0_OR_GREATER
return BitOperations.RotateLeft(i, distance);
#else
return (i << distance) | (i >> -distance);
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long RotateRight(long i, int distance)
{
#if NET6_0_OR_GREATER
return (long)BitOperations.RotateRight((ulong)i, distance);
#else
return (long)((ulong)i >> distance) | (i << -distance);
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong RotateRight(ulong i, int distance)
{
#if NET6_0_OR_GREATER
return BitOperations.RotateRight(i, distance);
#else
return (i >> distance) | (i << -distance);
#endif
}
public static int RightMove(int value, int pos)
{
if (pos != 0)
{
var mask = 0x7fffffff;
value >>= 1;
value &= mask;
value >>= pos - 1;
}
return value;
}
public static long RightMove(long value, int pos)
{
if (pos != 0)
{
var mask = 0x7fffffff;
value >>= 1;
value &= mask;
value >>= pos - 1;
}
return value;
}
public static uint RightMove(uint value, int pos)
{
if (pos != 0)
{
uint mask = 0x7fffffff;
value >>= 1;
value &= mask;
value >>= pos - 1;
}
return value;
}
}
================================================
FILE: src/BloomFilter/BloomFilter.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>BloomFilter</AssemblyName>
<AssemblyTitle>BloomFilter</AssemblyTitle>
<PackageId>BloomFilter.NetCore</PackageId>
<TargetFrameworks>net462;netstandard2.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Nullable>enable</Nullable>
<NullableReferenceTypes>true</NullableReferenceTypes>
<NoWarn>$(NoWarn);CS1591</NoWarn>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'net462' ">
<PackageReference Include="System.Runtime" />
<PackageReference Include="System.Memory" />
<PackageReference Include="System.Threading.Tasks.Extensions" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
</ItemGroup>
</Project>
================================================
FILE: src/BloomFilter/BloomFilterConstValue.cs
================================================
namespace BloomFilter;
public class BloomFilterConstValue
{
/// <summary>
/// The default name of the in-memory.
/// </summary>
public const string DefaultInMemoryName = "DefaultInMemory";
/// <summary>
/// The default name of the redis.
/// </summary>
public const string DefaultRedisName = "DefaultRedis";
}
================================================
FILE: src/BloomFilter/BloomFilterExtensions.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BloomFilter;
/// <summary>
/// BloomFilterExtensions
/// </summary>
public static class BloomFilterExtensions
{
#region Byte
public static bool Add(this IBloomFilter bloomFilter, byte data) => bloomFilter.Add(new[] { data });
public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, byte data) => bloomFilter.AddAsync(new[] { data });
public static bool Contains(this IBloomFilter bloomFilter, byte data) => bloomFilter.Contains(new[] { data });
public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFilter, byte data) => bloomFilter.ContainsAsync(new[] { data });
public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerable<byte> elements) => bloomFilter.Add(elements.Select(data => new byte[] { data }));
public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomFilter, IEnumerable<byte> elements) => bloomFilter.AddAsync(elements.Select(data => new byte[] { data }));
public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnumerable<byte> elements) => bloomFilter.Contains(elements.Select(data => new byte[] { data }));
public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter bloomFilter, IEnumerable<byte> elements) => bloomFilter.ContainsAsync(elements.Select(data => new byte[] { data }));
public static bool All(this IBloomFilter bloomFilter, IEnumerable<byte> elements) => bloomFilter.All(elements.Select(data => new byte[] { data }));
public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, IEnumerable<byte> elements) => bloomFilter.AllAsync(elements.Select(data => new byte[] { data }));
#endregion Byte
#region String
public static bool Add(this IBloomFilter bloomFilter, string data) => bloomFilter.Add(Encoding.UTF8.GetBytes(data));
public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, string data) => bloomFilter.AddAsync(Encoding.UTF8.GetBytes(data));
public static bool Contains(this IBloomFilter bloomFilter, string data) => bloomFilter.Contains(Encoding.UTF8.GetBytes(data));
public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFilter, string data) => bloomFilter.ContainsAsync(Encoding.UTF8.GetBytes(data));
public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerable<string> elements) => bloomFilter.Add(elements.Select(data => Encoding.UTF8.GetBytes(data)));
public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomFilter, IEnumerable<string> elements) => bloomFilter.AddAsync(elements.Select(data => Encoding.UTF8.GetBytes(data)));
public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnumerable<string> elements) => bloomFilter.Contains(elements.Select(data => Encoding.UTF8.GetBytes(data)));
public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter bloomFilter, IEnumerable<string> elements) => bloomFilter.ContainsAsync(elements.Select(data => Encoding.UTF8.GetBytes(data)));
public static bool All(this IBloomFilter bloomFilter, IEnumerable<string> elements) => bloomFilter.All(elements.Select(data => Encoding.UTF8.GetBytes(data)));
public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, IEnumerable<string> elements) => bloomFilter.AllAsync(elements.Select(data => Encoding.UTF8.GetBytes(data)));
#endregion String
#region ReadOnlySpan<char>
public static bool Add(this IBloomFilter bloomFilter, ReadOnlySpan<char> data) => bloomFilter.Add(data.ToUtf8().Span);
public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ReadOnlyMemory<char> data) => bloomFilter.AddAsync(data.Span.ToUtf8());
public static bool Contains(this IBloomFilter bloomFilter, ReadOnlySpan<char> data) => bloomFilter.Contains(data.ToUtf8().Span);
public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFilter, ReadOnlyMemory<char> data) => bloomFilter.ContainsAsync(data.Span.ToUtf8());
#endregion String
#region Double
public static bool Add(this IBloomFilter bloomFilter, double data) => bloomFilter.Add(BitConverter.GetBytes(data));
public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, double data) => bloomFilter.AddAsync(BitConverter.GetBytes(data));
public static bool Contains(this IBloomFilter bloomFilter, double data) => bloomFilter.Contains(BitConverter.GetBytes(data));
public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFilter, double data) => bloomFilter.ContainsAsync(BitConverter.GetBytes(data));
public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerable<double> elements) => bloomFilter.Add(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomFilter, IEnumerable<double> elements) => bloomFilter.AddAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnumerable<double> elements) => bloomFilter.Contains(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter bloomFilter, IEnumerable<double> elements) => bloomFilter.ContainsAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static bool All(this IBloomFilter bloomFilter, IEnumerable<double> elements) => bloomFilter.All(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, IEnumerable<double> elements) => bloomFilter.AllAsync(elements.Select(data => BitConverter.GetBytes(data)));
#endregion Double
#region Single
public static bool Add(this IBloomFilter bloomFilter, float data) => bloomFilter.Add(BitConverter.GetBytes(data));
public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, float data) => bloomFilter.AddAsync(BitConverter.GetBytes(data));
public static bool Contains(this IBloomFilter bloomFilter, float data) => bloomFilter.Contains(BitConverter.GetBytes(data));
public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFilter, float data) => bloomFilter.ContainsAsync(BitConverter.GetBytes(data));
public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerable<float> elements) => bloomFilter.Add(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomFilter, IEnumerable<float> elements) => bloomFilter.AddAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnumerable<float> elements) => bloomFilter.Contains(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter bloomFilter, IEnumerable<float> elements) => bloomFilter.ContainsAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static bool All(this IBloomFilter bloomFilter, IEnumerable<float> elements) => bloomFilter.All(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, IEnumerable<float> elements) => bloomFilter.AllAsync(elements.Select(data => BitConverter.GetBytes(data)));
#endregion Single
#region Int16
public static bool Add(this IBloomFilter bloomFilter, short data) => bloomFilter.Add(BitConverter.GetBytes(data));
public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, short data) => bloomFilter.AddAsync(BitConverter.GetBytes(data));
public static bool Contains(this IBloomFilter bloomFilter, short data) => bloomFilter.Contains(BitConverter.GetBytes(data));
public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFilter, short data) => bloomFilter.ContainsAsync(BitConverter.GetBytes(data));
public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerable<short> elements) => bloomFilter.Add(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomFilter, IEnumerable<short> elements) => bloomFilter.AddAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnumerable<short> elements) => bloomFilter.Contains(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter bloomFilter, IEnumerable<short> elements) => bloomFilter.ContainsAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static bool All(this IBloomFilter bloomFilter, IEnumerable<short> elements) => bloomFilter.All(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, IEnumerable<short> elements) => bloomFilter.AllAsync(elements.Select(data => BitConverter.GetBytes(data)));
#endregion Int16
#region Int32
public static bool Add(this IBloomFilter bloomFilter, int data) => bloomFilter.Add(BitConverter.GetBytes(data));
public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, int data) => bloomFilter.AddAsync(BitConverter.GetBytes(data));
public static bool Contains(this IBloomFilter bloomFilter, int data) => bloomFilter.Contains(BitConverter.GetBytes(data));
public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFilter, int data) => bloomFilter.ContainsAsync(BitConverter.GetBytes(data));
public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerable<int> elements) => bloomFilter.Add(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomFilter, IEnumerable<int> elements) => bloomFilter.AddAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnumerable<int> elements) => bloomFilter.Contains(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter bloomFilter, IEnumerable<int> elements) => bloomFilter.ContainsAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static bool All(this IBloomFilter bloomFilter, IEnumerable<int> elements) => bloomFilter.All(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, IEnumerable<int> elements) => bloomFilter.AllAsync(elements.Select(data => BitConverter.GetBytes(data)));
#endregion Int32
#region Int64
public static bool Add(this IBloomFilter bloomFilter, long data) => bloomFilter.Add(BitConverter.GetBytes(data));
public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, long data) => bloomFilter.AddAsync(BitConverter.GetBytes(data));
public static bool Contains(this IBloomFilter bloomFilter, long data) => bloomFilter.Contains(BitConverter.GetBytes(data));
public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFilter, long data) => bloomFilter.ContainsAsync(BitConverter.GetBytes(data));
public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerable<long> elements) => bloomFilter.Add(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomFilter, IEnumerable<long> elements) => bloomFilter.AddAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnumerable<long> elements) => bloomFilter.Contains(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter bloomFilter, IEnumerable<long> elements) => bloomFilter.ContainsAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static bool All(this IBloomFilter bloomFilter, IEnumerable<long> elements) => bloomFilter.All(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, IEnumerable<long> elements) => bloomFilter.AllAsync(elements.Select(data => BitConverter.GetBytes(data)));
#endregion Int64
#region UInt16
public static bool Add(this IBloomFilter bloomFilter, ushort data) => bloomFilter.Add(BitConverter.GetBytes(data));
public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ushort data) => bloomFilter.AddAsync(BitConverter.GetBytes(data));
public static bool Contains(this IBloomFilter bloomFilter, ushort data) => bloomFilter.Contains(BitConverter.GetBytes(data));
public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFilter, ushort data) => bloomFilter.ContainsAsync(BitConverter.GetBytes(data));
public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerable<ushort> elements) => bloomFilter.Add(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomFilter, IEnumerable<ushort> elements) => bloomFilter.AddAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnumerable<ushort> elements) => bloomFilter.Contains(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter bloomFilter, IEnumerable<ushort> elements) => bloomFilter.ContainsAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static bool All(this IBloomFilter bloomFilter, IEnumerable<ushort> elements) => bloomFilter.All(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, IEnumerable<ushort> elements) => bloomFilter.AllAsync(elements.Select(data => BitConverter.GetBytes(data)));
#endregion UInt16
#region UInt32
public static bool Add(this IBloomFilter bloomFilter, uint data) => bloomFilter.Add(BitConverter.GetBytes(data));
public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, uint data) => bloomFilter.AddAsync(BitConverter.GetBytes(data));
public static bool Contains(this IBloomFilter bloomFilter, uint data) => bloomFilter.Contains(BitConverter.GetBytes(data));
public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFilter, uint data) => bloomFilter.ContainsAsync(BitConverter.GetBytes(data));
public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerable<uint> elements) => bloomFilter.Add(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomFilter, IEnumerable<uint> elements) => bloomFilter.AddAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnumerable<uint> elements) => bloomFilter.Contains(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter bloomFilter, IEnumerable<uint> elements) => bloomFilter.ContainsAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static bool All(this IBloomFilter bloomFilter, IEnumerable<uint> elements) => bloomFilter.All(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, IEnumerable<uint> elements) => bloomFilter.AllAsync(elements.Select(data => BitConverter.GetBytes(data)));
#endregion UInt32
#region UInt64
public static bool Add(this IBloomFilter bloomFilter, ulong data) => bloomFilter.Add(BitConverter.GetBytes(data));
public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ulong data) => bloomFilter.AddAsync(BitConverter.GetBytes(data));
public static bool Contains(this IBloomFilter bloomFilter, ulong data) => bloomFilter.Contains(BitConverter.GetBytes(data));
public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFilter, ulong data) => bloomFilter.ContainsAsync(BitConverter.GetBytes(data));
public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerable<ulong> elements) => bloomFilter.Add(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomFilter, IEnumerable<ulong> elements) => bloomFilter.AddAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnumerable<ulong> elements) => bloomFilter.Contains(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter bloomFilter, IEnumerable<ulong> elements) => bloomFilter.ContainsAsync(elements.Select(data => BitConverter.GetBytes(data)));
public static bool All(this IBloomFilter bloomFilter, IEnumerable<ulong> elements) => bloomFilter.All(elements.Select(data => BitConverter.GetBytes(data)));
public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, IEnumerable<ulong> elements) => bloomFilter.AllAsync(elements.Select(data => BitConverter.GetBytes(data)));
#endregion UInt64
#region DateTime
public static bool Add(this IBloomFilter bloomFilter, DateTime data) => bloomFilter.Add(BitConverter.GetBytes(data.Ticks));
public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, DateTime data) => bloomFilter.AddAsync(BitConverter.GetBytes(data.Ticks));
public static bool Contains(this IBloomFilter bloomFilter, DateTime data) => bloomFilter.Contains(BitConverter.GetBytes(data.Ticks));
public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFilter, DateTime data) => bloomFilter.ContainsAsync(BitConverter.GetBytes(data.Ticks));
public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerable<DateTime> elements) => bloomFilter.Add(elements.Select(data => BitConverter.GetBytes(data.Ticks)));
public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomFilter, IEnumerable<DateTime> elements) => bloomFilter.AddAsync(elements.Select(data => BitConverter.GetBytes(data.Ticks)));
public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnumerable<DateTime> elements) => bloomFilter.Contains(elements.Select(data => BitConverter.GetBytes(data.Ticks)));
public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter bloomFilter, IEnumerable<DateTime> elements) => bloomFilter.ContainsAsync(elements.Select(data => BitConverter.GetBytes(data.Ticks)));
public static bool All(this IBloomFilter bloomFilter, IEnumerable<DateTime> elements) => bloomFilter.All(elements.Select(data => BitConverter.GetBytes(data.Ticks)));
public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, IEnumerable<DateTime> elements) => bloomFilter.AllAsync(elements.Select(data => BitConverter.GetBytes(data.Ticks)));
#endregion DateTime
}
================================================
FILE: src/BloomFilter/Configurations/BloomFilterOptions.cs
================================================
using System;
using System.Collections.Generic;
namespace BloomFilter.Configurations;
/// <summary>
/// BloomFilterOptions
/// </summary>
public class BloomFilterOptions
{
/// <summary>
/// Gets the extensions.
/// </summary>
/// <value>The extensions.</value>
internal IList<IBloomFilterOptionsExtension> Extensions { get; } = new List<IBloomFilterOptionsExtension>();
/// <summary>
/// Registers the extension.
/// </summary>
/// <param name="extension">Extension.</param>
public void RegisterExtension(IBloomFilterOptionsExtension extension)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(extension);
#else
if (extension == null) throw new ArgumentNullException(nameof(extension));
#endif
Extensions.Add(extension);
}
}
================================================
FILE: src/BloomFilter/Configurations/FilterMemoryOptions.cs
================================================
using System.Collections;
using System.Collections.Generic;
namespace BloomFilter.Configurations;
public class FilterMemoryOptions
{
/// <summary>
/// The Name
/// </summary>
public string Name { get; set; } = BloomFilterConstValue.DefaultInMemoryName;
/// <summary>
/// The expected elements
/// </summary>
public long ExpectedElements { get; set; } = 1_000_000;
/// <summary>
/// The error rate
/// </summary>
public double ErrorRate { get; set; } = 0.01;
/// <summary>
/// The Hash Method
/// </summary>
public HashMethod Method { get; set; } = HashMethod.Murmur3;
/// <summary>
/// Multiple bitmap
/// </summary>
public BitArray[]? Buckets { get; set; }
/// <summary>
/// Multiple bitmap from bytes
/// </summary>
public IList<byte[]>? BucketBytes { get; set; }
}
================================================
FILE: src/BloomFilter/Configurations/FilterMemoryOptionsExtension.cs
================================================
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace BloomFilter.Configurations;
public class FilterMemoryOptionsExtension : IBloomFilterOptionsExtension
{
private readonly FilterMemoryOptions _options;
private readonly Type? _serializerType;
/// <summary>
/// Initializes a new instance of the <see cref="FilterMemoryOptionsExtension"/> class.
/// </summary>
/// <param name="options">Configure.</param>
/// <param name="serializerType"></param>
public FilterMemoryOptionsExtension(FilterMemoryOptions options, Type? serializerType = null)
{
_options = options;
_serializerType = serializerType;
}
public void AddServices(IServiceCollection services)
{
services.TryAddSingleton<IBloomFilterFactory, DefaultBloomFilterFactory>();
if (_serializerType is null)
{
services.TryAddSingleton<IFilterMemorySerializer, DefaultFilterMemorySerializer>();
}
else
{
services.TryAddSingleton(typeof(IFilterMemorySerializer), _serializerType);
}
services.AddSingleton<IBloomFilter, FilterMemory>(x =>
{
return new FilterMemory(_options, x.GetRequiredService<IFilterMemorySerializer>());
});
}
}
================================================
FILE: src/BloomFilter/Configurations/IBloomFilterOptionsExtension.cs
================================================
using Microsoft.Extensions.DependencyInjection;
namespace BloomFilter.Configurations;
/// <summary>
/// BloomFilter options extension.
/// </summary>
public interface IBloomFilterOptionsExtension
{
/// <summary>
/// Adds the services.
/// </summary>
/// <param name="services">Services.</param>
void AddServices(IServiceCollection services);
}
================================================
FILE: src/BloomFilter/DefaultBloomFilterFactory.cs
================================================
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace BloomFilter;
public class DefaultBloomFilterFactory : IBloomFilterFactory
{
private readonly IEnumerable<IBloomFilter> _bloomFilters;
public DefaultBloomFilterFactory(IEnumerable<IBloomFilter> bloomFilters)
{
_bloomFilters = bloomFilters;
}
public IBloomFilter Get(string name)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(name);
#else
if (name == null) throw new ArgumentNullException(nameof(name));
#endif
var filter = _bloomFilters.FirstOrDefault(x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (filter == null) throw new ArgumentException("can not find a match BloomFilter");
return filter;
}
public bool TryGet(string name,
#if NET5_0_OR_GREATER
[MaybeNullWhen(false)]
#endif
out IBloomFilter bloomFilter)
{
bloomFilter = _bloomFilters.FirstOrDefault(x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
return bloomFilter != null;
}
}
================================================
FILE: src/BloomFilter/DefaultFilterMemorySerializer.cs
================================================
using System;
using System.Collections;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace BloomFilter;
public class DefaultFilterMemorySerializer : IFilterMemorySerializer
{
public async ValueTask SerializeAsync(FilterMemorySerializerParam param, Stream stream)
{
byte[] nameBytes = Encoding.UTF8.GetBytes(param.Name ?? string.Empty);
await stream.WriteAsync(BitConverter.GetBytes(nameBytes.Length), 0, 4);
await stream.WriteAsync(nameBytes, 0, nameBytes.Length);
await stream.WriteAsync(BitConverter.GetBytes(param.ExpectedElements), 0, 8);
await stream.WriteAsync(BitConverter.GetBytes(param.ErrorRate), 0, 8);
await stream.WriteAsync(BitConverter.GetBytes((int)param.Method), 0, 4);
await stream.WriteAsync(BitConverter.GetBytes(param.Buckets.Length), 0, 4);
foreach (var bucket in param.Buckets)
{
byte[] bucketBytes = new byte[bucket.Length / 8 + Mod(bucket.Length)];
bucket.CopyTo(bucketBytes, 0);
await stream.WriteAsync(BitConverter.GetBytes(bucketBytes.Length), 0, 4).ConfigureAwait(false);
await stream.WriteAsync(bucketBytes, 0, bucketBytes.Length).ConfigureAwait(false);
}
}
public async ValueTask<FilterMemorySerializerParam> DeserializeAsync(Stream stream)
{
byte[] lengthBytes = new byte[4];
byte[] int64Bytes = new byte[8];
// Read name
await ReadExactlyAsync(stream, lengthBytes);
int nameLength = BitConverter.ToInt32(lengthBytes, 0);
byte[] nameBytes = new byte[nameLength];
await ReadExactlyAsync(stream, nameBytes);
string name = Encoding.UTF8.GetString(nameBytes);
// Read expected elements
await ReadExactlyAsync(stream, int64Bytes);
long expectedElements = BitConverter.ToInt64(int64Bytes, 0);
// Read error rate
await ReadExactlyAsync(stream, int64Bytes);
double errorRate = BitConverter.ToDouble(int64Bytes, 0);
// Read method
await ReadExactlyAsync(stream, lengthBytes);
HashMethod method = (HashMethod)BitConverter.ToInt32(lengthBytes, 0);
// Read buckets
await ReadExactlyAsync(stream, lengthBytes);
int bucketsLength = BitConverter.ToInt32(lengthBytes, 0);
var buckets = new BitArray[bucketsLength];
for (int i = 0; i < bucketsLength; i++)
{
await ReadExactlyAsync(stream, lengthBytes);
int bitArrayLength = BitConverter.ToInt32(lengthBytes, 0);
byte[] bucketBytes = new byte[bitArrayLength];
await ReadExactlyAsync(stream, bucketBytes);
buckets[i] = new BitArray(bucketBytes);
}
// Create param with object initializer (compatible with init properties)
return new FilterMemorySerializerParam
{
Name = name,
ExpectedElements = expectedElements,
ErrorRate = errorRate,
Method = method,
Buckets = buckets
};
}
private async Task ReadExactlyAsync(Stream stream, byte[] data)
{
#if NET7_0_OR_GREATER
await stream.ReadExactlyAsync(data, 0, data.Length).ConfigureAwait(false);
#else
await stream.ReadAsync(data, 0, data.Length).ConfigureAwait(false);
#endif
}
private int Mod(int len) => len % 8 > 0 ? 1 : 0;
}
================================================
FILE: src/BloomFilter/Filter.cs
================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace BloomFilter;
/// <summary>
/// Represents a Bloom filter and provides
/// </summary>
/// <seealso cref="IBloomFilter" />
public abstract class Filter : IBloomFilter
{
//256MB
protected const int MaxInt = 2_147_483_640;
/// <summary>
/// Gets the name specified by BloomFilter.
/// </summary>
public string Name { get; }
/// <summary>
/// <see cref="HashFunction"/>
/// </summary>
public HashFunction Hash { get; private set; }
/// <summary>
/// the Capacity of the Bloom filter
/// </summary>
public long Capacity { get; private set; }
/// <summary>
/// number of hash functions
/// </summary>
public int Hashes { get; private set; }
/// <summary>
/// the expected elements.
/// </summary>
public long ExpectedElements { get; private set; }
/// <summary>
/// the number of expected elements
/// </summary>
public double ErrorRate { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="Filter"/> class.
/// </summary>
/// <param name="name"></param>
/// <param name="expectedElements">The expected elements.</param>
/// <param name="errorRate">The error rate.</param>
/// <param name="hashFunction">The hash function.</param>
/// <exception cref="ArgumentOutOfRangeException">
/// expectedElements - expectedElements must be > 0
/// or
/// errorRate
/// </exception>
/// <exception cref="ArgumentNullException">hashFunction</exception>
public Filter(string name, long expectedElements, double errorRate, HashFunction hashFunction)
{
if (expectedElements < 1)
throw new ArgumentOutOfRangeException("expectedElements", expectedElements, "expectedElements must be > 0");
if (errorRate >= 1 || errorRate <= 0)
throw new ArgumentOutOfRangeException("errorRate", errorRate, string.Format("errorRate must be between 0 and 1, exclusive. Was {0}", errorRate));
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(hashFunction);
#else
if (hashFunction == null)
throw new ArgumentNullException(nameof(hashFunction));
#endif
Name = name;
ExpectedElements = expectedElements;
ErrorRate = errorRate;
Hash = hashFunction;
Capacity = BestM(expectedElements, errorRate);
Hashes = BestK(expectedElements, Capacity);
}
/// <summary>
/// Initializes a new instance of the <see cref="Filter"/> class.
/// </summary>
/// <param name="name"></param>
/// <param name="capacity">The capacity.</param>
/// <param name="hashes">The hashes.</param>
/// <param name="hashFunction">The hash function.</param>
/// <exception cref="ArgumentOutOfRangeException">
/// capacity - capacity must be > 0
/// or
/// hashes - hashes must be > 0
/// </exception>
/// <exception cref="ArgumentNullException">hashFunction</exception>
public Filter(string name, long capacity, int hashes, HashFunction hashFunction)
{
if (capacity < 1)
throw new ArgumentOutOfRangeException("capacity", capacity, "capacity must be > 0");
if (hashes < 1)
throw new ArgumentOutOfRangeException("hashes", hashes, "hashes must be > 0");
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(hashFunction);
#else
if (hashFunction == null)
throw new ArgumentNullException(nameof(hashFunction));
#endif
Name = name;
Capacity = capacity;
Hashes = hashes;
Hash = hashFunction;
ExpectedElements = BestN(hashes, capacity);
ErrorRate = BestP(hashes, capacity, ExpectedElements);
}
protected void SetFilterParam(long expectedElements, double errorRate, HashMethod method)
{
if (expectedElements < 1)
throw new ArgumentOutOfRangeException("expectedElements", expectedElements, "expectedElements must be > 0");
if (errorRate >= 1 || errorRate <= 0)
throw new ArgumentOutOfRangeException("errorRate", errorRate, string.Format("errorRate must be between 0 and 1, exclusive. Was {0}", errorRate));
ExpectedElements = expectedElements;
ErrorRate = errorRate;
Hash = HashFunction.Functions[method];
Capacity = BestM(expectedElements, errorRate);
Hashes = BestK(expectedElements, Capacity);
}
/// <summary>
/// Adds the passed value to the filter.
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public abstract bool Add(ReadOnlySpan<byte> data);
/// <summary>
/// Async Adds the passed value to the filter.
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public abstract ValueTask<bool> AddAsync(ReadOnlyMemory<byte> data);
/// <summary>
/// Adds the specified elements.
/// </summary>
/// <param name="elements">The elements.</param>
/// <returns></returns>
public abstract IList<bool> Add(IEnumerable<byte[]> elements);
/// <summary>
/// Async Adds the specified elements.
/// </summary>
/// <param name="elements">The elements.</param>
/// <returns></returns>
public abstract ValueTask<IList<bool>> AddAsync(IEnumerable<byte[]> elements);
/// <summary>
/// Removes all elements from the filter
/// </summary>
public abstract void Clear();
/// <summary>
/// Async Removes all elements from the filter
/// </summary>
public abstract ValueTask ClearAsync();
/// <summary>
/// Tests whether an element is present in the filter
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
public abstract bool Contains(ReadOnlySpan<byte> element);
/// <summary>
/// Async Tests whether an element is present in the filter
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
public abstract ValueTask<bool> ContainsAsync(ReadOnlyMemory<byte> element);
/// <summary>
/// Tests whether an elements is present in the filter
/// </summary>
/// <param name="elements"></param>
/// <returns></returns>
public abstract IList<bool> Contains(IEnumerable<byte[]> elements);
/// <summary>
/// Async Tests whether an elements is present in the filter
/// </summary>
/// <param name="elements"></param>
/// <returns></returns>
public abstract ValueTask<IList<bool>> ContainsAsync(IEnumerable<byte[]> elements);
/// <summary>
/// Alls the specified elements.
/// </summary>
/// <param name="elements">The elements.</param>
/// <returns></returns>
public abstract bool All(IEnumerable<byte[]> elements);
/// <summary>
/// Async Alls the specified elements.
/// </summary>
/// <param name="elements">The elements.</param>
/// <returns></returns>
public abstract ValueTask<bool> AllAsync(IEnumerable<byte[]> elements);
/// <summary>
/// Hashes the specified value.
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public long[] ComputeHash(ReadOnlySpan<byte> data)
{
return Hash.ComputeHash(data, Capacity, Hashes);
}
/// <summary>
/// Calculates the optimal size of the bloom filter in bits given expectedElements (expected
/// number of elements in bloom filter) and falsePositiveProbability (tolerable false positive rate).
/// </summary>
/// <param name="n">Expected number of elements inserted in the bloom filter</param>
/// <param name="p">Tolerable false positive rate</param>
/// <returns>the optimal siz of the bloom filter in bits</returns>
public static long BestM(long n, double p)
{
return (long)Math.Ceiling(-1 * (n * Math.Log(p)) / Math.Pow(Math.Log(2), 2));
}
/// <summary>
/// Calculates the optimal hashes (number of hash function) given expectedElements (expected number of
/// elements in bloom filter) and size (size of bloom filter in bits).
/// </summary>
/// <param name="n">Expected number of elements inserted in the bloom filter</param>
/// <param name="m">The size of the bloom filter in bits.</param>
/// <returns>the optimal amount of hash functions hashes</returns>
public static int BestK(long n, long m)
{
return (int)Math.Ceiling((Math.Log(2) * m) / n);
}
/// <summary>
/// Calculates the amount of elements a Bloom filter for which the given configuration of size and hashes is optimal.
/// </summary>
/// <param name="k">number of hashes</param>
/// <param name="m">The size of the bloom filter in bits.</param>
/// <returns>mount of elements a Bloom filter for which the given configuration of size and hashes is optimal</returns>
public static long BestN(int k, long m)
{
return (long)Math.Ceiling((Math.Log(2) * m) / k);
}
/// <summary>
/// Calculates the best-case (uniform hash function) false positive probability.
/// </summary>
/// <param name="k"> number of hashes</param>
/// <param name="m">The size of the bloom filter in bits.</param>
/// <param name="insertedElements">number of elements inserted in the filter</param>
/// <returns>The calculated false positive probability</returns>
public static double BestP(int k, long m, double insertedElements)
{
return Math.Pow((1 - Math.Exp(-k * insertedElements / m)), k);
}
public override string ToString()
{
return $"Capacity:{Capacity},Hashes:{Hashes},ExpectedElements:{ExpectedElements},ErrorRate:{ErrorRate}";
}
protected static int LogMaxInt(long number, out int mod)
{
mod = (int)(number % MaxInt);
return (int)(number / MaxInt);
}
/// <summary>
/// Dispose
/// </summary>
public abstract void Dispose();
}
================================================
FILE: src/BloomFilter/FilterBuilder.cs
================================================
using System;
using BloomFilter.Configurations;
namespace BloomFilter;
/// <summary>
/// BloomFilter Builder - Supports both static factory methods and fluent API
/// </summary>
/// <example>
/// Static API:
/// <code>
/// var filter = FilterBuilder.Build(10_000_000, 0.001);
/// </code>
///
/// Fluent API:
/// <code>
/// var filter = FilterBuilder.Create()
/// .WithName("UserFilter")
/// .ExpectingElements(10_000_000)
/// .WithErrorRate(0.001)
/// .UsingHashMethod(HashMethod.XXHash3)
/// .BuildInMemory();
/// </code>
/// </example>
public partial class FilterBuilder
{
#region Fluent API - Instance Members
protected string _name = BloomFilterConstValue.DefaultInMemoryName;
protected long _expectedElements = 1_000_000;
protected double _errorRate = 0.01;
protected HashMethod _method = HashMethod.Murmur3;
protected HashFunction? _customHashFunction;
protected IFilterMemorySerializer? _customSerializer;
/// <summary>
/// Protected constructor for fluent API pattern and inheritance
/// </summary>
protected FilterBuilder() { }
/// <summary>
/// Creates a new Fluent Builder for Bloom Filter construction
/// </summary>
/// <returns>A new FilterBuilder instance</returns>
public static FilterBuilder Create() => new();
/// <summary>
/// Sets the name for the Bloom Filter
/// </summary>
/// <param name="name">The filter name</param>
/// <returns>The builder for method chaining</returns>
/// <exception cref="ArgumentException">Thrown when name is null or whitespace</exception>
public FilterBuilder WithName(string name)
{
#if NET8_0_OR_GREATER
ArgumentException.ThrowIfNullOrWhiteSpace(name);
#else
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Name cannot be null or whitespace", nameof(name));
#endif
_name = name;
return this;
}
/// <summary>
/// Sets the expected number of elements to be added to the filter
/// </summary>
/// <param name="count">The expected element count (must be > 0)</param>
/// <returns>The builder for method chaining</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when count is less than or equal to 0</exception>
public FilterBuilder ExpectingElements(long count)
{
if (count <= 0)
throw new ArgumentOutOfRangeException(nameof(count), count, "Expected elements must be greater than 0");
_expectedElements = count;
return this;
}
/// <summary>
/// Sets the acceptable false positive rate (probability)
/// </summary>
/// <param name="rate">The error rate (must be between 0 and 1, exclusive)</param>
/// <returns>The builder for method chaining</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when rate is not between 0 and 1</exception>
public FilterBuilder WithErrorRate(double rate)
{
if (rate <= 0 || rate >= 1)
throw new ArgumentOutOfRangeException(nameof(rate), rate, "Error rate must be between 0 and 1 (exclusive)");
_errorRate = rate;
return this;
}
/// <summary>
/// Sets the hash method to use for hashing elements
/// </summary>
/// <param name="method">The hash method</param>
/// <returns>The builder for method chaining</returns>
public FilterBuilder UsingHashMethod(HashMethod method)
{
_method = method;
_customHashFunction = null;
return this;
}
/// <summary>
/// Uses a custom hash function for hashing elements
/// </summary>
/// <param name="hashFunction">The custom hash function</param>
/// <returns>The builder for method chaining</returns>
/// <exception cref="ArgumentNullException">Thrown when hashFunction is null</exception>
public FilterBuilder UsingCustomHash(HashFunction hashFunction)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(hashFunction);
#else
if (hashFunction == null)
throw new ArgumentNullException(nameof(hashFunction));
#endif
_customHashFunction = hashFunction;
return this;
}
/// <summary>
/// Uses a custom serializer for persisting the Bloom Filter
/// </summary>
/// <param name="serializer">The custom serializer</param>
/// <returns>The builder for method chaining</returns>
/// <exception cref="ArgumentNullException">Thrown when serializer is null</exception>
public FilterBuilder WithSerializer(IFilterMemorySerializer serializer)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(serializer);
#else
if (serializer == null)
throw new ArgumentNullException(nameof(serializer));
#endif
_customSerializer = serializer;
return this;
}
/// <summary>
/// Builds an in-memory Bloom Filter with the configured settings
/// </summary>
/// <returns>A new IBloomFilter instance</returns>
public IBloomFilter BuildInMemory()
{
var hashFunction = _customHashFunction ?? HashFunction.Functions[_method];
var serializer = _customSerializer ?? new DefaultFilterMemorySerializer();
return new FilterMemory(_name, _expectedElements, _errorRate, hashFunction, serializer);
}
/// <summary>
/// Builds an in-memory Bloom Filter with explicit capacity and hash count (advanced usage)
/// </summary>
/// <param name="capacity">The bit array capacity</param>
/// <param name="hashes">The number of hash functions</param>
/// <returns>A new IBloomFilter instance</returns>
public IBloomFilter BuildInMemoryWithCapacity(long capacity, int hashes)
{
var hashFunction = _customHashFunction ?? HashFunction.Functions[_method];
var serializer = _customSerializer ?? new DefaultFilterMemorySerializer();
return new FilterMemory(_name, capacity, hashes, hashFunction, serializer);
}
#endregion
#region Static Factory Methods (Legacy API - Backward Compatible)
/// <summary>
/// Creates a BloomFilter for the specified expected element
/// </summary>
/// <param name="options"><see cref="FilterMemoryOptions"/></param>
/// <returns></returns>
public static IBloomFilter Build(FilterMemoryOptions options)
{
return new FilterMemory(options, new DefaultFilterMemorySerializer());
}
/// <summary>
/// Creates a BloomFilter for the specified expected element
/// </summary>
/// <param name="options"><see cref="FilterMemoryOptions"/></param>
/// <param name="filterMemorySerializer"><see cref="IFilterMemorySerializer"/></param>
/// <returns></returns>
public static IBloomFilter Build(FilterMemoryOptions options, IFilterMemorySerializer filterMemorySerializer)
{
return new FilterMemory(options, filterMemorySerializer);
}
/// <summary>
/// Creates a BloomFilter for the specified expected element
/// </summary>
/// <param name="expectedElements">The expected elements.</param>
/// <param name="name"></param>
/// <returns></returns>
public static IBloomFilter Build(long expectedElements, string name = BloomFilterConstValue.DefaultInMemoryName)
{
return Build(expectedElements, 0.01, name);
}
/// <summary>
///Creates a BloomFilter for the specified expected element
/// </summary>
/// <param name="expectedElements">The expected elements.</param>
/// <param name="hashMethod">The hash method.</param>
/// <param name="name"></param>
/// <returns></returns>
public static IBloomFilter Build(long expectedElements, HashMethod hashMethod, string name = BloomFilterConstValue.DefaultInMemoryName)
{
return Build(expectedElements, 0.01, hashMethod, name);
}
/// <summary>
/// Creates a BloomFilter for the specified expected element
/// </summary>
/// <param name="expectedElements">The expected elements.</param>
/// <param name="hashFunction">The hash function.</param>
/// <param name="name"></param>
/// <returns></returns>
public static IBloomFilter Build(long expectedElements, HashFunction hashFunction, string name = BloomFilterConstValue.DefaultInMemoryName)
{
return Build(expectedElements, 0.01, hashFunction, name);
}
/// <summary>
/// Creates a BloomFilter for the specified expected element
/// </summary>
/// <param name="expectedElements">The expected elements.</param>
/// <param name="errorRate">The error rate.</param>
/// <param name="name"></param>
/// <returns></returns>
public static IBloomFilter Build(long expectedElements, double errorRate, string name = BloomFilterConstValue.DefaultInMemoryName)
{
return Build(expectedElements, errorRate, HashFunction.Functions[HashMethod.Murmur3], name);
}
/// <summary>
/// Creates a BloomFilter for the specified expected element
/// </summary>
/// <param name="expectedElements">The expected elements.</param>
/// <param name="errorRate">The error rate.</param>
/// <param name="hashMethod">The hash method.</param>
/// <param name="name"></param>
/// <param name="filterMemorySerializer"></param>
/// <returns></returns>
public static IBloomFilter Build(long expectedElements, double errorRate, HashMethod hashMethod, string name = BloomFilterConstValue.DefaultInMemoryName, IFilterMemorySerializer? filterMemorySerializer = null)
{
return new FilterMemory(name, expectedElements, errorRate, HashFunction.Functions[hashMethod], filterMemorySerializer ?? new DefaultFilterMemorySerializer());
}
/// <summary>
/// Creates a BloomFilter for the specified expected element
/// </summary>
/// <param name="expectedElements">The expected elements.</param>
/// <param name="errorRate">The error rate.</param>
/// <param name="hashFunction">The hash function.</param>
/// <param name="name"></param>
/// <param name="filterMemorySerializer"></param>
/// <returns></returns>
public static IBloomFilter Build(long expectedElements, double errorRate, HashFunction hashFunction, string name = BloomFilterConstValue.DefaultInMemoryName, IFilterMemorySerializer? filterMemorySerializer = null)
{
return new FilterMemory(name, expectedElements, errorRate, hashFunction, filterMemorySerializer ?? new DefaultFilterMemorySerializer());
}
#endregion
}
================================================
FILE: src/BloomFilter/FilterMemory.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using BloomFilter.Configurations;
namespace BloomFilter;
/// <summary>
/// Bloom Filter In Mempory Implement
/// </summary>
public class FilterMemory : Filter
{
//The upper limit per bucket is 2147483640
private BitArray[] _buckets;
private readonly AsyncLock _asyncLock = new();
private readonly IFilterMemorySerializer _filterMemorySerializer;
private static readonly ValueTask Empty = new();
/// <summary>
/// Initializes a new instance of the <see cref="FilterMemory"/> class.
/// </summary>
/// <param name="options"><see cref="FilterMemoryOptions"/></param>
/// <param name="filterMemorySerializer"></param>
public FilterMemory(FilterMemoryOptions options, IFilterMemorySerializer filterMemorySerializer)
: base(options.Name, options.ExpectedElements, options.ErrorRate, HashFunction.Functions[options.Method])
{
_filterMemorySerializer = filterMemorySerializer;
if (options.Buckets is not null)
{
Import(options.Buckets);
}
else if (options.BucketBytes is not null)
{
Import(options.BucketBytes);
}
else
{
Init();
}
}
/// <summary>
/// Initializes a new instance of the <see cref="FilterMemory"/> class.
/// </summary>
/// <param name="name"></param>
/// <param name="expectedElements">The expected elements.</param>
/// <param name="errorRate">The error rate.</param>
/// <param name="hashFunction">The hash function.</param>
/// <param name="filterMemorySerializer"></param>
public FilterMemory(string name, long expectedElements, double errorRate, HashFunction hashFunction, IFilterMemorySerializer filterMemorySerializer)
: base(name, expectedElements, errorRate, hashFunction)
{
_filterMemorySerializer = filterMemorySerializer;
Init();
}
/// <summary>
/// Initializes a new instance of the <see cref="FilterMemory"/> class.
/// </summary>
/// <param name="name"></param>
/// <param name="size">The size.</param>
/// <param name="hashes">The hashes.</param>
/// <param name="hashFunction">The hash function.</param>
/// <param name="filterMemorySerializer"></param>
public FilterMemory(string name, long size, int hashes, HashFunction hashFunction, IFilterMemorySerializer filterMemorySerializer)
: base(name, size, hashes, hashFunction)
{
_filterMemorySerializer = filterMemorySerializer;
Init();
}
[MemberNotNull(nameof(_buckets))]
private void Init()
{
var bits = new List<BitArray>();
var m = Capacity;
while (m > 0)
{
if (m > MaxInt)
{
bits.Add(new BitArray(MaxInt));
m -= MaxInt;
}
else
{
bits.Add(new BitArray((int)m));
break;
}
}
_buckets = bits.ToArray();
}
/// <summary>
/// Serialize to a stream
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
/// <remarks>
/// This method holds the lock during the entire serialization process (including I/O).
/// This ensures data consistency but will block other operations (Add/Contains) during serialization.
/// The BitArray is cloned to ensure immutability during serialization.
/// </remarks>
public async ValueTask SerializeAsync(Stream stream)
{
using var _ = await _asyncLock.AcquireAsync();
await _filterMemorySerializer.SerializeAsync(new FilterMemorySerializerParam
{
Name = Name,
Method = Hash.Method,
ExpectedElements = ExpectedElements,
ErrorRate = ErrorRate,
Buckets = _buckets.Select(s => new BitArray(s)).ToArray() // Clone to ensure immutability
}, stream);
}
/// <summary>
/// Deserialize from the stream
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public async ValueTask DeserializeAsync(Stream stream)
{
var param = await _filterMemorySerializer.DeserializeAsync(stream);
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(param.Buckets);
#else
if (param.Buckets is null)
throw new ArgumentNullException(nameof(FilterMemorySerializerParam.Buckets));
#endif
if (param.Buckets.Length == 0)
throw new ArgumentOutOfRangeException($"The length must greater than 0", nameof(FilterMemorySerializerParam.Buckets));
SetFilterParam(param.ExpectedElements, param.ErrorRate, param.Method);
if (Capacity > param.Buckets.Sum(s => (long)s.Length))
{
throw new ArgumentOutOfRangeException($"The length must less than or equal to {Capacity}", nameof(FilterMemorySerializerParam.Buckets));
}
using var _ = await _asyncLock.AcquireAsync();
_buckets = new BitArray[param.Buckets.Length];
for (int i = 0; i < param.Buckets.Length; i++)
{
_buckets[i] = new BitArray(param.Buckets[i]);
}
}
/// <summary>
/// Importing bitmap
/// </summary>
/// <param name="buckets">Sets the multiple bitmap</param>
[MemberNotNull(nameof(_buckets))]
public void Import(BitArray[] buckets)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(buckets);
#else
if (buckets is null)
throw new ArgumentNullException(nameof(buckets));
#endif
if (buckets.Length == 0)
throw new ArgumentOutOfRangeException($"The length must greater than 0", nameof(buckets));
if (Capacity > buckets.Sum(s => (long)s.Length))
{
throw new ArgumentOutOfRangeException($"The length must less than or equal to {Capacity}", nameof(buckets));
}
using var _ = _asyncLock.Acquire();
_buckets = new BitArray[buckets.Length];
for (int i = 0; i < buckets.Length; i++)
{
_buckets[i] = new BitArray(buckets[i]);
}
}
/// <summary>
/// Importing bitmap
/// </summary>
/// <param name="bucketBytes">Sets the multiple bitmaps</param>
[MemberNotNull(nameof(_buckets))]
public void Import(IList<byte[]> bucketBytes)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(bucketBytes);
#else
if (bucketBytes is null)
throw new ArgumentNullException(nameof(bucketBytes));
#endif
if (bucketBytes.Count == 0)
throw new ArgumentOutOfRangeException($"The length must greater than 0", nameof(bucketBytes));
Import(bucketBytes.Select(s => new BitArray(s)).ToArray());
}
/// <summary>
/// Exporting bitmap
/// </summary>
public BitArray[] Export()
{
using var _ = _asyncLock.Acquire();
return _buckets.Select(s => new BitArray(s)).ToArray();
}
/// <summary>
/// Exporting bitmap
/// </summary>
public IList<byte[]> ExportToBytes()
{
int Mod(int len) => len % 8 > 0 ? 1 : 0;
var result = new List<byte[]>();
using var _ = _asyncLock.Acquire();
foreach (var bucket in _buckets)
{
var bits = new byte[bucket.Length / 8 + Mod(bucket.Length)];
bucket.CopyTo(bits, 0);
result.Add(bits);
}
return result;
}
/// <summary>
/// Adds the passed value to the filter.
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public override bool Add(ReadOnlySpan<byte> data)
{
bool added = false;
var positions = ComputeHash(data);
using var _ = _asyncLock.Acquire();
foreach (var position in positions)
{
if (!Get(position))
{
added = true;
Set(position);
}
}
return added;
}
/// <summary>
/// Adds the passed value to the filter.
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public override ValueTask<bool> AddAsync(ReadOnlyMemory<byte> data)
{
return new ValueTask<bool>(Add(data.Span));
}
public override IList<bool> Add(IEnumerable<byte[]> elements)
{
// Pre-allocate capacity if possible
var elementsList = elements as IList<byte[]> ?? elements.ToList();
var hashes = new List<long>(elementsList.Count * Hashes);
foreach (var element in elementsList)
{
hashes.AddRange(ComputeHash(element));
}
var processResults = new bool[hashes.Count];
using (var _ = _asyncLock.Acquire())
{
for (var i = 0; i < hashes.Count; i++)
{
if (!Get(hashes[i]))
{
Set(hashes[i]);
processResults[i] = false;
}
else
{
processResults[i] = true;
}
}
}
IList<bool> results = new List<bool>(elementsList.Count);
bool wasAdded = false;
int processed = 0;
//For each value check, if all bits in ranges of hashes bits are set
foreach (var item in processResults)
{
if (!item) wasAdded = true;
if ((processed + 1) % Hashes == 0)
{
results.Add(wasAdded);
wasAdded = false;
}
processed++;
}
return results;
}
public override ValueTask<IList<bool>> AddAsync(IEnumerable<byte[]> elements)
{
return new ValueTask<IList<bool>>(Add(elements));
}
/// <summary>
/// Tests whether an element is present in the filter
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
public override bool Contains(ReadOnlySpan<byte> element)
{
var positions = ComputeHash(element);
using var _ = _asyncLock.Acquire();
foreach (var position in positions)
{
if (!Get(position))
return false;
}
return true;
}
public override ValueTask<bool> ContainsAsync(ReadOnlyMemory<byte> element)
{
return new ValueTask<bool>(Contains(element.Span));
}
public override IList<bool> Contains(IEnumerable<byte[]> elements)
{
// Pre-allocate capacity if possible
var elementsList = elements as IList<byte[]> ?? elements.ToList();
var hashes = new List<long>(elementsList.Count * Hashes);
foreach (var element in elementsList)
{
hashes.AddRange(ComputeHash(element));
}
var processResults = new bool[hashes.Count];
using (var _ = _asyncLock.Acquire())
{
for (var i = 0; i < hashes.Count; i++)
{
processResults[i] = Get(hashes[i]);
}
}
IList<bool> results = new List<bool>(elementsList.Count);
bool isPresent = true;
int processed = 0;
//For each value check, if all bits in ranges of hashes bits are set
foreach (var item in processResults)
{
if (!item) isPresent = false;
if ((processed + 1) % Hashes == 0)
{
results.Add(isPresent);
isPresent = true;
}
processed++;
}
return results;
}
public override ValueTask<IList<bool>> ContainsAsync(IEnumerable<byte[]> elements)
{
return new ValueTask<IList<bool>>(Contains(elements));
}
public override bool All(IEnumerable<byte[]> elements)
{
return Contains(elements).All(e => e);
}
public override ValueTask<bool> AllAsync(IEnumerable<byte[]> elements)
{
return new ValueTask<bool>(All(elements));
}
/// <summary>
/// Removes all elements from the filter
/// </summary>
public override void Clear()
{
using var _ = _asyncLock.Acquire();
foreach (var item in _buckets)
{
item.SetAll(false);
}
}
public override ValueTask ClearAsync()
{
Clear();
return Empty;
}
private void Set(long index)
{
int idx = LogMaxInt(index, out int mod);
_buckets[idx].Set(mod, true);
}
public bool Get(long index)
{
int idx = LogMaxInt(index, out int mod);
return _buckets[idx].Get(mod);
}
public override void Dispose()
{
_asyncLock.Dispose();
}
}
================================================
FILE: src/BloomFilter/FilterMemorySerializerParam.cs
================================================
using System.Collections;
namespace BloomFilter;
/// <summary>
/// FilterMemorySerializerParam
/// </summary>
public class FilterMemorySerializerParam
{
/// <summary>
/// Gets the name specified by BloomFilter.
/// </summary>
#if NET5_0_OR_GREATER
public string Name { get; init; } = default!;
#else
public string Name { get; set; } = default!;
#endif
/// <summary>
/// <see cref="HashMethod"/>
/// </summary>
#if NET5_0_OR_GREATER
public HashMethod Method { get; init; }
#else
public HashMethod Method { get; set; }
#endif
/// <summary>
/// the expected elements.
/// </summary>
#if NET5_0_OR_GREATER
public long ExpectedElements { get; init; }
#else
public long ExpectedElements { get; set; }
#endif
/// <summary>
/// the number of expected elements
/// </summary>
#if NET5_0_OR_GREATER
public double ErrorRate { get; init; }
#else
public double ErrorRate { get; set; }
#endif
/// <summary>
/// bitmap
/// </summary>
#if NET5_0_OR_GREATER
public BitArray[] Buckets { get; init; } = default!;
#else
public BitArray[] Buckets { get; set; } = default!;
#endif
}
================================================
FILE: src/BloomFilter/FilterRedisBase.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BloomFilter;
/// <summary>
/// Abstract base class for Redis-based Bloom Filter implementations.
/// Encapsulates common batch operation logic shared across all Redis implementations.
/// </summary>
public abstract class FilterRedisBase : Filter
{
protected FilterRedisBase(string name, long expectedElements, double errorRate, HashFunction hashFunction)
: base(name, expectedElements, errorRate, hashFunction)
{
}
protected FilterRedisBase(string name, long capacity, int hashes, HashFunction hashFunction)
: base(name, capacity, hashes, hashFunction)
{
}
// Abstract methods - to be implemented by concrete Redis client implementations
/// <summary>
/// Sets a bit at the specified position in the Redis bitmap.
/// </summary>
/// <param name="position">The bit position.</param>
/// <returns>The previous value of the bit (true if it was set, false otherwise).</returns>
protected abstract bool SetBit(long position);
/// <summary>
/// Gets the bit value at the specified position in the Redis bitmap.
/// </summary>
/// <param name="position">The bit position.</param>
/// <returns>The value of the bit (true if set, false otherwise).</returns>
protected abstract bool GetBit(long position);
/// <summary>
/// Asynchronously sets a bit at the specified position in the Redis bitmap.
/// </summary>
/// <param name="position">The bit position.</param>
/// <returns>The previous value of the bit.</returns>
protected abstract Task<bool> SetBitAsync(long position);
/// <summary>
/// Asynchronously gets the bit value at the specified position in the Redis bitmap.
/// </summary>
/// <param name="position">The bit position.</param>
/// <returns>The value of the bit.</returns>
protected abstract Task<bool> GetBitAsync(long position);
/// <summary>
/// Sets multiple bits at the specified positions in the Redis bitmap.
/// </summary>
/// <param name="positions">Array of bit positions.</param>
/// <returns>Array of previous bit values.</returns>
protected abstract bool[] SetBits(long[] positions);
/// <summary>
/// Gets multiple bits at the specified positions in the Redis bitmap.
/// </summary>
/// <param name="positions">Array of bit positions.</param>
/// <returns>Array of bit values.</returns>
protected abstract bool[] GetBits(long[] positions);
/// <summary>
/// Asynchronously sets multiple bits at the specified positions in the Redis bitmap.
/// </summary>
/// <param name="positions">Array of bit positions.</param>
/// <returns>Array of previous bit values.</returns>
protected abstract Task<bool[]> SetBitsAsync(long[] positions);
/// <summary>
/// Asynchronously gets multiple bits at the specified positions in the Redis bitmap.
/// </summary>
/// <param name="positions">Array of bit positions.</param>
/// <returns>Array of bit values.</returns>
protected abstract Task<bool[]> GetBitsAsync(long[] positions);
/// <summary>
/// Clears all bits in the Redis bitmap.
/// </summary>
protected abstract void ClearBits();
/// <summary>
/// Asynchronously clears all bits in the Redis bitmap.
/// </summary>
protected abstract Task ClearBitsAsync();
// Common implementations - shared by all Redis implementations
public override IList<bool> Add(IEnumerable<byte[]> elements)
{
// Pre-allocate capacity if possible
var elementsList = elements as IList<byte[]> ?? elements.ToList();
var hashes = new List<long>(elementsList.Count * Hashes);
foreach (var element in elementsList)
{
hashes.AddRange(ComputeHash(element));
}
var processResults = SetBits(hashes.ToArray());
return ProcessBatchResults(processResults, Hashes, trackAdded: true);
}
public override async ValueTask<IList<bool>> AddAsync(IEnumerable<byte[]> elements)
{
// Pre-allocate capacity if possible
var elementsList = elements as IList<byte[]> ?? elements.ToList();
var hashes = new List<long>(elementsList.Count * Hashes);
foreach (var element in elementsList)
{
hashes.AddRange(ComputeHash(element));
}
var processResults = await SetBitsAsync(hashes.ToArray());
return ProcessBatchResults(processResults, Hashes, trackAdded: true);
}
public override IList<bool> Contains(IEnumerable<byte[]> elements)
{
// Pre-allocate capacity if possible
var elementsList = elements as IList<byte[]> ?? elements.ToList();
var hashes = new List<long>(elementsList.Count * Hashes);
foreach (var element in elementsList)
{
hashes.AddRange(ComputeHash(element));
}
var processResults = GetBits(hashes.ToArray());
return ProcessBatchResults(processResults, Hashes, trackAdded: false);
}
public override async ValueTask<IList<bool>> ContainsAsync(IEnumerable<byte[]> elements)
{
// Pre-allocate capacity if possible
var elementsList = elements as IList<byte[]> ?? elements.ToList();
var hashes = new List<long>(elementsList.Count * Hashes);
foreach (var element in elementsList)
{
hashes.AddRange(ComputeHash(element));
}
var processResults = await GetBitsAsync(hashes.ToArray());
return ProcessBatchResults(processResults, Hashes, trackAdded: false);
}
public override bool All(IEnumerable<byte[]> elements)
=> Contains(elements).All(e => e);
public override ValueTask<bool> AllAsync(IEnumerable<byte[]> elements)
=> new(Contains(elements).All(e => e));
public override void Clear()
=> ClearBits();
public override async ValueTask ClearAsync()
=> await ClearBitsAsync();
/// <summary>
/// Processes batch operation results, converting bit-level results to element-level results.
/// </summary>
/// <param name="processResults">Bit-level operation results (from Redis).</param>
/// <param name="hashes">Number of hash functions (bits per element).</param>
/// <param name="trackAdded">If true, tracks additions (wasAdded logic); if false, tracks presence (isPresent logic).</param>
/// <returns>Element-level results.</returns>
protected static IList<bool> ProcessBatchResults(bool[] processResults, int hashes, bool trackAdded)
{
var results = new List<bool>(processResults.Length / hashes);
bool flag = trackAdded ? false : true;
int processed = 0;
foreach (var item in processResults)
{
if (trackAdded && !item) flag = true; // Add: any bit not previously set = new addition
if (!trackAdded && !item) flag = false; // Contains: any bit not set = not present
if ((processed + 1) % hashes == 0)
{
results.Add(flag);
flag = trackAdded ? false : true;
}
processed++;
}
return results;
}
}
================================================
FILE: src/BloomFilter/HashAlgorithms/Adler32.cs
================================================
using System;
namespace BloomFilter.HashAlgorithms;
public class Adler32 : HashFunction
{
public override HashMethod Method => HashMethod.Adler32;
private const int seed32 = 89_478_583;
public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, int k)
{
long[] positions = new long[k];
int hashes = 0;
int salt = 0;
var adler32 = new Internal.Adler32();
while (hashes < k)
{
adler32.Append(data);
adler32.Append(BitConverter.GetBytes(hashes + salt++ + seed32));
var adlerValue = adler32.GetCurrentHashAsUInt32();
adler32.Reset();
long hash = BinaryHelper.Rejection(adlerValue, m);
if (hash != -1)
{
positions[hashes++] = hash;
}
}
return positions;
}
}
================================================
FILE: src/BloomFilter/HashAlgorithms/Crc32.cs
================================================
using System;
namespace BloomFilter.HashAlgorithms;
public partial class Crc32 : HashFunction
{
public override HashMethod Method => HashMethod.CRC32;
private const int seed32 = 89_478_583;
public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, int k)
{
long[] positions = new long[k];
int hashes = 0;
int salt = 0;
var crc32 = new Internal.Crc32();
while (hashes < k)
{
crc32.Append(data);
crc32.Append(BitConverter.GetBytes(hashes + salt++ + seed32));
var crc = crc32.GetCurrentHashAsUInt32();
crc32.Reset();
long hash = BinaryHelper.Rejection(crc, m);
if (hash != -1)
{
positions[hashes++] = hash;
}
}
return positions;
}
}
================================================
FILE: src/BloomFilter/HashAlgorithms/Crc64.cs
================================================
using System;
namespace BloomFilter.HashAlgorithms;
public partial class Crc64 : HashFunction
{
public override HashMethod Method => HashMethod.CRC64;
public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, int k)
{
long[] positions = new long[k];
var hash = Internal.Crc64.HashToUInt64(data);
uint hash1 = (uint)hash;
uint hash2 = (uint)(hash >> 32);
for (int i = 0; i < k; i++)
{
positions[i] = ((hash1 + (i * hash2)) % m);
}
return positions;
}
}
================================================
FILE: src/BloomFilter/HashAlgorithms/HashCrypto.cs
================================================
using System;
using System.Collections;
using System.Security.Cryptography;
namespace BloomFilter.HashAlgorithms;
public class HashCryptoSHA1 : HashCrypto
{
public override HashMethod Method => HashMethod.SHA1;
public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, int k)
{
using var hashAlgorithm = SHA1.Create();
return ComputeHash(hashAlgorithm, data, m, k);
}
}
public class HashCryptoSHA256 : HashCrypto
{
public override HashMethod Method => HashMethod.SHA256;
public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, int k)
{
using var hashAlgorithm = SHA256.Create();
return ComputeHash(hashAlgorithm, data, m, k);
}
}
public class HashCryptoSHA384 : HashCrypto
{
public override HashMethod Method => HashMethod.SHA384;
public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, int k)
{
using var hashAlgorithm = SHA384.Create();
return ComputeHash(hashAlgorithm, data, m, k);
}
}
public class HashCryptoSHA512 : HashCrypto
{
public override HashMethod Method => HashMethod.SHA512;
public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, int k)
{
using var hashAlgorithm = SHA512.Create();
return ComputeHash(hashAlgorithm, data, m, k);
}
}
public abstract class HashCrypto : HashFunction
{
protected long[] ComputeHash(HashAlgorithm hashAlgorithm, ReadOnlySpan<byte> data, long m, int k)
{
long[] positions = new long[k];
int computedHashes = 0;
byte[] digest = new byte[hashAlgorithm.HashSize / 8];
byte[] output = new byte[hashAlgorithm.HashSize / 8];
#if !NET6_0_OR_GREATER
var bytes = data.ToArray();
#endif
while (computedHashes < k)
{
hashAlgorithm.TransformBlock(digest, 0, digest.Length, output, 0);
#if NET6_0_OR_GREATER
hashAlgorithm.TryComputeHash(data, digest, out int bytesWritten);
#else
digest = hashAlgorithm.ComputeHash(bytes, 0, bytes.Length);
#endif
BitArray hashed = new(digest);
int filterSize = 32 - (int)BinaryHelper.NumberOfLeadingZeros((uint)m);
for (int split = 0; split < (hashAlgorithm.HashSize / filterSize) && computedHashes < k; split++)
{
int from = split * filterSize;
int to = ((split + 1) * filterSize);
int intHash = BinaryHelper.BitToIntOne(hashed, from, to);
if (intHash < m)
{
positions[computedHashes] = (uint)intHash;
computedHashes++;
}
}
}
return positions;
}
}
================================================
FILE: src/BloomFilter/HashAlgorithms/Internal/Adler32.cs
================================================
using System;
using System.Buffers.Binary;
using System.Runtime.InteropServices;
#if NET6_0_OR_GREATER
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
namespace BloomFilter.HashAlgorithms.Internal;
/// <summary>
/// Adler32 algorithm
/// </summary>
internal sealed partial class Adler32 : NonCryptoHashAlgorithm
{
private const int Size = sizeof(uint);
private uint _adler;
private uint _alderInitial;
// largest prime smaller than 65536
private const int MOD32 = 65_521;
// NMAX32 is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
private const int NMAX32 = 5_552;
/// <summary>
/// Initializes a new instance of the <see cref="Adler32"/> class.
/// </summary>
public Adler32(uint adler = 1)
: base(Size)
{
_alderInitial = adler;
_adler = adler;
}
/// <summary>
/// Appends the contents of <paramref name="source"/> to the data already
/// processed for the current hash computation.
/// </summary>
/// <param name="source">The data to process.</param>
public override void Append(ReadOnlySpan<byte> source)
{
_adler = Update(_adler, source);
}
/// <summary>
/// Resets the hash computation to the initial state.
/// </summary>
public override void Reset()
{
_adler = _alderInitial;
}
/// <summary>
/// Writes the computed hash value to <paramref name="destination"/>
/// without modifying accumulated state.
/// </summary>
/// <param name="destination">The buffer that receives the computed hash value.</param>
protected override void GetCurrentHashCore(Span<byte> destination)
{
BinaryPrimitives.WriteUInt32LittleEndian(destination, _adler);
}
/// <summary>
/// Writes the computed hash value to <paramref name="destination"/>
/// then clears the accumulated state.
/// </summary>
protected override void GetHashAndResetCore(Span<byte> destination)
{
BinaryPrimitives.WriteUInt32LittleEndian(destination, _adler);
_adler = _alderInitial;
}
/// <summary>Gets the current computed hash value without modifying accumulated state.</summary>
/// <returns>The hash value for the data already provided.</returns>
public uint GetCurrentHashAsUInt32() => _adler;
private static uint Update(uint adler, ReadOnlySpan<byte> source)
{
#if NET6_0_OR_GREATER
if (Ssse3.IsSupported)
{
return GetSse(source, adler);
}
#endif
return GetSimple(source, adler);
}
internal static uint GetSimple(ReadOnlySpan<byte> source, uint adler)
{
var count = source.Length;
uint s1 = adler & 0xFFFF;
uint s2 = adler >> 16;
int offset = 0;
while (count > 0)
{
int n = NMAX32;
if (n > count)
{
n = count;
}
count -= n;
while (--n >= 0)
{
s1 = s1 + (uint)(source[offset++] & 0xff);
s2 = s2 + s1;
}
s1 %= MOD32;
s2 %= MOD32;
}
adler = (s2 << 16) | s1;
return adler;
}
#if NET6_0_OR_GREATER
internal static unsafe uint GetSse(ReadOnlySpan<byte> buffer, uint adler)
{
const int BLOCK_SIZE = 32;
uint s1 = adler & 0xFFFF;
uint s2 = adler >> 16;
uint len = (uint)buffer.Length;
uint blocks = len / BLOCK_SIZE;
len = len - blocks * BLOCK_SIZE;
Vector128<sbyte> tap1 = Vector128.Create(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17);
Vector128<sbyte> tap2 = Vector128.Create(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
Vector128<byte> zero = Vector128<byte>.Zero;
Vector128<short> ones = Vector128.Create(1, 1, 1, 1, 1, 1, 1, 1);
fixed (byte* bufPtr = &MemoryMarshal.GetReference(buffer))
{
var buf = bufPtr;
while (blocks != 0)
{
uint n = NMAX32 / BLOCK_SIZE;
if (n > blocks)
{
n = blocks;
}
blocks -= n;
// Process n blocks of data. At most NMAX data bytes can be
// processed before s2 must be reduced modulo BASE.
Vector128<uint> v_ps = Vector128.Create(0, 0, 0, s1 * n);
Vector128<uint> v_s2 = Vector128.Create(0, 0, 0, s2);
Vector128<uint> v_s1 = Vector128.Create(0u, 0, 0, 0);
do
{
// Load 32 input bytes.
Vector128<byte> bytes1 = Sse2.LoadVector128(&buf[0]);
Vector128<byte> bytes2 = Sse2.LoadVector128(&buf[16]);
// Add previous block byte sum to v_ps.
v_ps = Sse2.Add(v_ps, v_s1);
// Horizontally add the bytes for s1, multiply-adds the
// bytes by [ 32, 31, 30, ... ] for s2.
Vector128<ushort> sad1 = Sse2.SumAbsoluteDifferences(bytes1, zero);
v_s1 = Sse2.Add(v_s1, sad1.AsUInt32());
Vector128<short> mad11 = Ssse3.MultiplyAddAdjacent(bytes1, tap1);
Vector128<int> mad12 = Sse2.MultiplyAddAdjacent(mad11, ones);
v_s2 = Sse2.Add(v_s2, mad12.AsUInt32());
Vector128<ushort> sad2 = Sse2.SumAbsoluteDifferences(bytes2, zero);
v_s1 = Sse2.Add(v_s1, sad2.AsUInt32());
Vector128<short> mad21 = Ssse3.MultiplyAddAdjacent(bytes2, tap2);
Vector128<int> mad22 = Sse2.MultiplyAddAdjacent(mad21, ones);
v_s2 = Sse2.Add(v_s2, mad22.AsUInt32());
buf += BLOCK_SIZE;
n--;
} while (n != 0);
var shift = Sse2.ShiftLeftLogical(v_ps, 5);
v_s2 = Sse2.Add(v_s2, shift);
// Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
// A B C D -> B A D C
const int S2301 = 2 << 6 | 3 << 4 | 0 << 2 | 1;
// A B C D -> C D A B
const int S1032 = 1 << 6 | 0 << 4 | 3 << 2 | 2;
v_s1 = Sse2.Add(v_s1, Sse2.Shuffle(v_s1, S2301));
v_s1 = Sse2.Add(v_s1, Sse2.Shuffle(v_s1, S1032));
s1 += Sse2.ConvertToUInt32(v_s1);
v_s2 = Sse2.Add(v_s2, Sse2.Shuffle(v_s2, S2301));
v_s2 = Sse2.Add(v_s2, Sse2.Shuffle(v_s2, S1032));
s2 = Sse2.ConvertToUInt32(v_s2);
s1 %= MOD32;
s2 %= MOD32;
}
if (len > 0)
{
if (len >= 16)
{
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
s2 += (s1 += *buf++);
len -= 16;
}
while (len-- > 0)
{
s2 += (s1 += *buf++);
}
if (s1 >= MOD32)
{
s1 -= MOD32;
}
s2 %= MOD32;
}
return s1 | (s2 << 16);
}
}
#endif
}
================================================
FILE: src/BloomFilter/HashAlgorithms/Internal/Crc32.Arm.cs
================================================
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#if NET6_0_OR_GREATER
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using ArmCrc = System.Runtime.Intrinsics.Arm.Crc32;
namespace BloomFilter.HashAlgorithms.Internal;
internal partial class Crc32
{
private static uint UpdateScalarArm64(uint crc, ReadOnlySpan<byte> source)
{
Debug.Assert(ArmCrc.Arm64.IsSupported, "ARM CRC support is required.");
// Compute in 8 byte chunks
if (source.Length >= sizeof(ulong))
{
ref byte ptr = ref MemoryMarshal.GetReference(source);
int longLength = source.Length & ~0x7; // Exclude trailing bytes not a multiple of 8
for (int i = 0; i < longLength; i += sizeof(ulong))
{
crc = ArmCrc.Arm64.ComputeCrc32(crc,
Unsafe.ReadUnaligned<ulong>(ref Unsafe.Add(ref ptr, i)));
}
source = source.Slice(longLength);
}
// Compute remaining bytes
for (int i = 0; i < source.Length; i++)
{
crc = ArmCrc.ComputeCrc32(crc, source[i]);
}
return crc;
}
private static uint UpdateScalarArm32(uint crc, ReadOnlySpan<byte> source)
{
Debug.Assert(ArmCrc.IsSupported, "ARM CRC support is required.");
// Compute in 4 byte chunks
if (source.Length >= sizeof(uint))
{
ref byte ptr = ref MemoryMarshal.GetReference(source);
int intLength = source.Length & ~0x3; // Exclude trailing bytes not a multiple of 4
for (int i = 0; i < intLength; i += sizeof(uint))
{
crc = ArmCrc.ComputeCrc32(crc,
Unsafe.ReadUnaligned<uint>(ref Unsafe.Add(ref ptr, i)));
}
source = source.Slice(intLength);
}
// Compute remaining bytes
for (int i = 0; i < source.Length; i++)
{
crc = ArmCrc.ComputeCrc32(crc, source[i]);
}
return crc;
}
}
#endif
================================================
FILE: src/BloomFilter/HashAlgorithms/Internal/Crc32.Table.cs
================================================
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
namespace BloomFilter.HashAlgorithms.Internal;
internal partial class Crc32 : NonCryptoHashAlgorithm
{
/// <summary>CRC-32 transition table</summary>
/// <remarks>
/// While this implementation is based on the standard CRC-32 polynomial,
/// x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x1 + x0,
/// this version uses reflected bit ordering, so 0x04C11DB7 becomes 0xEDB88320
/// </remarks>
private static ReadOnlySpan<uint> CrcLookup => new uint[]
{
// Generated by GenerateTable(0xEDB88320u):
//
// static uint[] GenerateTable(uint reflectedPolynomial)
// {
// uint[] table = new uint[256];
// for (int i = 0; i < table.Length; i++)
// {
// uint val = (uint)i;
// for (int j = 0; j < 8; j++)
// {
// if ((val & 0b0000_0001) == 0)
// {
// val >>= 1;
// }
// else
// {
// val = (val >> 1) ^ reflectedPolynomial;
// }
// }
// table[i] = val;
// }
// return table;
// }
0x0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x76DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0xEDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x9B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x1DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x6B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0xF00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x86D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x3B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x4DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0xD6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0xA00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x26D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x5005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0xCB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0xBDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
};
}
================================================
FILE: src/BloomFilter/HashAlgorithms/Internal/Crc32.Vectorized.cs
================================================
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#if NET7_0_OR_GREATER
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.InteropServices;
using System;
using static BloomFilter.HashAlgorithms.Internal.VectorHelper;
namespace BloomFilter.HashAlgorithms.Internal
{
internal partial class Crc32
{
// We check for little endian byte order here in case we're ever on ARM in big endian mode.
// All of these checks except the length check are elided by JIT, so the JITted implementation
// will be either a return false or a length check against a constant. This means this method
// should be inlined into the caller.
private static bool CanBeVectorized(ReadOnlySpan<byte> source) =>
BitConverter.IsLittleEndian
&& VectorHelper.IsSupported
// Vectorization can process spans as short as a single vector (16 bytes), but if ARM intrinsics are supported they
// seem to be more performant for spans less than 8 vectors (128 bytes).
&& source.Length >= Vector128<byte>.Count * (System.Runtime.Intrinsics.Arm.Crc32.IsSupported ? 8 : 1);
// Processes the bytes in source in 64 byte chunks using carryless/polynomial multiplication intrinsics,
// followed by processing 16 byte chunks, and then processing remaining bytes individually. Requires
// little endian byte order and support for PCLMULQDQ intrinsics on Intel architecture or AES and
// AdvSimd intrinsics on ARM architecture. Based on the algorithm put forth in the Intel paper "Fast CRC
// Computation for Generic Polynomials Using PCLMULQDQ Instruction" in December, 2009.
// https://github.com/intel/isa-l/blob/33a2d9484595c2d6516c920ce39a694c144ddf69/crc/crc32_ieee_by4.asm
// https://github.com/SixLabors/ImageSharp/blob/f4f689ce67ecbcc35cebddba5aacb603e6d1068a/src/ImageSharp/Formats/Png/Zlib/Crc32.cs#L80
private static uint UpdateVectorized(uint crc, ReadOnlySpan<byte> source)
{
Debug.Assert(CanBeVectorized(source), "source cannot be vectorized.");
// Work with a reference to where we're at in the ReadOnlySpan and a local length
// to avoid extraneous range checks.
ref byte srcRef = ref MemoryMarshal.GetReference(source);
int length = source.Length;
Vector128<ulong> kConstants;
Vector128<ulong> x1; // Accumulator for the new CRC
Vector128<ulong> x2;
if (length >= Vector128<byte>.Count * 8)
{
x1 = Vector128.LoadUnsafe(ref srcRef).AsUInt64();
x2 = Vector128.LoadUnsafe(ref srcRef, 16).AsUInt64();
Vector128<ulong> x3 = Vector128.LoadUnsafe(ref srcRef, 32).AsUInt64();
Vector128<ulong> x4 = Vector128.LoadUnsafe(ref srcRef, 48).AsUInt64();
srcRef = ref Unsafe.Add(ref srcRef, Vector128<byte>.Count * 4);
length -= Vector128<byte>.Count * 4;
// Load and XOR the initial CRC value
x1 ^= Vector128.CreateScalar(crc).AsUInt64();
kConstants = Vector128.Create(0x0154442bd4UL, 0x01c6e41596UL); // k1, k2
// Parallel fold blocks of 64, if any.
do
{
Vector128<ulong> y5 = Vector128.LoadUnsafe(ref srcRef).AsUInt64();
Vector128<ulong> y6 = Vector128.LoadUnsafe(ref srcRef, 16).AsUInt64();
Vector128<ulong> y7 = Vector128.LoadUnsafe(ref srcRef, 32).AsUInt64();
Vector128<ulong> y8 = Vector128.LoadUnsafe(ref srcRef, 48).AsUInt64();
x1 = FoldPolynomialPair(y5, x1, kConstants);
x2 = FoldPolynomialPair(y6, x2, kConstants);
x3 = FoldPolynomialPair(y7, x3, kConstants);
x4 = FoldPolynomialPair(y8, x4, kConstants);
srcRef = ref Unsafe.Add(ref srcRef, Vector128<byte>.Count * 4);
length -= Vector128<byte>.Count * 4;
} while (length >= Vector128<byte>.Count * 4);
// Fold into 128-bits.
kConstants = Vector128.Create(0x01751997d0UL, 0x00ccaa009eUL); // k3, k4
x1 = FoldPolynomialPair(x2, x1, kConstants);
x1 = FoldPolynomialPair(x3, x1, kConstants);
x1 = FoldPolynomialPair(x4, x1, kConstants);
}
else
{
// For shorter sources just load the first vector and XOR with the CRC
Debug.Assert(length >= 16);
x1 = Vector128.LoadUnsafe(ref srcRef).AsUInt64();
x1 ^= Vector128.Create
gitextract_745aaz2k/
├── .gitignore
├── BloomFilter.NetCore.sln
├── Directory.Build.props
├── Directory.Packages.props
├── LICENSE
├── README.md
├── README.zh-CN.md
├── VERSION
├── build.cmd
├── build.sh
├── nuget_push.cmd
├── sign.snk
├── src/
│ ├── BloomFilter/
│ │ ├── Annotations.cs
│ │ ├── AsyncLock.cs
│ │ ├── BinaryHelper.cs
│ │ ├── BloomFilter.csproj
│ │ ├── BloomFilterConstValue.cs
│ │ ├── BloomFilterExtensions.cs
│ │ ├── Configurations/
│ │ │ ├── BloomFilterOptions.cs
│ │ │ ├── FilterMemoryOptions.cs
│ │ │ ├── FilterMemoryOptionsExtension.cs
│ │ │ └── IBloomFilterOptionsExtension.cs
│ │ ├── DefaultBloomFilterFactory.cs
│ │ ├── DefaultFilterMemorySerializer.cs
│ │ ├── Filter.cs
│ │ ├── FilterBuilder.cs
│ │ ├── FilterMemory.cs
│ │ ├── FilterMemorySerializerParam.cs
│ │ ├── FilterRedisBase.cs
│ │ ├── HashAlgorithms/
│ │ │ ├── Adler32.cs
│ │ │ ├── Crc32.cs
│ │ │ ├── Crc64.cs
│ │ │ ├── HashCrypto.cs
│ │ │ ├── Internal/
│ │ │ │ ├── Adler32.cs
│ │ │ │ ├── Crc32.Arm.cs
│ │ │ │ ├── Crc32.Table.cs
│ │ │ │ ├── Crc32.Vectorized.cs
│ │ │ │ ├── Crc32.cs
│ │ │ │ ├── Crc64.Table.cs
│ │ │ │ ├── Crc64.Vectorized.cs
│ │ │ │ ├── Crc64.cs
│ │ │ │ ├── FNV1.cs
│ │ │ │ ├── FNV1a.cs
│ │ │ │ ├── ModifiedFNV1.cs
│ │ │ │ ├── Murmur128BitsX64.State.cs
│ │ │ │ ├── Murmur128BitsX64.cs
│ │ │ │ ├── Murmur128BitsX86.State.cs
│ │ │ │ ├── Murmur128BitsX86.cs
│ │ │ │ ├── Murmur32BitsX86.State.cs
│ │ │ │ ├── Murmur32BitsX86.cs
│ │ │ │ ├── NonCryptoHashAlgorithm.cs
│ │ │ │ ├── ThrowHelper.cs
│ │ │ │ ├── VectorHelper.cs
│ │ │ │ ├── XxHash128.cs
│ │ │ │ ├── XxHash3.cs
│ │ │ │ ├── XxHash32.State.cs
│ │ │ │ ├── XxHash32.cs
│ │ │ │ ├── XxHash64.State.cs
│ │ │ │ ├── XxHash64.cs
│ │ │ │ └── XxHashShared.cs
│ │ │ ├── LCGWithFNV.cs
│ │ │ ├── Murmur128BitsX64.cs
│ │ │ ├── Murmur128BitsX86.cs
│ │ │ ├── Murmur32BitsX86.cs
│ │ │ ├── RNGWithFNV.cs
│ │ │ ├── XXHash128.cs
│ │ │ ├── XXHash3.cs
│ │ │ ├── XXHash32.cs
│ │ │ └── XXHash64.cs
│ │ ├── HashFunction.cs
│ │ ├── HashMethod.cs
│ │ ├── IBloomFilter.cs
│ │ ├── IBloomFilterFactory.cs
│ │ ├── IFilterMemorySerializer.cs
│ │ ├── Properties/
│ │ │ └── AssemblyInfo.cs
│ │ ├── ServiceCollectionExtensions.cs
│ │ └── StringSpanExtensions.cs
│ ├── BloomFilter.CSRedis/
│ │ ├── BloomFilter.CSRedis.csproj
│ │ ├── Configurations/
│ │ │ ├── FilterCSRedisOptions.cs
│ │ │ ├── FilterCSRedisOptionsExtension.cs
│ │ │ └── ServiceCollectionExtensions.cs
│ │ ├── FilterCSRedis.cs
│ │ └── FilterCSRedisBuilder.cs
│ ├── BloomFilter.EasyCaching/
│ │ ├── BloomFilter.EasyCaching.csproj
│ │ ├── Configurations/
│ │ │ ├── FilterEasyCachingRedisExtension.cs
│ │ │ ├── FilterEasyCachingRedisOptions.cs
│ │ │ └── ServiceCollectionExtensions.cs
│ │ ├── FilterEasyCachingBuilder.cs
│ │ └── FilterEasyCachingRedis.cs
│ ├── BloomFilter.FreeRedis/
│ │ ├── BloomFilter.FreeRedis.csproj
│ │ ├── Configurations/
│ │ │ ├── FilterFreeRedisOptions.cs
│ │ │ ├── FilterFreeRedisOptionsExtension.cs
│ │ │ └── ServiceCollectionExtensions.cs
│ │ ├── FilterFreeRedis.cs
│ │ └── FilterFreeRedisBuilder.cs
│ └── BloomFilter.Redis/
│ ├── BloomFilter.Redis.csproj
│ ├── Configurations/
│ │ ├── FilterRedisOptions.cs
│ │ ├── FilterRedisOptionsExtension.cs
│ │ └── ServiceCollectionExtensions.cs
│ ├── FilterRedis.cs
│ ├── FilterRedisBuilder.cs
│ ├── IRedisBitOperate.cs
│ └── RedisBitOperate.cs
└── test/
├── BenchmarkTest/
│ ├── BenchmarkTest.csproj
│ ├── FreeRedisBenchmark.cs
│ ├── Helper.cs
│ ├── MemoryBenchmark.cs
│ ├── Program.cs
│ └── RedisBenchmark.cs
├── BloomFilter.Redis.Test/
│ ├── BloomFilter.Redis.Test.csproj
│ ├── BloomFilterCSRedisTest.cs
│ ├── BloomFilterEasyCachingRedisTest.cs
│ ├── BloomFilterFreeRedisTest.cs
│ ├── BloomFilterRedisTest.cs
│ ├── ConfigurationsTest.cs
│ ├── RedisBitOperateTest.cs
│ └── Utilitiy.cs
├── BloomFilterTest/
│ ├── AsyncLockTests.cs
│ ├── BloomFilterTest.cs
│ ├── BloomFilterTest.csproj
│ ├── ConfigurationsTest.cs
│ ├── FluentFilterBuilderTest.cs
│ ├── HashAlgorithms/
│ │ ├── Adler32Test.cs
│ │ ├── CrcTest.cs
│ │ ├── FNVTest.cs
│ │ ├── Murmur3Test.cs
│ │ ├── TestPayloadParameter.cs
│ │ └── XxHashTest.cs
│ ├── ImportExportTest.cs
│ ├── IssuesTest.cs
│ ├── SerializerTest.cs
│ ├── Utilitiy.cs
│ ├── ValueTypeTest.cs
│ └── xunit.runner.json
├── Demo/
│ ├── BloomFilterMemory.cs
│ ├── BloomFilterRedis.cs
│ ├── Demo.csproj
│ ├── Program.cs
│ └── TestExcute.cs
└── PerformanceTest/
├── GeneralPerformance.cs
├── HashErrRate.cs
├── HashSpeed.cs
├── Helper.cs
├── Issues_2.cs
├── PerformanceTest.csproj
├── Program.cs
└── TestExcute.cs
SYMBOL INDEX (983 symbols across 123 files)
FILE: src/BloomFilter.CSRedis/Configurations/FilterCSRedisOptions.cs
class FilterCSRedisOptions (line 8) | public class FilterCSRedisOptions : FilterMemoryOptions
FILE: src/BloomFilter.CSRedis/Configurations/FilterCSRedisOptionsExtension.cs
class FilterCSRedisOptionsExtension (line 10) | public class FilterCSRedisOptionsExtension : IBloomFilterOptionsExtension
method FilterCSRedisOptionsExtension (line 18) | public FilterCSRedisOptionsExtension(FilterCSRedisOptions options)
method AddServices (line 23) | public void AddServices(IServiceCollection services)
FILE: src/BloomFilter.CSRedis/Configurations/ServiceCollectionExtensions.cs
class ServiceCollectionExtensions (line 8) | public static class ServiceCollectionExtensions
method UseCSRedis (line 16) | public static BloomFilterOptions UseCSRedis(this BloomFilterOptions op...
method UseCSRedis (line 33) | public static BloomFilterOptions UseCSRedis(this BloomFilterOptions op...
FILE: src/BloomFilter.CSRedis/FilterCSRedis.cs
class FilterCSRedis (line 11) | public class FilterCSRedis : FilterRedisBase
method FilterCSRedis (line 25) | public FilterCSRedis(string name, CSRedisClient client, string redisKe...
method FilterCSRedis (line 42) | public FilterCSRedis(string name, CSRedisClient client, string redisKe...
method SetBit (line 52) | protected override bool SetBit(long position)
method GetBit (line 55) | protected override bool GetBit(long position)
method SetBitAsync (line 58) | protected override async Task<bool> SetBitAsync(long position)
method GetBitAsync (line 61) | protected override async Task<bool> GetBitAsync(long position)
method SetBits (line 64) | protected override bool[] SetBits(long[] positions)
method GetBits (line 85) | protected override bool[] GetBits(long[] positions)
method SetBitsAsync (line 106) | protected override async Task<bool[]> SetBitsAsync(long[] positions)
method GetBitsAsync (line 127) | protected override async Task<bool[]> GetBitsAsync(long[] positions)
method ClearBits (line 148) | protected override void ClearBits()
method ClearBitsAsync (line 151) | protected override async Task ClearBitsAsync()
method Add (line 156) | public override bool Add(ReadOnlySpan<byte> data)
method AddAsync (line 162) | public override async ValueTask<bool> AddAsync(ReadOnlyMemory<byte> data)
method Contains (line 169) | public override bool Contains(ReadOnlySpan<byte> element)
method ContainsAsync (line 175) | public override async ValueTask<bool> ContainsAsync(ReadOnlyMemory<byt...
method Dispose (line 182) | public override void Dispose()
FILE: src/BloomFilter.CSRedis/FilterCSRedisBuilder.cs
class FilterCSRedisBuilder (line 22) | public class FilterCSRedisBuilder : FilterBuilder
method WithRedisKey (line 35) | public FilterCSRedisBuilder WithRedisKey(string redisKey)
method WithRedisClient (line 49) | public FilterCSRedisBuilder WithRedisClient(CSRedisClient client)
method BuildCSRedis (line 66) | public IBloomFilter BuildCSRedis()
method BuildCSRedisWithCapacity (line 87) | public IBloomFilter BuildCSRedisWithCapacity(long capacity, int hashes)
FILE: src/BloomFilter.EasyCaching/Configurations/FilterEasyCachingRedisExtension.cs
class FilterEasyCachingRedisExtension (line 9) | public class FilterEasyCachingRedisExtension : IBloomFilterOptionsExtension
method FilterEasyCachingRedisExtension (line 17) | public FilterEasyCachingRedisExtension(FilterEasyCachingRedisOptions o...
method AddServices (line 22) | public void AddServices(IServiceCollection services)
FILE: src/BloomFilter.EasyCaching/Configurations/FilterEasyCachingRedisOptions.cs
class FilterEasyCachingRedisOptions (line 6) | public class FilterEasyCachingRedisOptions : FilterMemoryOptions
FILE: src/BloomFilter.EasyCaching/Configurations/ServiceCollectionExtensions.cs
class ServiceCollectionExtensions (line 8) | public static class ServiceCollectionExtensions
method UseEasyCachingRedis (line 16) | public static BloomFilterOptions UseEasyCachingRedis(this BloomFilterO...
method UseEasyCachingRedis (line 33) | public static BloomFilterOptions UseEasyCachingRedis(this BloomFilterO...
FILE: src/BloomFilter.EasyCaching/FilterEasyCachingBuilder.cs
class FilterEasyCachingBuilder (line 22) | public class FilterEasyCachingBuilder : FilterBuilder
method WithRedisKey (line 35) | public FilterEasyCachingBuilder WithRedisKey(string redisKey)
method WithRedisCachingProvider (line 49) | public FilterEasyCachingBuilder WithRedisCachingProvider(IRedisCaching...
method BuildEasyCaching (line 66) | public IBloomFilter BuildEasyCaching()
method BuildEasyCachingWithCapacity (line 87) | public IBloomFilter BuildEasyCachingWithCapacity(long capacity, int ha...
FILE: src/BloomFilter.EasyCaching/FilterEasyCachingRedis.cs
class FilterEasyCachingRedis (line 12) | public class FilterEasyCachingRedis : FilterRedisBase
method FilterEasyCachingRedis (line 26) | public FilterEasyCachingRedis(string name, IRedisCachingProvider provi...
method FilterEasyCachingRedis (line 43) | public FilterEasyCachingRedis(string name, IRedisCachingProvider provi...
method SetBit (line 53) | protected override bool SetBit(long position)
method GetBit (line 60) | protected override bool GetBit(long position)
method SetBitAsync (line 67) | protected override async Task<bool> SetBitAsync(long position)
method GetBitAsync (line 74) | protected override async Task<bool> GetBitAsync(long position)
method SetBits (line 81) | protected override bool[] SetBits(long[] positions)
method GetBits (line 114) | protected override bool[] GetBits(long[] positions)
method SetBitsAsync (line 147) | protected override async Task<bool[]> SetBitsAsync(long[] positions)
method GetBitsAsync (line 187) | protected override async Task<bool[]> GetBitsAsync(long[] positions)
method ClearBits (line 227) | protected override void ClearBits()
method ClearBitsAsync (line 230) | protected override async Task ClearBitsAsync()
method Add (line 235) | public override bool Add(ReadOnlySpan<byte> element)
method AddAsync (line 241) | public override async ValueTask<bool> AddAsync(ReadOnlyMemory<byte> data)
method Contains (line 248) | public override bool Contains(ReadOnlySpan<byte> element)
method ContainsAsync (line 254) | public override async ValueTask<bool> ContainsAsync(ReadOnlyMemory<byt...
method Dispose (line 261) | public override void Dispose()
FILE: src/BloomFilter.FreeRedis/Configurations/FilterFreeRedisOptions.cs
class FilterFreeRedisOptions (line 8) | public class FilterFreeRedisOptions : FilterMemoryOptions
FILE: src/BloomFilter.FreeRedis/Configurations/FilterFreeRedisOptionsExtension.cs
class FilterFreeRedisOptionsExtension (line 10) | public class FilterFreeRedisOptionsExtension : IBloomFilterOptionsExtension
method FilterFreeRedisOptionsExtension (line 18) | public FilterFreeRedisOptionsExtension(FilterFreeRedisOptions options)
method AddServices (line 23) | public void AddServices(IServiceCollection services)
FILE: src/BloomFilter.FreeRedis/Configurations/ServiceCollectionExtensions.cs
class ServiceCollectionExtensions (line 8) | public static class ServiceCollectionExtensions
method UseFreeRedis (line 16) | public static BloomFilterOptions UseFreeRedis(this BloomFilterOptions ...
method UseFreeRedis (line 33) | public static BloomFilterOptions UseFreeRedis(this BloomFilterOptions ...
FILE: src/BloomFilter.FreeRedis/FilterFreeRedis.cs
class FilterFreeRedis (line 11) | public class FilterFreeRedis : FilterRedisBase
method FilterFreeRedis (line 25) | public FilterFreeRedis(string name, RedisClient client, string redisKe...
method FilterFreeRedis (line 42) | public FilterFreeRedis(string name, RedisClient client, string redisKe...
method SetBit (line 52) | protected override bool SetBit(long position)
method GetBit (line 55) | protected override bool GetBit(long position)
method SetBitAsync (line 58) | protected override async Task<bool> SetBitAsync(long position)
method GetBitAsync (line 61) | protected override async Task<bool> GetBitAsync(long position)
method SetBits (line 64) | protected override bool[] SetBits(long[] positions)
method GetBits (line 85) | protected override bool[] GetBits(long[] positions)
method SetBitsAsync (line 106) | protected override async Task<bool[]> SetBitsAsync(long[] positions)
method GetBitsAsync (line 127) | protected override async Task<bool[]> GetBitsAsync(long[] positions)
method ClearBits (line 148) | protected override void ClearBits()
method ClearBitsAsync (line 151) | protected override async Task ClearBitsAsync()
method Add (line 156) | public override bool Add(ReadOnlySpan<byte> data)
method AddAsync (line 162) | public override async ValueTask<bool> AddAsync(ReadOnlyMemory<byte> data)
method Contains (line 169) | public override bool Contains(ReadOnlySpan<byte> element)
method ContainsAsync (line 175) | public override async ValueTask<bool> ContainsAsync(ReadOnlyMemory<byt...
method Dispose (line 182) | public override void Dispose()
FILE: src/BloomFilter.FreeRedis/FilterFreeRedisBuilder.cs
class FilterFreeRedisBuilder (line 22) | public class FilterFreeRedisBuilder : FilterBuilder
method WithRedisKey (line 35) | public FilterFreeRedisBuilder WithRedisKey(string redisKey)
method WithRedisClient (line 49) | public FilterFreeRedisBuilder WithRedisClient(RedisClient client)
method BuildFreeRedis (line 66) | public IBloomFilter BuildFreeRedis()
method BuildFreeRedisWithCapacity (line 87) | public IBloomFilter BuildFreeRedisWithCapacity(long capacity, int hashes)
FILE: src/BloomFilter.Redis/Configurations/FilterRedisOptions.cs
class FilterRedisOptions (line 7) | public class FilterRedisOptions : FilterMemoryOptions
FILE: src/BloomFilter.Redis/Configurations/FilterRedisOptionsExtension.cs
class FilterRedisOptionsExtension (line 8) | public class FilterRedisOptionsExtension : IBloomFilterOptionsExtension
method FilterRedisOptionsExtension (line 16) | public FilterRedisOptionsExtension(FilterRedisOptions options)
method AddServices (line 21) | public void AddServices(IServiceCollection services)
FILE: src/BloomFilter.Redis/Configurations/ServiceCollectionExtensions.cs
class ServiceCollectionExtensions (line 8) | public static class ServiceCollectionExtensions
method UseRedis (line 16) | public static BloomFilterOptions UseRedis(this BloomFilterOptions opti...
method UseRedis (line 33) | public static BloomFilterOptions UseRedis(this BloomFilterOptions opti...
FILE: src/BloomFilter.Redis/FilterRedis.cs
class FilterRedis (line 10) | public class FilterRedis : FilterRedisBase
method FilterRedis (line 24) | public FilterRedis(string name, IRedisBitOperate redisBitOperate, stri...
method FilterRedis (line 41) | public FilterRedis(string name, IRedisBitOperate redisBitOperate, stri...
method SetBit (line 51) | protected override bool SetBit(long position)
method GetBit (line 54) | protected override bool GetBit(long position)
method SetBitAsync (line 57) | protected override async Task<bool> SetBitAsync(long position)
method GetBitAsync (line 60) | protected override async Task<bool> GetBitAsync(long position)
method SetBits (line 63) | protected override bool[] SetBits(long[] positions)
method GetBits (line 66) | protected override bool[] GetBits(long[] positions)
method SetBitsAsync (line 69) | protected override async Task<bool[]> SetBitsAsync(long[] positions)
method GetBitsAsync (line 72) | protected override async Task<bool[]> GetBitsAsync(long[] positions)
method ClearBits (line 75) | protected override void ClearBits()
method ClearBitsAsync (line 78) | protected override async Task ClearBitsAsync()
method Add (line 88) | public override bool Add(ReadOnlySpan<byte> data)
method AddAsync (line 95) | public override async ValueTask<bool> AddAsync(ReadOnlyMemory<byte> data)
method Contains (line 107) | public override bool Contains(ReadOnlySpan<byte> element)
method ContainsAsync (line 114) | public override async ValueTask<bool> ContainsAsync(ReadOnlyMemory<byt...
method Dispose (line 121) | public override void Dispose()
FILE: src/BloomFilter.Redis/FilterRedisBuilder.cs
class FilterRedisBuilder (line 27) | public class FilterRedisBuilder : FilterBuilder
method WithRedisKey (line 43) | public FilterRedisBuilder WithRedisKey(string redisKey)
method WithRedisConnection (line 57) | public FilterRedisBuilder WithRedisConnection(string connectionString)
method WithRedisConnection (line 74) | public FilterRedisBuilder WithRedisConnection(ConfigurationOptions opt...
method WithRedisConnection (line 95) | public FilterRedisBuilder WithRedisConnection(IConnectionMultiplexer c...
method WithRedisBitOperate (line 116) | public FilterRedisBuilder WithRedisBitOperate(IRedisBitOperate redisBi...
method BuildRedis (line 136) | public IBloomFilter BuildRedis()
method BuildRedisWithCapacity (line 177) | public IBloomFilter BuildRedisWithCapacity(long capacity, int hashes)
method Build (line 222) | public static IBloomFilter Build(string configuration, string redisKey...
method Build (line 236) | public static IBloomFilter Build(string configuration, string redisKey...
method Build (line 250) | public static IBloomFilter Build(string configuration, string redisKey...
method Build (line 264) | public static IBloomFilter Build(string configuration, string redisKey...
method Build (line 279) | public static IBloomFilter Build(string configuration, string redisKey...
method Build (line 294) | public static IBloomFilter Build(string configuration, string redisKey...
method Build (line 307) | public static IBloomFilter Build(ConfigurationOptions configuration, s...
method Build (line 321) | public static IBloomFilter Build(ConfigurationOptions configuration, s...
method Build (line 335) | public static IBloomFilter Build(ConfigurationOptions configuration, s...
method Build (line 349) | public static IBloomFilter Build(ConfigurationOptions configuration, s...
method Build (line 364) | public static IBloomFilter Build(ConfigurationOptions configuration, s...
method Build (line 379) | public static IBloomFilter Build(ConfigurationOptions configuration, s...
method Build (line 393) | public static IBloomFilter Build(IConnectionMultiplexer connection, st...
method Build (line 407) | public static IBloomFilter Build(IConnectionMultiplexer connectionn, s...
method Build (line 421) | public static IBloomFilter Build(IConnectionMultiplexer connection, st...
method Build (line 434) | public static IBloomFilter Build(IConnectionMultiplexer connection, st...
method Build (line 449) | public static IBloomFilter Build(IConnectionMultiplexer connection, st...
method Build (line 464) | public static IBloomFilter Build(IConnectionMultiplexer connection, st...
method Build (line 478) | public static IBloomFilter Build(IRedisBitOperate redisBitOperate, str...
method Build (line 492) | public static IBloomFilter Build(IRedisBitOperate redisBitOperate, str...
method Build (line 506) | public static IBloomFilter Build(IRedisBitOperate redisBitOperate, str...
method Build (line 519) | public static IBloomFilter Build(IRedisBitOperate redisBitOperate, str...
method Build (line 534) | public static IBloomFilter Build(IRedisBitOperate redisBitOperate, str...
method Build (line 549) | public static IBloomFilter Build(IRedisBitOperate redisBitOperate, str...
FILE: src/BloomFilter.Redis/IRedisBitOperate.cs
type IRedisBitOperate (line 9) | public interface IRedisBitOperate : IDisposable
method Set (line 11) | bool[] Set(string redisKey, long[] positions, bool value);
method SetAsync (line 13) | Task<bool[]> SetAsync(string redisKey, long[] positions, bool value);
method Set (line 15) | bool Set(string redisKey, long position, bool value);
method SetAsync (line 17) | Task<bool> SetAsync(string redisKey, long position, bool value);
method Get (line 19) | bool Get(string redisKey, long position);
method GetAsync (line 21) | Task<bool> GetAsync(string redisKey, long position);
method Get (line 23) | bool[] Get(string redisKey, long[] positions);
method GetAsync (line 25) | Task<bool[]> GetAsync(string redisKey, long[] positions);
method Clear (line 27) | void Clear(string redisKey);
method ClearAsync (line 29) | Task ClearAsync(string redisKey);
FILE: src/BloomFilter.Redis/RedisBitOperate.cs
class RedisBitOperate (line 13) | public class RedisBitOperate : IRedisBitOperate
method RedisBitOperate (line 27) | public RedisBitOperate(string configuration)
method RedisBitOperate (line 36) | public RedisBitOperate(ConfigurationOptions configurationOptions)
method RedisBitOperate (line 45) | public RedisBitOperate(IConnectionMultiplexer connection)
method Clear (line 50) | public void Clear(string redisKey)
method ClearAsync (line 55) | public async Task ClearAsync(string redisKey)
method Get (line 61) | public bool Get(string redisKey, long position)
method Get (line 66) | public bool[] Get(string redisKey, long[] positions)
method GetAsync (line 84) | public async Task<bool> GetAsync(string redisKey, long position)
method GetAsync (line 90) | public async Task<bool[]> GetAsync(string redisKey, long[] positions)
method Set (line 115) | public bool[] Set(string redisKey, long[] positions, bool value)
method SetAsync (line 132) | public async Task<bool[]> SetAsync(string redisKey, long[] positions, ...
method Set (line 157) | public bool Set(string redisKey, long position, bool value)
method SetAsync (line 162) | public async Task<bool> SetAsync(string redisKey, long position, bool ...
method Dispose (line 168) | public void Dispose()
method Database (line 176) | private IDatabase Database(int? db = null)
method DatabaseAsync (line 181) | private async Task<IDatabase> DatabaseAsync(int? db = null)
method GetConnection (line 187) | private IConnectionMultiplexer GetConnection()
method GetConnectionAsync (line 226) | private async Task<IConnectionMultiplexer> GetConnectionAsync()
FILE: src/BloomFilter/Annotations.cs
class AllowNullAttribute (line 7) | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | At...
class DisallowNullAttribute (line 11) | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | At...
class MaybeNullAttribute (line 15) | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | At...
class NotNullAttribute (line 19) | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | At...
class MaybeNullWhenAttribute (line 23) | [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
method MaybeNullWhenAttribute (line 30) | public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = retur...
class NotNullWhenAttribute (line 37) | [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
method NotNullWhenAttribute (line 44) | public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnV...
class NotNullIfNotNullAttribute (line 51) | [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property |...
method NotNullIfNotNullAttribute (line 58) | public NotNullIfNotNullAttribute(string parameterName) => ParameterNam...
class DoesNotReturnAttribute (line 65) | [AttributeUsage(AttributeTargets.Method, Inherited = false)]
class DoesNotReturnIfAttribute (line 69) | [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
method DoesNotReturnIfAttribute (line 77) | public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue...
class MemberNotNullAttribute (line 85) | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inh...
method MemberNotNullAttribute (line 92) | public MemberNotNullAttribute(string member) => Members = new[] { memb...
method MemberNotNullAttribute (line 98) | public MemberNotNullAttribute(params string[] members) => Members = me...
method MemberNotNullAttribute (line 154) | public MemberNotNullAttribute(string member) => Members = new[] { memb...
method MemberNotNullAttribute (line 160) | public MemberNotNullAttribute(params string[] members) => Members = me...
class MemberNotNullWhenAttribute (line 105) | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inh...
method MemberNotNullWhenAttribute (line 115) | public MemberNotNullWhenAttribute(bool returnValue, string member)
method MemberNotNullWhenAttribute (line 128) | public MemberNotNullWhenAttribute(bool returnValue, params string[] me...
method MemberNotNullWhenAttribute (line 177) | public MemberNotNullWhenAttribute(bool returnValue, string member)
method MemberNotNullWhenAttribute (line 190) | public MemberNotNullWhenAttribute(bool returnValue, params string[] me...
class MemberNotNullAttribute (line 147) | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inh...
method MemberNotNullAttribute (line 92) | public MemberNotNullAttribute(string member) => Members = new[] { memb...
method MemberNotNullAttribute (line 98) | public MemberNotNullAttribute(params string[] members) => Members = me...
method MemberNotNullAttribute (line 154) | public MemberNotNullAttribute(string member) => Members = new[] { memb...
method MemberNotNullAttribute (line 160) | public MemberNotNullAttribute(params string[] members) => Members = me...
class MemberNotNullWhenAttribute (line 167) | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inh...
method MemberNotNullWhenAttribute (line 115) | public MemberNotNullWhenAttribute(bool returnValue, string member)
method MemberNotNullWhenAttribute (line 128) | public MemberNotNullWhenAttribute(bool returnValue, params string[] me...
method MemberNotNullWhenAttribute (line 177) | public MemberNotNullWhenAttribute(bool returnValue, string member)
method MemberNotNullWhenAttribute (line 190) | public MemberNotNullWhenAttribute(bool returnValue, params string[] me...
FILE: src/BloomFilter/AsyncLock.cs
type AsyncLock (line 11) | internal readonly struct AsyncLock : IDisposable
method AsyncLock (line 19) | public AsyncLock() : this(1)
method AsyncLock (line 23) | public AsyncLock(int maxCount = 1)
method Acquire (line 31) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method AcquireAsync (line 38) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Dispose (line 45) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Return (line 48) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method WaitForAcquireAsync (line 56) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
type Releaser (line 63) | public readonly struct Releaser(SemaphoreSlim? semaphore) : IDisposable
method Dispose (line 65) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method GetRemainingCount (line 70) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method GetCurrentCount (line 76) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
FILE: src/BloomFilter/BinaryHelper.cs
class BinaryHelper (line 12) | internal class BinaryHelper
method BitToIntOne (line 14) | public static int BitToIntOne(BitArray bit, int from, int to)
method Rejection (line 36) | public static long Rejection(long random, long m)
method NumberOfTrailingZeros (line 45) | public static uint NumberOfTrailingZeros(uint i)
method NumberOfLeadingZeros (line 58) | public static uint NumberOfLeadingZeros(uint i)
method RotateLeft (line 72) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method RotateLeft (line 82) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method RotateRight (line 92) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method RotateRight (line 102) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method RotateLeft (line 112) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method RotateLeft (line 122) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method RotateRight (line 132) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method RotateRight (line 142) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method RightMove (line 152) | public static int RightMove(int value, int pos)
method RightMove (line 165) | public static long RightMove(long value, int pos)
method RightMove (line 178) | public static uint RightMove(uint value, int pos)
FILE: src/BloomFilter/BloomFilterConstValue.cs
class BloomFilterConstValue (line 3) | public class BloomFilterConstValue
FILE: src/BloomFilter/BloomFilterExtensions.cs
class BloomFilterExtensions (line 12) | public static class BloomFilterExtensions
method Add (line 16) | public static bool Add(this IBloomFilter bloomFilter, byte data) => bl...
method AddAsync (line 18) | public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ...
method Contains (line 20) | public static bool Contains(this IBloomFilter bloomFilter, byte data) ...
method ContainsAsync (line 22) | public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFil...
method Add (line 24) | public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerab...
method AddAsync (line 26) | public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomF...
method Contains (line 28) | public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnu...
method ContainsAsync (line 30) | public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter b...
method All (line 32) | public static bool All(this IBloomFilter bloomFilter, IEnumerable<byte...
method AllAsync (line 34) | public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, ...
method Add (line 40) | public static bool Add(this IBloomFilter bloomFilter, string data) => ...
method AddAsync (line 42) | public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ...
method Contains (line 44) | public static bool Contains(this IBloomFilter bloomFilter, string data...
method ContainsAsync (line 46) | public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFil...
method Add (line 48) | public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerab...
method AddAsync (line 50) | public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomF...
method Contains (line 52) | public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnu...
method ContainsAsync (line 54) | public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter b...
method All (line 56) | public static bool All(this IBloomFilter bloomFilter, IEnumerable<stri...
method AllAsync (line 58) | public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, ...
method Add (line 64) | public static bool Add(this IBloomFilter bloomFilter, ReadOnlySpan<cha...
method AddAsync (line 66) | public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ...
method Contains (line 68) | public static bool Contains(this IBloomFilter bloomFilter, ReadOnlySpa...
method ContainsAsync (line 70) | public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFil...
method Add (line 76) | public static bool Add(this IBloomFilter bloomFilter, double data) => ...
method AddAsync (line 78) | public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ...
method Contains (line 80) | public static bool Contains(this IBloomFilter bloomFilter, double data...
method ContainsAsync (line 82) | public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFil...
method Add (line 84) | public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerab...
method AddAsync (line 86) | public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomF...
method Contains (line 88) | public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnu...
method ContainsAsync (line 90) | public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter b...
method All (line 92) | public static bool All(this IBloomFilter bloomFilter, IEnumerable<doub...
method AllAsync (line 94) | public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, ...
method Add (line 100) | public static bool Add(this IBloomFilter bloomFilter, float data) => b...
method AddAsync (line 102) | public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ...
method Contains (line 104) | public static bool Contains(this IBloomFilter bloomFilter, float data)...
method ContainsAsync (line 106) | public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFil...
method Add (line 108) | public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerab...
method AddAsync (line 110) | public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomF...
method Contains (line 112) | public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnu...
method ContainsAsync (line 114) | public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter b...
method All (line 116) | public static bool All(this IBloomFilter bloomFilter, IEnumerable<floa...
method AllAsync (line 118) | public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, ...
method Add (line 124) | public static bool Add(this IBloomFilter bloomFilter, short data) => b...
method AddAsync (line 126) | public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ...
method Contains (line 128) | public static bool Contains(this IBloomFilter bloomFilter, short data)...
method ContainsAsync (line 130) | public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFil...
method Add (line 132) | public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerab...
method AddAsync (line 134) | public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomF...
method Contains (line 136) | public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnu...
method ContainsAsync (line 138) | public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter b...
method All (line 140) | public static bool All(this IBloomFilter bloomFilter, IEnumerable<shor...
method AllAsync (line 142) | public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, ...
method Add (line 148) | public static bool Add(this IBloomFilter bloomFilter, int data) => blo...
method AddAsync (line 150) | public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ...
method Contains (line 152) | public static bool Contains(this IBloomFilter bloomFilter, int data) =...
method ContainsAsync (line 154) | public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFil...
method Add (line 156) | public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerab...
method AddAsync (line 158) | public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomF...
method Contains (line 160) | public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnu...
method ContainsAsync (line 162) | public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter b...
method All (line 164) | public static bool All(this IBloomFilter bloomFilter, IEnumerable<int>...
method AllAsync (line 166) | public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, ...
method Add (line 172) | public static bool Add(this IBloomFilter bloomFilter, long data) => bl...
method AddAsync (line 174) | public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ...
method Contains (line 176) | public static bool Contains(this IBloomFilter bloomFilter, long data) ...
method ContainsAsync (line 178) | public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFil...
method Add (line 180) | public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerab...
method AddAsync (line 182) | public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomF...
method Contains (line 184) | public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnu...
method ContainsAsync (line 186) | public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter b...
method All (line 188) | public static bool All(this IBloomFilter bloomFilter, IEnumerable<long...
method AllAsync (line 190) | public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, ...
method Add (line 196) | public static bool Add(this IBloomFilter bloomFilter, ushort data) => ...
method AddAsync (line 198) | public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ...
method Contains (line 200) | public static bool Contains(this IBloomFilter bloomFilter, ushort data...
method ContainsAsync (line 202) | public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFil...
method Add (line 204) | public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerab...
method AddAsync (line 206) | public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomF...
method Contains (line 208) | public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnu...
method ContainsAsync (line 210) | public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter b...
method All (line 212) | public static bool All(this IBloomFilter bloomFilter, IEnumerable<usho...
method AllAsync (line 214) | public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, ...
method Add (line 220) | public static bool Add(this IBloomFilter bloomFilter, uint data) => bl...
method AddAsync (line 222) | public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ...
method Contains (line 224) | public static bool Contains(this IBloomFilter bloomFilter, uint data) ...
method ContainsAsync (line 226) | public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFil...
method Add (line 228) | public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerab...
method AddAsync (line 230) | public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomF...
method Contains (line 232) | public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnu...
method ContainsAsync (line 234) | public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter b...
method All (line 236) | public static bool All(this IBloomFilter bloomFilter, IEnumerable<uint...
method AllAsync (line 238) | public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, ...
method Add (line 244) | public static bool Add(this IBloomFilter bloomFilter, ulong data) => b...
method AddAsync (line 246) | public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ...
method Contains (line 248) | public static bool Contains(this IBloomFilter bloomFilter, ulong data)...
method ContainsAsync (line 250) | public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFil...
method Add (line 252) | public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerab...
method AddAsync (line 254) | public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomF...
method Contains (line 256) | public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnu...
method ContainsAsync (line 258) | public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter b...
method All (line 260) | public static bool All(this IBloomFilter bloomFilter, IEnumerable<ulon...
method AllAsync (line 262) | public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, ...
method Add (line 268) | public static bool Add(this IBloomFilter bloomFilter, DateTime data) =...
method AddAsync (line 270) | public static ValueTask<bool> AddAsync(this IBloomFilter bloomFilter, ...
method Contains (line 272) | public static bool Contains(this IBloomFilter bloomFilter, DateTime da...
method ContainsAsync (line 274) | public static ValueTask<bool> ContainsAsync(this IBloomFilter bloomFil...
method Add (line 276) | public static IList<bool> Add(this IBloomFilter bloomFilter, IEnumerab...
method AddAsync (line 278) | public static ValueTask<IList<bool>> AddAsync(this IBloomFilter bloomF...
method Contains (line 280) | public static IList<bool> Contains(this IBloomFilter bloomFilter, IEnu...
method ContainsAsync (line 282) | public static ValueTask<IList<bool>> ContainsAsync(this IBloomFilter b...
method All (line 284) | public static bool All(this IBloomFilter bloomFilter, IEnumerable<Date...
method AllAsync (line 286) | public static ValueTask<bool> AllAsync(this IBloomFilter bloomFilter, ...
FILE: src/BloomFilter/Configurations/BloomFilterOptions.cs
class BloomFilterOptions (line 9) | public class BloomFilterOptions
method RegisterExtension (line 21) | public void RegisterExtension(IBloomFilterOptionsExtension extension)
FILE: src/BloomFilter/Configurations/FilterMemoryOptions.cs
class FilterMemoryOptions (line 6) | public class FilterMemoryOptions
FILE: src/BloomFilter/Configurations/FilterMemoryOptionsExtension.cs
class FilterMemoryOptionsExtension (line 7) | public class FilterMemoryOptionsExtension : IBloomFilterOptionsExtension
method FilterMemoryOptionsExtension (line 17) | public FilterMemoryOptionsExtension(FilterMemoryOptions options, Type?...
method AddServices (line 23) | public void AddServices(IServiceCollection services)
FILE: src/BloomFilter/Configurations/IBloomFilterOptionsExtension.cs
type IBloomFilterOptionsExtension (line 8) | public interface IBloomFilterOptionsExtension
method AddServices (line 14) | void AddServices(IServiceCollection services);
FILE: src/BloomFilter/DefaultBloomFilterFactory.cs
class DefaultBloomFilterFactory (line 8) | public class DefaultBloomFilterFactory : IBloomFilterFactory
method DefaultBloomFilterFactory (line 12) | public DefaultBloomFilterFactory(IEnumerable<IBloomFilter> bloomFilters)
method Get (line 17) | public IBloomFilter Get(string name)
method TryGet (line 32) | public bool TryGet(string name,
FILE: src/BloomFilter/DefaultFilterMemorySerializer.cs
class DefaultFilterMemorySerializer (line 9) | public class DefaultFilterMemorySerializer : IFilterMemorySerializer
method SerializeAsync (line 11) | public async ValueTask SerializeAsync(FilterMemorySerializerParam para...
method DeserializeAsync (line 31) | public async ValueTask<FilterMemorySerializerParam> DeserializeAsync(S...
method ReadExactlyAsync (line 82) | private async Task ReadExactlyAsync(Stream stream, byte[] data)
method Mod (line 91) | private int Mod(int len) => len % 8 > 0 ? 1 : 0;
FILE: src/BloomFilter/Filter.cs
class Filter (line 11) | public abstract class Filter : IBloomFilter
method Filter (line 59) | public Filter(string name, long expectedElements, double errorRate, Ha...
method Filter (line 95) | public Filter(string name, long capacity, int hashes, HashFunction has...
method SetFilterParam (line 118) | protected void SetFilterParam(long expectedElements, double errorRate,...
method Add (line 138) | public abstract bool Add(ReadOnlySpan<byte> data);
method AddAsync (line 145) | public abstract ValueTask<bool> AddAsync(ReadOnlyMemory<byte> data);
method Add (line 152) | public abstract IList<bool> Add(IEnumerable<byte[]> elements);
method AddAsync (line 159) | public abstract ValueTask<IList<bool>> AddAsync(IEnumerable<byte[]> el...
method Clear (line 164) | public abstract void Clear();
method ClearAsync (line 169) | public abstract ValueTask ClearAsync();
method Contains (line 176) | public abstract bool Contains(ReadOnlySpan<byte> element);
method ContainsAsync (line 183) | public abstract ValueTask<bool> ContainsAsync(ReadOnlyMemory<byte> ele...
method Contains (line 190) | public abstract IList<bool> Contains(IEnumerable<byte[]> elements);
method ContainsAsync (line 197) | public abstract ValueTask<IList<bool>> ContainsAsync(IEnumerable<byte[...
method All (line 204) | public abstract bool All(IEnumerable<byte[]> elements);
method AllAsync (line 211) | public abstract ValueTask<bool> AllAsync(IEnumerable<byte[]> elements);
method ComputeHash (line 218) | public long[] ComputeHash(ReadOnlySpan<byte> data)
method BestM (line 230) | public static long BestM(long n, double p)
method BestK (line 242) | public static int BestK(long n, long m)
method BestN (line 253) | public static long BestN(int k, long m)
method BestP (line 265) | public static double BestP(int k, long m, double insertedElements)
method ToString (line 270) | public override string ToString()
method LogMaxInt (line 275) | protected static int LogMaxInt(long number, out int mod)
method Dispose (line 284) | public abstract void Dispose();
FILE: src/BloomFilter/FilterBuilder.cs
class FilterBuilder (line 25) | public partial class FilterBuilder
method FilterBuilder (line 39) | protected FilterBuilder() { }
method Create (line 45) | public static FilterBuilder Create() => new();
method WithName (line 53) | public FilterBuilder WithName(string name)
method ExpectingElements (line 71) | public FilterBuilder ExpectingElements(long count)
method WithErrorRate (line 85) | public FilterBuilder WithErrorRate(double rate)
method UsingHashMethod (line 98) | public FilterBuilder UsingHashMethod(HashMethod method)
method UsingCustomHash (line 111) | public FilterBuilder UsingCustomHash(HashFunction hashFunction)
method WithSerializer (line 129) | public FilterBuilder WithSerializer(IFilterMemorySerializer serializer)
method BuildInMemory (line 145) | public IBloomFilter BuildInMemory()
method BuildInMemoryWithCapacity (line 159) | public IBloomFilter BuildInMemoryWithCapacity(long capacity, int hashes)
method Build (line 176) | public static IBloomFilter Build(FilterMemoryOptions options)
method Build (line 187) | public static IBloomFilter Build(FilterMemoryOptions options, IFilterM...
method Build (line 198) | public static IBloomFilter Build(long expectedElements, string name = ...
method Build (line 210) | public static IBloomFilter Build(long expectedElements, HashMethod has...
method Build (line 222) | public static IBloomFilter Build(long expectedElements, HashFunction h...
method Build (line 234) | public static IBloomFilter Build(long expectedElements, double errorRa...
method Build (line 248) | public static IBloomFilter Build(long expectedElements, double errorRa...
method Build (line 262) | public static IBloomFilter Build(long expectedElements, double errorRa...
FILE: src/BloomFilter/FilterMemory.cs
class FilterMemory (line 15) | public class FilterMemory : Filter
method FilterMemory (line 30) | public FilterMemory(FilterMemoryOptions options, IFilterMemorySerializ...
method FilterMemory (line 57) | public FilterMemory(string name, long expectedElements, double errorRa...
method FilterMemory (line 73) | public FilterMemory(string name, long size, int hashes, HashFunction h...
method Init (line 80) | [MemberNotNull(nameof(_buckets))]
method SerializeAsync (line 111) | public async ValueTask SerializeAsync(Stream stream)
method DeserializeAsync (line 130) | public async ValueTask DeserializeAsync(Stream stream)
method Import (line 165) | [MemberNotNull(nameof(_buckets))]
method Import (line 197) | [MemberNotNull(nameof(_buckets))]
method Export (line 216) | public BitArray[] Export()
method ExportToBytes (line 225) | public IList<byte[]> ExportToBytes()
method Add (line 248) | public override bool Add(ReadOnlySpan<byte> data)
method AddAsync (line 272) | public override ValueTask<bool> AddAsync(ReadOnlyMemory<byte> data)
method Add (line 277) | public override IList<bool> Add(IEnumerable<byte[]> elements)
method AddAsync (line 325) | public override ValueTask<IList<bool>> AddAsync(IEnumerable<byte[]> el...
method Contains (line 335) | public override bool Contains(ReadOnlySpan<byte> element)
method ContainsAsync (line 349) | public override ValueTask<bool> ContainsAsync(ReadOnlyMemory<byte> ele...
method Contains (line 354) | public override IList<bool> Contains(IEnumerable<byte[]> elements)
method ContainsAsync (line 395) | public override ValueTask<IList<bool>> ContainsAsync(IEnumerable<byte[...
method All (line 400) | public override bool All(IEnumerable<byte[]> elements)
method AllAsync (line 405) | public override ValueTask<bool> AllAsync(IEnumerable<byte[]> elements)
method Clear (line 413) | public override void Clear()
method ClearAsync (line 423) | public override ValueTask ClearAsync()
method Set (line 429) | private void Set(long index)
method Get (line 436) | public bool Get(long index)
method Dispose (line 442) | public override void Dispose()
FILE: src/BloomFilter/FilterMemorySerializerParam.cs
class FilterMemorySerializerParam (line 8) | public class FilterMemorySerializerParam
FILE: src/BloomFilter/FilterRedisBase.cs
class FilterRedisBase (line 12) | public abstract class FilterRedisBase : Filter
method FilterRedisBase (line 14) | protected FilterRedisBase(string name, long expectedElements, double e...
method FilterRedisBase (line 19) | protected FilterRedisBase(string name, long capacity, int hashes, Hash...
method SetBit (line 31) | protected abstract bool SetBit(long position);
method GetBit (line 38) | protected abstract bool GetBit(long position);
method SetBitAsync (line 45) | protected abstract Task<bool> SetBitAsync(long position);
method GetBitAsync (line 52) | protected abstract Task<bool> GetBitAsync(long position);
method SetBits (line 59) | protected abstract bool[] SetBits(long[] positions);
method GetBits (line 66) | protected abstract bool[] GetBits(long[] positions);
method SetBitsAsync (line 73) | protected abstract Task<bool[]> SetBitsAsync(long[] positions);
method GetBitsAsync (line 80) | protected abstract Task<bool[]> GetBitsAsync(long[] positions);
method ClearBits (line 85) | protected abstract void ClearBits();
method ClearBitsAsync (line 90) | protected abstract Task ClearBitsAsync();
method Add (line 94) | public override IList<bool> Add(IEnumerable<byte[]> elements)
method AddAsync (line 109) | public override async ValueTask<IList<bool>> AddAsync(IEnumerable<byte...
method Contains (line 124) | public override IList<bool> Contains(IEnumerable<byte[]> elements)
method ContainsAsync (line 139) | public override async ValueTask<IList<bool>> ContainsAsync(IEnumerable...
method All (line 154) | public override bool All(IEnumerable<byte[]> elements)
method AllAsync (line 157) | public override ValueTask<bool> AllAsync(IEnumerable<byte[]> elements)
method Clear (line 160) | public override void Clear()
method ClearAsync (line 163) | public override async ValueTask ClearAsync()
method ProcessBatchResults (line 173) | protected static IList<bool> ProcessBatchResults(bool[] processResults...
FILE: src/BloomFilter/HashAlgorithms/Adler32.cs
class Adler32 (line 5) | public class Adler32 : HashFunction
method ComputeHash (line 11) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
FILE: src/BloomFilter/HashAlgorithms/Crc32.cs
class Crc32 (line 5) | public partial class Crc32 : HashFunction
method ComputeHash (line 11) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
FILE: src/BloomFilter/HashAlgorithms/Crc64.cs
class Crc64 (line 5) | public partial class Crc64 : HashFunction
method ComputeHash (line 9) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
FILE: src/BloomFilter/HashAlgorithms/HashCrypto.cs
class HashCryptoSHA1 (line 7) | public class HashCryptoSHA1 : HashCrypto
method ComputeHash (line 11) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
class HashCryptoSHA256 (line 18) | public class HashCryptoSHA256 : HashCrypto
method ComputeHash (line 22) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
class HashCryptoSHA384 (line 29) | public class HashCryptoSHA384 : HashCrypto
method ComputeHash (line 33) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
class HashCryptoSHA512 (line 40) | public class HashCryptoSHA512 : HashCrypto
method ComputeHash (line 44) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
class HashCrypto (line 51) | public abstract class HashCrypto : HashFunction
method ComputeHash (line 53) | protected long[] ComputeHash(HashAlgorithm hashAlgorithm, ReadOnlySpan...
FILE: src/BloomFilter/HashAlgorithms/Internal/Adler32.cs
class Adler32 (line 15) | internal sealed partial class Adler32 : NonCryptoHashAlgorithm
method Adler32 (line 31) | public Adler32(uint adler = 1)
method Append (line 43) | public override void Append(ReadOnlySpan<byte> source)
method Reset (line 51) | public override void Reset()
method GetCurrentHashCore (line 61) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetHashAndResetCore (line 70) | protected override void GetHashAndResetCore(Span<byte> destination)
method GetCurrentHashAsUInt32 (line 78) | public uint GetCurrentHashAsUInt32() => _adler;
method Update (line 80) | private static uint Update(uint adler, ReadOnlySpan<byte> source)
method GetSimple (line 92) | internal static uint GetSimple(ReadOnlySpan<byte> source, uint adler)
method GetSse (line 124) | internal static unsafe uint GetSse(ReadOnlySpan<byte> buffer, uint adler)
FILE: src/BloomFilter/HashAlgorithms/Internal/Crc32.Arm.cs
class Crc32 (line 14) | internal partial class Crc32
method UpdateScalarArm64 (line 16) | private static uint UpdateScalarArm64(uint crc, ReadOnlySpan<byte> sou...
method UpdateScalarArm32 (line 44) | private static uint UpdateScalarArm32(uint crc, ReadOnlySpan<byte> sou...
FILE: src/BloomFilter/HashAlgorithms/Internal/Crc32.Table.cs
class Crc32 (line 8) | internal partial class Crc32 : NonCryptoHashAlgorithm
FILE: src/BloomFilter/HashAlgorithms/Internal/Crc32.Vectorized.cs
class Crc32 (line 16) | internal partial class Crc32
method CanBeVectorized (line 22) | private static bool CanBeVectorized(ReadOnlySpan<byte> source) =>
method UpdateVectorized (line 36) | private static uint UpdateVectorized(uint crc, ReadOnlySpan<byte> source)
FILE: src/BloomFilter/HashAlgorithms/Internal/Crc32.cs
class Crc32 (line 28) | internal partial class Crc32 : NonCryptoHashAlgorithm
method Crc32 (line 36) | public Crc32() : base(Size)
method Append (line 40) | public override void Append(ReadOnlySpan<byte> source)
method Reset (line 45) | public override void Reset()
method GetCurrentHashCore (line 50) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetHashAndResetCore (line 55) | protected override void GetHashAndResetCore(Span<byte> destination)
method GetCurrentHashAsUInt32 (line 61) | public uint GetCurrentHashAsUInt32() => ~_crc;
method Update (line 63) | private static uint Update(uint crc, ReadOnlySpan<byte> source)
method UpdateScalar (line 75) | private static uint UpdateScalar(uint crc, ReadOnlySpan<byte> source)
FILE: src/BloomFilter/HashAlgorithms/Internal/Crc64.Table.cs
class Crc64 (line 8) | internal sealed partial class Crc64 : NonCryptoHashAlgorithm
FILE: src/BloomFilter/HashAlgorithms/Internal/Crc64.Vectorized.cs
class Crc64 (line 12) | internal partial class Crc64
method LoadFromSource (line 14) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method CanBeVectorized (line 37) | private static bool CanBeVectorized(ReadOnlySpan<byte> source) => Vect...
method UpdateVectorized (line 46) | private static ulong UpdateVectorized(ulong crc, ReadOnlySpan<byte> so...
FILE: src/BloomFilter/HashAlgorithms/Internal/Crc64.cs
class Crc64 (line 28) | internal sealed partial class Crc64 : NonCryptoHashAlgorithm
method Crc64 (line 38) | public Crc64()
method Append (line 48) | public override void Append(ReadOnlySpan<byte> source)
method Reset (line 56) | public override void Reset()
method GetCurrentHashCore (line 66) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetHashAndResetCore (line 75) | protected override void GetHashAndResetCore(Span<byte> destination)
method GetCurrentHashAsUInt64 (line 83) | public ulong GetCurrentHashAsUInt64() => _crc;
method HashToUInt64 (line 85) | public static ulong HashToUInt64(ReadOnlySpan<byte> source) =>
method Update (line 88) | private static ulong Update(ulong crc, ReadOnlySpan<byte> source)
method UpdateScalar (line 100) | private static ulong UpdateScalar(ulong crc, ReadOnlySpan<byte> source)
FILE: src/BloomFilter/HashAlgorithms/Internal/FNV1.cs
class FNV1 (line 9) | internal partial class FNV1 : NonCryptoHashAlgorithm
method FNV1 (line 21) | public FNV1()
method Append (line 32) | public override void Append(ReadOnlySpan<byte> source)
method Reset (line 40) | public override void Reset()
method GetCurrentHashCore (line 50) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetHashAndResetCore (line 59) | protected override void GetHashAndResetCore(Span<byte> destination)
method GetCurrentHashAsUInt32 (line 67) | public uint GetCurrentHashAsUInt32() => _current;
method HashToUInt32 (line 72) | public static uint HashToUInt32(ReadOnlySpan<byte> source) =>
method Update (line 75) | private static uint Update(uint current, ReadOnlySpan<byte> source)
FILE: src/BloomFilter/HashAlgorithms/Internal/FNV1a.cs
class FNV1a (line 9) | internal class FNV1a : NonCryptoHashAlgorithm
method FNV1a (line 21) | public FNV1a()
method Append (line 32) | public override void Append(ReadOnlySpan<byte> source)
method Reset (line 40) | public override void Reset()
method GetCurrentHashCore (line 50) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetHashAndResetCore (line 59) | protected override void GetHashAndResetCore(Span<byte> destination)
method GetCurrentHashAsUInt32 (line 67) | public uint GetCurrentHashAsUInt32() => _current;
method HashToUInt32 (line 72) | public static uint HashToUInt32(ReadOnlySpan<byte> source) =>
method Update (line 75) | private static uint Update(uint current, ReadOnlySpan<byte> source)
FILE: src/BloomFilter/HashAlgorithms/Internal/ModifiedFNV1.cs
class ModifiedFNV1 (line 9) | internal class ModifiedFNV1 : NonCryptoHashAlgorithm
method ModifiedFNV1 (line 21) | public ModifiedFNV1()
method Append (line 32) | public override void Append(ReadOnlySpan<byte> source)
method Reset (line 40) | public override void Reset()
method GetCurrentHashCore (line 50) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetHashAndResetCore (line 60) | protected override void GetHashAndResetCore(Span<byte> destination)
method GetCurrentHashAsUInt32 (line 69) | public uint GetCurrentHashAsUInt32()
method HashToUInt32 (line 77) | public static uint HashToUInt32(ReadOnlySpan<byte> source) =>
method Update (line 80) | private static uint Update(uint current, ReadOnlySpan<byte> source)
method Finalization (line 91) | private static uint Finalization(uint current)
FILE: src/BloomFilter/HashAlgorithms/Internal/Murmur128BitsX64.State.cs
class Murmur128BitsX64 (line 7) | internal partial class Murmur128BitsX64
type State (line 9) | private struct State
method State (line 17) | internal State(uint seed)
method ProcessBlock (line 22) | internal unsafe void ProcessBlock(ReadOnlySpan<byte> source)
method Tail (line 40) | internal readonly ulong[] Tail(int length, ReadOnlySpan<byte> remain...
method Finalization (line 73) | private static ulong[] Finalization(int length, ulong hash1, ulong h...
method FMix (line 94) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
FILE: src/BloomFilter/HashAlgorithms/Internal/Murmur128BitsX64.cs
class Murmur128BitsX64 (line 10) | internal partial class Murmur128BitsX64 : NonCryptoHashAlgorithm
method Murmur128BitsX64 (line 20) | public Murmur128BitsX64() : base(HashSize)
method Murmur128BitsX64 (line 24) | public Murmur128BitsX64(uint seed)
method Reset (line 31) | public override void Reset()
method Append (line 37) | public override void Append(ReadOnlySpan<byte> source)
method GetCurrentHashCore (line 76) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetCurrentHashAsUInt128 (line 85) | public UInt128 GetCurrentHashAsUInt128()
method GetCurrentHashAsUInt128Array (line 94) | public ulong[] GetCurrentHashAsUInt128Array()
method HashToUInt128Array (line 107) | public static ulong[] HashToUInt128Array(ReadOnlySpan<byte> source, ui...
method Fill (line 122) | private static void Fill(Span<byte> destination, ref ulong[] hash)
FILE: src/BloomFilter/HashAlgorithms/Internal/Murmur128BitsX86.State.cs
class Murmur128BitsX86 (line 7) | internal partial class Murmur128BitsX86
type State (line 9) | private struct State
method State (line 21) | internal State(uint seed)
method ProcessBlock (line 26) | internal unsafe void ProcessBlock(ReadOnlySpan<byte> source)
method Tail (line 52) | internal readonly uint[] Tail(int length, ReadOnlySpan<byte> remaining)
method Finalization (line 92) | private static uint[] Finalization(int length, uint h1, uint h2, uin...
method FMix (line 112) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
FILE: src/BloomFilter/HashAlgorithms/Internal/Murmur128BitsX86.cs
class Murmur128BitsX86 (line 10) | internal partial class Murmur128BitsX86 : NonCryptoHashAlgorithm
method Murmur128BitsX86 (line 20) | public Murmur128BitsX86() : base(HashSize)
method Murmur128BitsX86 (line 24) | public Murmur128BitsX86(uint seed)
method Reset (line 31) | public override void Reset()
method Append (line 37) | public override void Append(ReadOnlySpan<byte> source)
method GetCurrentHashCore (line 76) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetCurrentHashAsUInt128Array (line 84) | public uint[] GetCurrentHashAsUInt128Array()
method HashToUInt128Array (line 97) | public static uint[] HashToUInt128Array(ReadOnlySpan<byte> source, uin...
method Fill (line 112) | private static void Fill(Span<byte> destination, ref uint[] hash)
FILE: src/BloomFilter/HashAlgorithms/Internal/Murmur32BitsX86.State.cs
class Murmur32BitsX86 (line 7) | internal partial class Murmur32BitsX86
type State (line 9) | private struct State
method State (line 26) | internal State(uint seed)
method ProcessBlock (line 31) | internal unsafe void ProcessBlock(ReadOnlySpan<byte> source)
method Tail (line 39) | internal readonly uint Tail(int length, ReadOnlySpan<byte> remaining)
method Finalization (line 75) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
FILE: src/BloomFilter/HashAlgorithms/Internal/Murmur32BitsX86.cs
class Murmur32BitsX86 (line 10) | internal partial class Murmur32BitsX86 : NonCryptoHashAlgorithm
method Murmur32BitsX86 (line 20) | public Murmur32BitsX86() : base(HashSize)
method Murmur32BitsX86 (line 24) | public Murmur32BitsX86(uint seed)
method Reset (line 31) | public override void Reset()
method Append (line 37) | public override void Append(ReadOnlySpan<byte> source)
method GetCurrentHashCore (line 76) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetCurrentHashAsUInt32 (line 84) | public uint GetCurrentHashAsUInt32()
method HashToUInt32 (line 97) | public static uint HashToUInt32(ReadOnlySpan<byte> source, uint seed = 0)
FILE: src/BloomFilter/HashAlgorithms/Internal/NonCryptoHashAlgorithm.cs
class NonCryptoHashAlgorithm (line 10) | internal abstract class NonCryptoHashAlgorithm
method NonCryptoHashAlgorithm (line 18) | protected NonCryptoHashAlgorithm(int hashLengthInBytes)
method Append (line 26) | public abstract void Append(ReadOnlySpan<byte> source);
method Reset (line 28) | public abstract void Reset();
method GetCurrentHashCore (line 30) | protected abstract void GetCurrentHashCore(Span<byte> destination);
method Append (line 32) | public void Append(byte[] source)
method GetHashAndResetCore (line 46) | protected virtual void GetHashAndResetCore(Span<byte> destination)
method ThrowDestinationTooShort (line 54) | #if NET6_0_OR_GREATER
FILE: src/BloomFilter/HashAlgorithms/Internal/ThrowHelper.cs
class ThrowHelper (line 6) | internal static partial class ThrowHelper
method ThrowUnreachableException (line 9) | [DoesNotReturn]
FILE: src/BloomFilter/HashAlgorithms/Internal/VectorHelper.cs
class VectorHelper (line 14) | internal static class VectorHelper
method FoldPolynomialPair (line 21) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method CarrylessMultiplyLower (line 30) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method CarrylessMultiplyUpper (line 47) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method CarrylessMultiplyLeftUpperRightLower (line 64) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method CarrylessMultiplyLeftLowerRightUpper (line 81) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method ShiftRightBytesInVector (line 98) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method ShiftLowerToUpper (line 116) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
FILE: src/BloomFilter/HashAlgorithms/Internal/XxHash128.cs
class XxHash128 (line 20) | internal sealed unsafe class XxHash128 : NonCryptoHashAlgorithm
method XxHash128 (line 28) | public XxHash128() : this(0)
method XxHash128 (line 33) | public XxHash128(ulong seed) : base(HashLengthInBytes)
method Hash (line 42) | public static byte[] Hash(ReadOnlySpan<byte> source, ulong seed = 0)
method Hash (line 55) | public static int Hash(ReadOnlySpan<byte> source, Span<byte> destinati...
method TryHash (line 71) | public static bool TryHash(ReadOnlySpan<byte> source, Span<byte> desti...
method HashToHash128 (line 85) | internal static Hash128 HashToHash128(ReadOnlySpan<byte> source, ulong...
method Reset (line 110) | public override void Reset()
method Append (line 117) | public override void Append(ReadOnlySpan<byte> source)
method GetCurrentHashCore (line 124) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetCurrentHashAsHash128 (line 130) | internal Hash128 GetCurrentHashAsHash128()
method WriteBigEndian128 (line 159) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method HashLength0To16 (line 175) | private static Hash128 HashLength0To16(byte* source, uint length, ulon...
method HashLength1To3 (line 197) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method HashLength4To8 (line 222) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method HashLength9To16 (line 248) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method HashLength17To128 (line 275) | private static Hash128 HashLength17To128(byte* source, uint length, ul...
method HashLength129To240 (line 301) | private static Hash128 HashLength129To240(byte* source, uint length, u...
method HashLengthOver240 (line 334) | private static Hash128 HashLengthOver240(byte* source, uint length, ul...
method AvalancheHash (line 359) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Mix32Bytes (line 371) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
type Hash128 (line 380) | [DebuggerDisplay("Low64: {" + nameof(Low64) + "}, High64: {" + nameof(...
method Hash128 (line 386) | public Hash128(ulong low64, ulong high64)
FILE: src/BloomFilter/HashAlgorithms/Internal/XxHash3.cs
class XxHash3 (line 20) | internal sealed unsafe class XxHash3 : NonCryptoHashAlgorithm
method XxHash3 (line 28) | public XxHash3() : this(0)
method XxHash3 (line 33) | public XxHash3(ulong seed) : base(HashLengthInBytes)
method HashToUInt64 (line 42) | public static ulong HashToUInt64(ReadOnlySpan<byte> source, ulong seed...
method Reset (line 67) | public override void Reset()
method Append (line 74) | public override void Append(ReadOnlySpan<byte> source)
method GetCurrentHashCore (line 81) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetCurrentHashAsUInt64 (line 89) | public ulong GetCurrentHashAsUInt64()
method HashLength0To16 (line 116) | private static ulong HashLength0To16(byte* source, uint length, ulong ...
method HashLength1To3 (line 137) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method HashLength4To8 (line 155) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method HashLength9To16 (line 172) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method HashLength17To128 (line 192) | private static ulong HashLength17To128(byte* source, uint length, ulon...
method HashLength129To240 (line 221) | private static ulong HashLength129To240(byte* source, uint length, ulo...
method HashLengthOver240 (line 270) | private static ulong HashLengthOver240(byte* source, uint length, ulon...
FILE: src/BloomFilter/HashAlgorithms/Internal/XxHash32.State.cs
class XxHash32 (line 15) | internal sealed partial class XxHash32
type State (line 17) | private struct State
method State (line 26) | internal State(uint seed)
method ProcessStripe (line 37) | internal unsafe void ProcessStripe(ReadOnlySpan<byte> source)
method Converge (line 51) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method ApplyRound (line 61) | private static uint ApplyRound(uint acc, ReadOnlySpan<byte> lane)
method Complete (line 70) | internal readonly uint Complete(int length, ReadOnlySpan<byte> remai...
FILE: src/BloomFilter/HashAlgorithms/Internal/XxHash32.cs
class XxHash32 (line 19) | internal sealed partial class XxHash32 : NonCryptoHashAlgorithm
method XxHash32 (line 36) | public XxHash32()
method XxHash32 (line 48) | public XxHash32(uint seed)
method Reset (line 58) | public override void Reset()
method Append (line 69) | public override void Append(ReadOnlySpan<byte> source)
method GetCurrentHashCore (line 116) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetCurrentHashAsUInt32 (line 124) | public uint GetCurrentHashAsUInt32()
method HashToUInt32 (line 141) | public static uint HashToUInt32(ReadOnlySpan<byte> source, uint seed = 0)
FILE: src/BloomFilter/HashAlgorithms/Internal/XxHash64.State.cs
class XxHash64 (line 15) | internal sealed partial class XxHash64
method Avalanche (line 17) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
type State (line 28) | private struct State
method State (line 37) | internal State(ulong seed)
method ProcessStripe (line 48) | internal void ProcessStripe(ReadOnlySpan<byte> source)
method MergeAccumulator (line 61) | private static ulong MergeAccumulator(ulong acc, ulong accN)
method Converge (line 70) | private readonly ulong Converge()
method ApplyRound (line 86) | private static ulong ApplyRound(ulong acc, ReadOnlySpan<byte> lane)
method ApplyRound (line 91) | private static ulong ApplyRound(ulong acc, ulong lane)
method Complete (line 100) | internal readonly ulong Complete(long length, ReadOnlySpan<byte> rem...
FILE: src/BloomFilter/HashAlgorithms/Internal/XxHash64.cs
class XxHash64 (line 19) | internal sealed partial class XxHash64 : NonCryptoHashAlgorithm
method XxHash64 (line 36) | public XxHash64()
method XxHash64 (line 48) | public XxHash64(ulong seed)
method Reset (line 58) | public override void Reset()
method Append (line 69) | public override void Append(ReadOnlySpan<byte> source)
method GetCurrentHashCore (line 116) | protected override void GetCurrentHashCore(Span<byte> destination)
method GetCurrentHashAsUInt64 (line 124) | public ulong GetCurrentHashAsUInt64()
method HashToUInt64 (line 141) | public static ulong HashToUInt64(ReadOnlySpan<byte> source, ulong seed...
FILE: src/BloomFilter/HashAlgorithms/Internal/XxHashShared.cs
class XxHashShared (line 18) | internal static unsafe class XxHashShared
method XxHashShared (line 109) | static XxHashShared()
method Initialize (line 157) | public static void Initialize(ref State state, ulong seed)
method Reset (line 176) | public static void Reset(ref State state)
method Rrmxmx (line 189) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method HashInternalLoop (line 199) | public static void HashInternalLoop(ulong* accumulators, byte* source,...
method ConsumeStripes (line 215) | public static void ConsumeStripes(ulong* accumulators, ref ulong strip...
method Append (line 237) | public static void Append(ref State state, ReadOnlySpan<byte> source)
method CopyAccumulators (line 329) | public static void CopyAccumulators(ref State state, ulong* accumulators)
method DigestLong (line 357) | public static void DigestLong(ref State state, ulong* accumulators, by...
method InitializeAccumulators (line 387) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method MergeAccumulators (line 417) | public static ulong MergeAccumulators(ulong* accumulators, byte* secre...
method Mix16Bytes (line 429) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Multiply32To64 (line 436) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Avalanche (line 440) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Multiply64To128 (line 449) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Multiply64To128ThenFold (line 468) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method DeriveSecretFromSeed (line 475) | public static void DeriveSecretFromSeed(byte* destinationSecret, ulong...
method Accumulate (line 509) | [MethodImpl(MethodImplOptions.NoInlining)]
method Accumulate512 (line 611) | [MethodImpl(MethodImplOptions.NoInlining)]
method Accumulate512Inlined (line 617) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Accumulate256 (line 660) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Accumulate128 (line 678) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method MultiplyWideningLower (line 693) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method ScrambleAccumulators (line 712) | private static void ScrambleAccumulators(ulong* accumulators, byte* se...
method ScrambleAccumulator256 (line 753) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method ScrambleAccumulator128 (line 762) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method XorShift (line 772) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method ReadUInt32LE (line 779) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method ReadUInt64LE (line 785) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method WriteUInt64LE (line 791) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
type State (line 801) | [StructLayout(LayoutKind.Auto)]
FILE: src/BloomFilter/HashAlgorithms/LCGWithFNV.cs
class LCGWithFNV1a (line 8) | public class LCGWithFNV1a : LCGWithFNV
method Hash (line 12) | public override long Hash(ReadOnlySpan<byte> data)
class LCGModifiedFNV1 (line 21) | public class LCGModifiedFNV1 : LCGWithFNV1a
method Hash (line 25) | public override long Hash(ReadOnlySpan<byte> data)
class LCGWithFNV (line 34) | public class LCGWithFNV : HashFunction
method ComputeHash (line 38) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
method Hash (line 65) | public virtual long Hash(ReadOnlySpan<byte> data)
FILE: src/BloomFilter/HashAlgorithms/Murmur128BitsX64.cs
class Murmur128BitsX64 (line 5) | public class Murmur128BitsX64 : HashFunction
method ComputeHash (line 9) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
FILE: src/BloomFilter/HashAlgorithms/Murmur128BitsX86.cs
class Murmur128BitsX86 (line 5) | public class Murmur128BitsX86 : HashFunction
method ComputeHash (line 9) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
FILE: src/BloomFilter/HashAlgorithms/Murmur32BitsX86.cs
class Murmur32BitsX86 (line 9) | public class Murmur32BitsX86 : HashFunction
method ComputeHash (line 13) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
FILE: src/BloomFilter/HashAlgorithms/RNGWithFNV.cs
class RNGWithFNV1a (line 8) | public class RNGWithFNV1a : RNGWithFNV1
method Hash (line 12) | public override long Hash(ReadOnlySpan<byte> data)
class RNGModifiedFNV1 (line 21) | public class RNGModifiedFNV1 : RNGWithFNV1a
method Hash (line 25) | public override long Hash(ReadOnlySpan<byte> data)
class RNGWithFNV1 (line 34) | public class RNGWithFNV1 : HashFunction
method ComputeHash (line 41) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
method Hash (line 58) | public virtual long Hash(ReadOnlySpan<byte> data)
FILE: src/BloomFilter/HashAlgorithms/XXHash128.cs
class XXHash128 (line 6) | public class XXHash128 : HashFunction
method ComputeHash (line 10) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
FILE: src/BloomFilter/HashAlgorithms/XXHash3.cs
class XXHash3 (line 5) | public class XXHash3 : HashFunction
method ComputeHash (line 9) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
FILE: src/BloomFilter/HashAlgorithms/XXHash32.cs
class XXHash32 (line 5) | public class XXHash32 : HashFunction
method ComputeHash (line 9) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
FILE: src/BloomFilter/HashAlgorithms/XXHash64.cs
class XXHash64 (line 5) | public class XXHash64 : HashFunction
method ComputeHash (line 9) | public override long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
FILE: src/BloomFilter/HashFunction.cs
class HashFunction (line 10) | public abstract class HashFunction
method ComputeHash (line 59) | public abstract long[] ComputeHash(ReadOnlySpan<byte> data, long m, in...
FILE: src/BloomFilter/HashMethod.cs
type HashMethod (line 6) | public enum HashMethod : int
FILE: src/BloomFilter/IBloomFilter.cs
type IBloomFilter (line 10) | public interface IBloomFilter : IDisposable
method Add (line 22) | bool Add(ReadOnlySpan<byte> data);
method AddAsync (line 29) | ValueTask<bool> AddAsync(ReadOnlyMemory<byte> data);
method Add (line 36) | IList<bool> Add(IEnumerable<byte[]> elements);
method AddAsync (line 43) | ValueTask<IList<bool>> AddAsync(IEnumerable<byte[]> elements);
method Contains (line 50) | bool Contains(ReadOnlySpan<byte> element);
method ContainsAsync (line 57) | ValueTask<bool> ContainsAsync(ReadOnlyMemory<byte> element);
method Contains (line 64) | IList<bool> Contains(IEnumerable<byte[]> elements);
method ContainsAsync (line 71) | ValueTask<IList<bool>> ContainsAsync(IEnumerable<byte[]> elements);
method All (line 78) | bool All(IEnumerable<byte[]> elements);
method AllAsync (line 85) | ValueTask<bool> AllAsync(IEnumerable<byte[]> elements);
method Clear (line 90) | void Clear();
method ClearAsync (line 95) | ValueTask ClearAsync();
method ComputeHash (line 102) | long[] ComputeHash(ReadOnlySpan<byte> data);
FILE: src/BloomFilter/IBloomFilterFactory.cs
type IBloomFilterFactory (line 8) | public interface IBloomFilterFactory
method Get (line 15) | IBloomFilter Get(string name);
method TryGet (line 23) | bool TryGet(string name,
FILE: src/BloomFilter/IFilterMemorySerializer.cs
type IFilterMemorySerializer (line 9) | public interface IFilterMemorySerializer
method SerializeAsync (line 17) | ValueTask SerializeAsync(FilterMemorySerializerParam param, Stream str...
method DeserializeAsync (line 24) | ValueTask<FilterMemorySerializerParam> DeserializeAsync(Stream stream);
FILE: src/BloomFilter/ServiceCollectionExtensions.cs
class ServiceCollectionExtensions (line 7) | public static class ServiceCollectionExtensions
method AddBloomFilter (line 14) | public static IServiceCollection AddBloomFilter(this IServiceCollectio...
method UseInMemory (line 40) | public static BloomFilterOptions UseInMemory(this BloomFilterOptions o...
method UseInMemory (line 57) | public static BloomFilterOptions UseInMemory(this BloomFilterOptions o...
method UseInMemoryWithSerializer (line 74) | public static BloomFilterOptions UseInMemoryWithSerializer<TSerializer...
method UseInMemoryWithSerializer (line 92) | public static BloomFilterOptions UseInMemoryWithSerializer<TSerializer...
FILE: src/BloomFilter/StringSpanExtensions.cs
class StringSpanExtensions (line 6) | internal static class StringSpanExtensions
method ToUtf8 (line 8) | public static ReadOnlyMemory<byte> ToUtf8(this ReadOnlySpan<char> value)
method FromUtf8 (line 23) | public static ReadOnlyMemory<char> FromUtf8(this ReadOnlySpan<byte> so...
method ToUtf8Bytes (line 39) | public static byte[] ToUtf8Bytes(this ReadOnlySpan<char> value)
method WithoutBom (line 44) | public static ReadOnlySpan<char> WithoutBom(this ReadOnlySpan<char> va...
method WithoutBom (line 51) | public static ReadOnlySpan<byte> WithoutBom(this ReadOnlySpan<byte> va...
FILE: test/BenchmarkTest/FreeRedisBenchmark.cs
class FreeRedisBenchmark (line 9) | [RPlotExporter, RankColumn]
method Setup (line 24) | [GlobalSetup]
method Add (line 42) | [Benchmark]
method AddAsync (line 48) | [Benchmark]
FILE: test/BenchmarkTest/Helper.cs
class Helper (line 9) | class Helper
method GenerateString (line 14) | public static string GenerateString(int length)
method GenerateBytes (line 25) | public static byte[] GenerateBytes(int size = 4)
method GenerateData (line 34) | public static IList<byte[]> GenerateData(int n)
FILE: test/BenchmarkTest/MemoryBenchmark.cs
class MemoryBenchmark (line 6) | [RPlotExporter, RankColumn]
method Setup (line 24) | [GlobalSetup]
method Add (line 35) | [Benchmark]
FILE: test/BenchmarkTest/Program.cs
class Program (line 8) | class Program
method Main (line 10) | static void Main(string[] args)
FILE: test/BenchmarkTest/RedisBenchmark.cs
class RedisBenchmark (line 8) | [RPlotExporter, RankColumn]
method Setup (line 23) | [GlobalSetup]
method Add (line 34) | [Benchmark]
method AddAsync (line 40) | [Benchmark]
FILE: test/BloomFilter.Redis.Test/BloomFilterCSRedisTest.cs
class BloomFilterCSRedisTest (line 9) | public class BloomFilterCSRedisTest
method RedisOptionsTest (line 11) | [Fact]
method RedisOptionsConfigurationTest (line 31) | [Fact]
method RedisOptionsSharedTest (line 51) | [Fact]
method Test (line 83) | private void Test(IBloomFilter bf)
FILE: test/BloomFilter.Redis.Test/BloomFilterEasyCachingRedisTest.cs
class BloomFilterEasyCachingRedis (line 15) | public class BloomFilterEasyCachingRedis
method RedisOptionsTest (line 17) | [Fact]
method Test (line 78) | private void Test(IBloomFilter bf)
FILE: test/BloomFilter.Redis.Test/BloomFilterFreeRedisTest.cs
class BloomFilterFreeRedisTest (line 9) | public class BloomFilterFreeRedisTest
method RedisOptionsTest (line 11) | [Fact]
method RedisOptionsConfigurationTest (line 31) | [Fact]
method RedisOptionsSharedTest (line 51) | [Fact]
method Test (line 83) | private void Test(IBloomFilter bf)
FILE: test/BloomFilter.Redis.Test/BloomFilterRedisTest.cs
class BloomFilterRedisTest (line 12) | public class BloomFilterRedisTest
method NormalTest (line 14) | [Theory]
method NormalTestAsync (line 57) | [Theory]
method BytesArrayTest (line 100) | [Theory]
method IntTest (line 150) | [Fact]
method IntTestAsync (line 176) | [Fact]
method BuildTest (line 202) | [Fact]
method buildTest (line 242) | void buildTest(IBloomFilter bf)
method BuildTestAsync (line 262) | [Fact]
method buildTestAsync (line 302) | async Task buildTestAsync(IBloomFilter bf)
FILE: test/BloomFilter.Redis.Test/ConfigurationsTest.cs
class ConfigurationsTest (line 9) | public class ConfigurationsTest
method RedisOptionsTest (line 11) | [Fact]
method RedisOptionsConfigurationTest (line 31) | [Fact]
method RedisOptionsSharedTest (line 51) | [Fact]
method Test (line 83) | private void Test(IBloomFilter bf)
FILE: test/BloomFilter.Redis.Test/RedisBitOperateTest.cs
class RedisBitOperateTest (line 11) | public class RedisBitOperateTest
method NormalTest (line 14) | [Fact]
method NormalTestAsync (line 25) | [Fact]
method Can_Connection_Has_Not_Close (line 36) | [Fact]
method Can_Connection_Has_Not_CloseAsync (line 52) | [Fact]
method Can_Close_With_New_Connection (line 68) | [Fact]
method Can_Close_With_New_ConnectionAsync (line 84) | [Fact]
method Can_The_Batch_Result (line 100) | [Fact]
method Can_The_Batch_ResultAsync (line 125) | [Fact]
FILE: test/BloomFilter.Redis.Test/Utilitiy.cs
class Utilitiy (line 8) | class Utilitiy
method GenerateString (line 12) | public static string GenerateString(int length)
FILE: test/BloomFilterTest/AsyncLockTests.cs
class AsyncLockTests (line 6) | [Collection("AsyncLock Tests")]
method TestMaxCount (line 10) | [Fact]
method TestLock (line 28) | [Fact]
FILE: test/BloomFilterTest/BloomFilterTest.cs
class BloomFilterTest (line 10) | public class BloomFilterTest
method NormalTest (line 12) | [Theory]
method BytesArrayTest (line 55) | [Theory]
method BuildTest (line 102) | [Fact]
method buildTest (line 114) | private void buildTest(IBloomFilter bf)
method FixMurmur3Test (line 134) | [Fact]
FILE: test/BloomFilterTest/ConfigurationsTest.cs
class ConfigurationsTest (line 12) | public class ConfigurationsTest
method NormalTest (line 14) | [Fact]
method BloomFilterFactoryTest (line 48) | [Fact]
FILE: test/BloomFilterTest/FluentFilterBuilderTest.cs
class FluentFilterBuilderTest (line 7) | public class FluentFilterBuilderTest
method Create_ReturnsNewBuilder (line 9) | [Fact]
method BuildInMemory_WithDefaults_CreatesFilter (line 16) | [Fact]
method WithName_SetsFilterName (line 26) | [Fact]
method WithName_Null_ThrowsArgumentException (line 36) | [Fact]
method WithName_EmptyOrWhitespace_ThrowsArgumentException (line 45) | [Fact]
method ExpectingElements_SetsExpectedElements (line 54) | [Fact]
method ExpectingElements_ZeroOrNegative_ThrowsArgumentOutOfRangeException (line 65) | [Fact]
method WithErrorRate_SetsErrorRate (line 74) | [Fact]
method WithErrorRate_InvalidRange_ThrowsArgumentOutOfRangeException (line 85) | [Fact]
method UsingHashMethod_SetsHashMethod (line 96) | [Fact]
method UsingCustomHash_SetsCustomHashFunction (line 107) | [Fact]
method UsingCustomHash_Null_ThrowsArgumentNullException (line 119) | [Fact]
method ChainedCalls_BuildsCorrectFilter (line 127) | [Fact]
method BuildInMemory_FilterFunctionsCorrectly (line 141) | [Fact]
method BuildInMemoryWithCapacity_CreatesFilterWithSpecificCapacity (line 158) | [Fact]
method MultipleBuilds_EachBuildIsIndependent (line 169) | [Fact]
method WithSerializer_UsesCustomSerializer (line 185) | [Fact]
method WithSerializer_Null_ThrowsArgumentNullException (line 197) | [Fact]
method UsingHashMethod_OverridesCustomHash (line 205) | [Fact]
FILE: test/BloomFilterTest/HashAlgorithms/Adler32Test.cs
class Adler32Test (line 8) | public class Adler32Test
method Adler_Append (line 11) | [Theory]
FILE: test/BloomFilterTest/HashAlgorithms/CrcTest.cs
class CrcTest (line 9) | public class CrcTest
method Crc64_Append (line 13) | [Theory]
method Crc32_Append (line 44) | [Theory]
method Crc64TestData (line 75) | public static IEnumerable<object[]> Crc64TestData()
method Crc32TestData (line 83) | public static IEnumerable<object[]> Crc32TestData()
FILE: test/BloomFilterTest/HashAlgorithms/FNVTest.cs
class FNVTest (line 9) | public class FNVTest
method FNVTest (line 13) | public FNVTest(ITestOutputHelper testOutputHelper)
method FNV1_Test (line 18) | [Fact]
method FNV1_Append (line 31) | [Fact]
method FNV1a_Test (line 60) | [Fact]
method FNV1a_Append (line 73) | [Fact]
method ModifiedFNV1_Test (line 102) | [Fact]
method ModifiedFNV1_Append (line 115) | [Fact]
method ModifiedFNV1TestData (line 144) | private static IEnumerable<(uint Hash, string Hex)> ModifiedFNV1TestDa...
method FNV1aTestData (line 198) | private static IEnumerable<(uint Hash, string Hex)> FNV1aTestData()
method FNV1TestData (line 252) | private static IEnumerable<(uint Hash, string Hex)> FNV1TestData()
FILE: test/BloomFilterTest/HashAlgorithms/Murmur3Test.cs
class Murmur3Test (line 9) | public class Murmur3Test
method Murmur32BitsX86_Hash (line 11) | [Fact]
method Murmur32BitsX86_Append (line 24) | [Fact]
method MurMurHash128X64 (line 52) | [Fact]
method MurMurHash128X64_Append (line 71) | [Fact]
method MurMurHash128X86 (line 102) | [Fact]
method MurMurHash128X86_Append (line 115) | [Fact]
method Murmur128BitsX86TestData (line 140) | private static IEnumerable<(uint[] Hash, uint Seed, string Hex)> Murmu...
method Murmur128BitsX64TestData (line 194) | private static IEnumerable<(string Hash, uint Seed, string Hex)> Murmu...
method Murmur32BitsX86TestData (line 248) | private static IEnumerable<(string Hash, uint Seed, string Hex)> Murmu...
FILE: test/BloomFilterTest/HashAlgorithms/TestPayloadParameter.cs
class TestPayloadParameter (line 5) | public class TestPayloadParameter<TExpected>
method TestPayloadParameter (line 12) | public TestPayloadParameter(byte[] payload, Range range, TExpected exp...
method TestPayloadParameter (line 20) | public TestPayloadParameter(byte[] payload, TExpected expected)
FILE: test/BloomFilterTest/HashAlgorithms/XxHashTest.cs
class XxHashTest (line 9) | public class XxHashTest
method XxHash32_ToUInt32 (line 11) | [Theory]
method XxHash32_Append (line 33) | [Theory]
method XxHash64_ToUInt64 (line 63) | [Theory]
method XxHash64_Append (line 85) | [Theory]
method XxHash3_ToUInt64 (line 115) | [Fact]
method XxHash3_Append (line 129) | [Fact]
method XxHash128_ToUInt64 (line 152) | [Fact]
method XxHash128_Append (line 166) | [Fact]
method XxHash32TestData (line 189) | public static IEnumerable<object[]> XxHash32TestData()
method XxHash64TestData (line 197) | public static IEnumerable<object[]> XxHash64TestData()
method XxHash3TestData (line 207) | private static IEnumerable<(ulong Hash, ulong Seed, string Ascii)> XxH...
method XxHash128TestData (line 1207) | private static IEnumerable<(ulong HashHigh, ulong HashLow, ulong Seed,...
FILE: test/BloomFilterTest/ImportExportTest.cs
class ImportExportTest (line 11) | public class ImportExportTest
method ExportToBytes_And_Import (line 14) | [Fact]
method Export_BitArray_And_Import (line 34) | [Fact]
method Fill_Export_And_Import_Contains (line 55) | [Theory]
FILE: test/BloomFilterTest/IssuesTest.cs
class IssuesTest (line 13) | public class IssuesTest
method Issues_16 (line 16) | [Theory]
FILE: test/BloomFilterTest/SerializerTest.cs
class SerializerTest (line 10) | public class SerializerTest
method Serialize (line 12) | [Theory]
method SerializeLarge (line 52) | [Theory]
FILE: test/BloomFilterTest/Utilitiy.cs
class Utilitiy (line 9) | static class Utilitiy
method GenerateString (line 14) | public static string GenerateString(int length)
method GenerateBytes (line 25) | public static byte[] GenerateBytes(int size = 4)
method ToUtf8Bytes (line 34) | public static byte[] ToUtf8Bytes(this string s)
method FromHex (line 39) | public static byte[] FromHex(this string s)
FILE: test/BloomFilterTest/ValueTypeTest.cs
class ValueTypeTest (line 11) | public class ValueTypeTest
method Int32 (line 13) | [Theory]
method Int16 (line 56) | [Theory]
method Int64 (line 99) | [Theory]
method Double (line 142) | [Theory]
method Float (line 185) | [Theory]
method Date (line 229) | [Theory]
FILE: test/Demo/BloomFilterMemory.cs
class BloomFilterMemory (line 6) | public class BloomFilterMemory
method SampleInMem (line 8) | [Test("Sample In Memory")]
method Sample (line 24) | private void Sample(IBloomFilter bf)
FILE: test/Demo/BloomFilterRedis.cs
class BloomFilterRedis (line 7) | public class BloomFilterRedis
method SampleInRedis (line 9) | [Test("Sample In Redis")]
method Sample (line 26) | private void Sample(IBloomFilter bf)
FILE: test/Demo/Program.cs
class Program (line 6) | class Program
method Main (line 8) | static void Main(string[] args)
FILE: test/Demo/TestExcute.cs
class TestAttribute (line 27) | public class TestAttribute : Attribute
method TestAttribute (line 42) | public TestAttribute()
method TestAttribute (line 50) | public TestAttribute(string description, string code = "")
class TestExcute (line 60) | public static class TestExcute
method Excute (line 66) | public static void Excute(Type t)
method LrTag (line 167) | private static void LrTag(string view, string tag, int size)
method WriteLine (line 186) | private static void WriteLine(this TextWriter writer,
class ExecuteFunc (line 199) | private class ExecuteFunc
method ExecuteFunc (line 215) | public ExecuteFunc(object instance, MethodInfo method, string descri...
method Execute (line 235) | public void Execute()
method ToString (line 247) | public override string ToString()
FILE: test/PerformanceTest/GeneralPerformance.cs
class GeneralPerformance (line 14) | public class GeneralPerformance
method RedisPerformance (line 16) | [Test("RedisPerformance")]
method RedisClusterPerformance (line 45) | [Test("RedisClusterPerformance")]
method MemoryPerformance (line 77) | [Test("MemoryPerformance")]
method Performance (line 97) | private void Performance(IList<byte[]> hashData, IBloomFilter bf)
FILE: test/PerformanceTest/HashErrRate.cs
class HashErrRate (line 9) | public class HashErrRate
method ErrRateTest (line 11) | [Test("Bloom Filter Hash ErrRate")]
method ErrRateTest (line 34) | private void ErrRateTest(HashMethod hashMethod, IList<byte[]> hashData...
FILE: test/PerformanceTest/HashSpeed.cs
class HashSpeed (line 9) | public class HashSpeed
method Performance (line 11) | [Test("HashPerformance")]
method HashPerformance (line 42) | private void HashPerformance(HashFunction hashFunction)
FILE: test/PerformanceTest/Helper.cs
class Helper (line 11) | internal class Helper
method GenerateString (line 16) | public static string GenerateString(int length)
method GenerateBytes (line 27) | public static byte[] GenerateBytes(int size = 4)
method GenerateData (line 36) | public static IList<byte[]> GenerateData(long n)
method GenerateData (line 41) | public static IList<byte[]> GenerateData(int n)
method Time (line 59) | public static void Time(string name, Action<int> action, int iteration...
method TimeWithThread (line 70) | public static void TimeWithThread(string name, Action<int, int> action...
method TimeWithParallel (line 93) | public static void TimeWithParallel(string name, Action<int> action, i...
method TimeExecute (line 105) | private static void TimeExecute(string name, Action action, int iterat...
method GetCycleCount (line 144) | private static ulong GetCycleCount()
method QueryThreadCycleTime (line 151) | [DllImport("kernel32.dll")]
method GetCurrentThread (line 155) | [DllImport("kernel32.dll")]
method PrintMem (line 158) | public static void PrintMem()
method FormatBytesToString (line 163) | public static string FormatBytesToString(double bytes)
FILE: test/PerformanceTest/Issues_2.cs
class Issues_2 (line 12) | public class Issues_2
method Performance (line 14) | [Test("Redis Performance")]
FILE: test/PerformanceTest/Program.cs
class Program (line 6) | class Program
method Main (line 8) | static void Main(string[] args)
FILE: test/PerformanceTest/TestExcute.cs
class TestAttribute (line 27) | public class TestAttribute : Attribute
method TestAttribute (line 42) | public TestAttribute()
method TestAttribute (line 50) | public TestAttribute(string description, string code = "")
class TestExcute (line 60) | public static class TestExcute
method Excute (line 66) | public static void Excute(Type t)
method LrTag (line 167) | private static void LrTag(string view, string tag, int size)
method WriteLine (line 186) | private static void WriteLine(this TextWriter writer,
class ExecuteFunc (line 199) | private class ExecuteFunc
method ExecuteFunc (line 215) | public ExecuteFunc(object instance, MethodInfo method, string descri...
method Execute (line 235) | public void Execute()
method ToString (line 247) | public override string ToString()
Condensed preview — 147 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,219K chars).
[
{
"path": ".gitignore",
"chars": 696,
"preview": "# Build results\n\n[Dd]ebug/\n[Rr]elease/\nx64/\napp.publish/\n[Bb]in/\n[Oo]bj/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]u"
},
{
"path": "BloomFilter.NetCore.sln",
"chars": 6756,
"preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.0.3190"
},
{
"path": "Directory.Build.props",
"chars": 1454,
"preview": "<Project>\n\n <PropertyGroup>\n <Version>$(Ver)</Version>\n <PackageVersion>$(Ver)</PackageVersion>\n <Copyright>20"
},
{
"path": "Directory.Packages.props",
"chars": 3220,
"preview": "<Project>\n <PropertyGroup>\n <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>\n <CentralPackag"
},
{
"path": "LICENSE",
"chars": 1069,
"preview": "MIT License\n\nCopyright (c) 2018 v.la@live.cn\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
},
{
"path": "README.md",
"chars": 38133,
"preview": "# BloomFilter.NetCore\n\n[](https://opensource.org/licen"
},
{
"path": "README.zh-CN.md",
"chars": 30181,
"preview": "# BloomFilter.NetCore\n\n[](https://opensource.org/licen"
},
{
"path": "VERSION",
"chars": 6,
"preview": "3.0.0\n"
},
{
"path": "build.cmd",
"chars": 668,
"preview": "set artifacts=%~dp0artifacts\n\nif exist %artifacts% rd /q /s %artifacts%\n\nset /p ver=<VERSION\n\ndotnet restore src/BloomF"
},
{
"path": "build.sh",
"chars": 270,
"preview": "#!/usr/bin/env bash\nset -e\nbasepath=$(cd `dirname $0`; pwd)\nartifacts=${basepath}/artifacts\n\nif [[ -d ${artifacts} ]]; t"
},
{
"path": "nuget_push.cmd",
"chars": 471,
"preview": "set /p ver=<VERSION\nset sourceUrl=-s https://www.nuget.org/api/v2/package\n\ndotnet nuget push artifacts/BloomFilter.NetCo"
},
{
"path": "src/BloomFilter/Annotations.cs",
"chars": 9859,
"preview": "\n#if NETSTANDARD2_0 || NETFRAMEWORK\n\nnamespace System.Diagnostics.CodeAnalysis;\n\n/// <summary>Specifies that null is all"
},
{
"path": "src/BloomFilter/AsyncLock.cs",
"chars": 2285,
"preview": "using System;\nusing System.Runtime.CompilerServices;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace B"
},
{
"path": "src/BloomFilter/BinaryHelper.cs",
"chars": 4879,
"preview": "using System;\nusing System.Collections;\nusing System.Numerics;\nusing System.Runtime.CompilerServices;\n\n#if NET6_0_OR_GR"
},
{
"path": "src/BloomFilter/BloomFilter.csproj",
"chars": 940,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\t<PropertyGroup>\n\t\t<AssemblyName>BloomFilter</AssemblyName>\n\t\t<AssemblyTitle>BloomFil"
},
{
"path": "src/BloomFilter/BloomFilterConstValue.cs",
"chars": 344,
"preview": "namespace BloomFilter;\n\npublic class BloomFilterConstValue\n{\n /// <summary>\n /// The default name of the in-memor"
},
{
"path": "src/BloomFilter/BloomFilterExtensions.cs",
"chars": 19180,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nna"
},
{
"path": "src/BloomFilter/Configurations/BloomFilterOptions.cs",
"chars": 809,
"preview": "using System;\nusing System.Collections.Generic;\n\nnamespace BloomFilter.Configurations;\n\n/// <summary>\n/// BloomFilterOp"
},
{
"path": "src/BloomFilter/Configurations/FilterMemoryOptions.cs",
"chars": 871,
"preview": "using System.Collections;\nusing System.Collections.Generic;\n\nnamespace BloomFilter.Configurations;\n\npublic class Filter"
},
{
"path": "src/BloomFilter/Configurations/FilterMemoryOptionsExtension.cs",
"chars": 1349,
"preview": "using System;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection.Extensions"
},
{
"path": "src/BloomFilter/Configurations/IBloomFilterOptionsExtension.cs",
"chars": 366,
"preview": "using Microsoft.Extensions.DependencyInjection;\n\nnamespace BloomFilter.Configurations;\n\n/// <summary>\n/// BloomFilter o"
},
{
"path": "src/BloomFilter/DefaultBloomFilterFactory.cs",
"chars": 1126,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics.CodeAnalysis;\nusing System.Linq;\n\nnamespace Bl"
},
{
"path": "src/BloomFilter/DefaultFilterMemorySerializer.cs",
"chars": 3405,
"preview": "using System;\nusing System.Collections;\nusing System.IO;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Bl"
},
{
"path": "src/BloomFilter/Filter.cs",
"chars": 9996,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nnamespace BloomFilter;\n\n/// <summary>\n//"
},
{
"path": "src/BloomFilter/FilterBuilder.cs",
"chars": 10501,
"preview": "using System;\nusing BloomFilter.Configurations;\n\nnamespace BloomFilter;\n\n/// <summary>\n/// BloomFilter Builder - Suppor"
},
{
"path": "src/BloomFilter/FilterMemory.cs",
"chars": 12849,
"preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Diagnostics.CodeAnalysis;\nusing "
},
{
"path": "src/BloomFilter/FilterMemorySerializerParam.cs",
"chars": 1169,
"preview": "using System.Collections;\n\nnamespace BloomFilter;\n\n/// <summary>\n/// FilterMemorySerializerParam\n/// </summary>\npublic "
},
{
"path": "src/BloomFilter/FilterRedisBase.cs",
"chars": 7275,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace BloomFilter;"
},
{
"path": "src/BloomFilter/HashAlgorithms/Adler32.cs",
"chars": 867,
"preview": "using System;\n\nnamespace BloomFilter.HashAlgorithms;\n\npublic class Adler32 : HashFunction\n{\n public override HashMet"
},
{
"path": "src/BloomFilter/HashAlgorithms/Crc32.cs",
"chars": 844,
"preview": "using System;\n\nnamespace BloomFilter.HashAlgorithms;\n\npublic partial class Crc32 : HashFunction\n{\n public override H"
},
{
"path": "src/BloomFilter/HashAlgorithms/Crc64.cs",
"chars": 560,
"preview": "using System;\n\nnamespace BloomFilter.HashAlgorithms;\n\npublic partial class Crc64 : HashFunction\n{\n public override H"
},
{
"path": "src/BloomFilter/HashAlgorithms/HashCrypto.cs",
"chars": 2725,
"preview": "using System;\nusing System.Collections;\nusing System.Security.Cryptography;\n\nnamespace BloomFilter.HashAlgorithms;\n\npub"
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Adler32.cs",
"chars": 7919,
"preview": "using System;\nusing System.Buffers.Binary;\nusing System.Runtime.InteropServices;\n\n#if NET6_0_OR_GREATER\nusing System.Run"
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Crc32.Arm.cs",
"chars": 2177,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Crc32.Table.cs",
"chars": 4829,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Crc32.Vectorized.cs",
"chars": 6453,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Crc32.cs",
"chars": 3055,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Crc64.Table.cs",
"chars": 6599,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Crc64.Vectorized.cs",
"chars": 7918,
"preview": "#if NET7_0_OR_GREATER\nusing System;\nusing System.Diagnostics;\nusing System.Runtime.CompilerServices;\nusing System.Runtim"
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Crc64.cs",
"chars": 3700,
"preview": "\n// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you unde"
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/FNV1.cs",
"chars": 2574,
"preview": "using System;\nusing System.Buffers.Binary;\n\nnamespace BloomFilter.HashAlgorithms.Internal;\n\n/// <summary>\n/// FNV1 alg"
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/FNV1a.cs",
"chars": 2567,
"preview": "using System;\nusing System.Buffers.Binary;\n\nnamespace BloomFilter.HashAlgorithms.Internal;\n\n/// <summary>\n/// FNV1a algo"
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/ModifiedFNV1.cs",
"chars": 3063,
"preview": "using System;\nusing System.Buffers.Binary;\n\nnamespace BloomFilter.HashAlgorithms.Internal;\n\n/// <summary>\n/// Implemen"
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Murmur128BitsX64.State.cs",
"chars": 3551,
"preview": "using System;\nusing System.Buffers.Binary;\nusing System.Runtime.CompilerServices;\n\nnamespace BloomFilter.HashAlgorithms."
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Murmur128BitsX64.cs",
"chars": 3500,
"preview": "using System;\nusing System.Buffers.Binary;\n\nnamespace BloomFilter.HashAlgorithms.Internal;\n\n/// <summary>\n/// Provides "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Murmur128BitsX86.State.cs",
"chars": 4502,
"preview": "using System;\nusing System.Buffers.Binary;\nusing System.Runtime.CompilerServices;\n\nnamespace BloomFilter.HashAlgorithms."
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Murmur128BitsX86.cs",
"chars": 3314,
"preview": "using System;\nusing System.Buffers.Binary;\n\nnamespace BloomFilter.HashAlgorithms.Internal;\n\n/// <summary>\n/// Provides "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Murmur32BitsX86.State.cs",
"chars": 2503,
"preview": "using System;\nusing System.Buffers.Binary;\nusing System.Runtime.CompilerServices;\n\nnamespace BloomFilter.HashAlgorithms."
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/Murmur32BitsX86.cs",
"chars": 2870,
"preview": "using System;\nusing System.Buffers.Binary;\n\nnamespace BloomFilter.HashAlgorithms.Internal;\n\n/// <summary>\n/// Provides "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/NonCryptoHashAlgorithm.cs",
"chars": 1458,
"preview": "using System;\nusing System.Diagnostics;\nusing System.Diagnostics.CodeAnalysis;\n\nnamespace BloomFilter.HashAlgorithms.Int"
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/ThrowHelper.cs",
"chars": 299,
"preview": "using System.Diagnostics;\nusing System.Diagnostics.CodeAnalysis;\n\nnamespace BloomFilter.HashAlgorithms.Internal;\n\nintern"
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/VectorHelper.cs",
"chars": 4291,
"preview": "#if NET7_0_OR_GREATER\n\nusing System.Diagnostics.CodeAnalysis;\nusing System.Runtime.CompilerServices;\nusing System.Runti"
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/XxHash128.cs",
"chars": 17157,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/XxHash3.cs",
"chars": 11578,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/XxHash32.State.cs",
"chars": 3181,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/XxHash32.cs",
"chars": 4734,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/XxHash64.State.cs",
"chars": 4324,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/XxHash64.cs",
"chars": 4738,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "src/BloomFilter/HashAlgorithms/Internal/XxHashShared.cs",
"chars": 39285,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "src/BloomFilter/HashAlgorithms/LCGWithFNV.cs",
"chars": 2099,
"preview": "using System;\n\nnamespace BloomFilter.HashAlgorithms;\n\n/// <summary>\n/// Implements an Linear Congruential Generator Wit"
},
{
"path": "src/BloomFilter/HashAlgorithms/Murmur128BitsX64.cs",
"chars": 600,
"preview": "using System;\n\nnamespace BloomFilter.HashAlgorithms;\n\npublic class Murmur128BitsX64 : HashFunction\n{\n public overrid"
},
{
"path": "src/BloomFilter/HashAlgorithms/Murmur128BitsX86.cs",
"chars": 580,
"preview": "using System;\n\nnamespace BloomFilter.HashAlgorithms;\n\npublic class Murmur128BitsX86 : HashFunction\n{\n public overrid"
},
{
"path": "src/BloomFilter/HashAlgorithms/Murmur32BitsX86.cs",
"chars": 748,
"preview": "using System;\n\nnamespace BloomFilter.HashAlgorithms;\n\n/// <summary>\n/// Building a Better Bloom Filter\" by Adam Kirsch "
},
{
"path": "src/BloomFilter/HashAlgorithms/RNGWithFNV.cs",
"chars": 1527,
"preview": "using System;\n\nnamespace BloomFilter.HashAlgorithms;\n\n/// <summary>\n/// Implements an Random With FNV1a hash algorithm."
},
{
"path": "src/BloomFilter/HashAlgorithms/XXHash128.cs",
"chars": 839,
"preview": "using System;\nusing System.Buffers.Binary;\n\nnamespace BloomFilter.HashAlgorithms;\n\npublic class XXHash128 : HashFunctio"
},
{
"path": "src/BloomFilter/HashAlgorithms/XXHash3.cs",
"chars": 559,
"preview": "using System;\n\nnamespace BloomFilter.HashAlgorithms;\n\npublic class XXHash3 : HashFunction\n{\n public override HashMet"
},
{
"path": "src/BloomFilter/HashAlgorithms/XXHash32.cs",
"chars": 555,
"preview": "using System;\n\nnamespace BloomFilter.HashAlgorithms;\n\npublic class XXHash32 : HashFunction\n{\n public override HashMe"
},
{
"path": "src/BloomFilter/HashAlgorithms/XXHash64.cs",
"chars": 564,
"preview": "using System;\n\nnamespace BloomFilter.HashAlgorithms;\n\npublic class XXHash64 : HashFunction\n{\n public override HashMe"
},
{
"path": "src/BloomFilter/HashFunction.cs",
"chars": 2057,
"preview": "using BloomFilter.HashAlgorithms;\nusing System;\nusing System.Collections.Generic;\n\nnamespace BloomFilter;\n\n/// <summary"
},
{
"path": "src/BloomFilter/HashMethod.cs",
"chars": 555,
"preview": "namespace BloomFilter;\n\n/// <summary>\n/// Hash Methods\n/// </summary>\npublic enum HashMethod : int\n{\n LCGWithFNV1 = "
},
{
"path": "src/BloomFilter/IBloomFilter.cs",
"chars": 2889,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nnamespace BloomFilter;\n\n/// <summary>\n//"
},
{
"path": "src/BloomFilter/IBloomFilterFactory.cs",
"chars": 695,
"preview": "using System.Diagnostics.CodeAnalysis;\n\nnamespace BloomFilter;\n\n/// <summary>\n/// BloomFilter Factory\n/// </summary>\npu"
},
{
"path": "src/BloomFilter/IFilterMemorySerializer.cs",
"chars": 681,
"preview": "using System.IO;\nusing System.Threading.Tasks;\n\nnamespace BloomFilter;\n\n/// <summary>\n/// Represents a <see cref=\"Filt"
},
{
"path": "src/BloomFilter/Properties/AssemblyInfo.cs",
"chars": 1907,
"preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Secu"
},
{
"path": "src/BloomFilter/ServiceCollectionExtensions.cs",
"chars": 4081,
"preview": "using System;\nusing BloomFilter;\nusing BloomFilter.Configurations;\n\nnamespace Microsoft.Extensions.DependencyInjection\n"
},
{
"path": "src/BloomFilter/StringSpanExtensions.cs",
"chars": 1845,
"preview": "using System;\nusing System.Text;\n\nnamespace BloomFilter;\n\ninternal static class StringSpanExtensions\n{\n public stati"
},
{
"path": "src/BloomFilter.CSRedis/BloomFilter.CSRedis.csproj",
"chars": 732,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\t<PropertyGroup>\n\t\t<AssemblyName>BloomFilter.CSRedis</AssemblyName>\n\t\t<AssemblyTitle>"
},
{
"path": "src/BloomFilter.CSRedis/Configurations/FilterCSRedisOptions.cs",
"chars": 1247,
"preview": "using BloomFilter.Configurations;\nusing CSRedis;\nusing System;\nusing System.Collections.Generic;\n\nnamespace BloomFilter"
},
{
"path": "src/BloomFilter.CSRedis/Configurations/FilterCSRedisOptionsExtension.cs",
"chars": 2744,
"preview": "using BloomFilter.Configurations;\nusing CSRedis;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extens"
},
{
"path": "src/BloomFilter.CSRedis/Configurations/ServiceCollectionExtensions.cs",
"chars": 1510,
"preview": "using BloomFilter;\nusing BloomFilter.Configurations;\nusing BloomFilter.CSRedis.Configurations;\nusing System;\n\nnamespace"
},
{
"path": "src/BloomFilter.CSRedis/FilterCSRedis.cs",
"chars": 5915,
"preview": "using CSRedis;\nusing System;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace BloomFilter.CSRedis;\n\n/// <summ"
},
{
"path": "src/BloomFilter.CSRedis/FilterCSRedisBuilder.cs",
"chars": 3828,
"preview": "using CSRedis;\nusing System;\n\nnamespace BloomFilter.CSRedis;\n\n/// <summary>\n/// BloomFilter CSRedis Builder - Supports b"
},
{
"path": "src/BloomFilter.EasyCaching/BloomFilter.EasyCaching.csproj",
"chars": 824,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\t<PropertyGroup>\n\t\t<AssemblyName>BloomFilter.EasyCaching</AssemblyName>\n\t\t<AssemblyTi"
},
{
"path": "src/BloomFilter.EasyCaching/Configurations/FilterEasyCachingRedisExtension.cs",
"chars": 1699,
"preview": "using BloomFilter.Configurations;\nusing BloomFilter.EasyCaching;\nusing EasyCaching.Core;\nusing Microsoft.Extensions.Dep"
},
{
"path": "src/BloomFilter.EasyCaching/Configurations/FilterEasyCachingRedisOptions.cs",
"chars": 634,
"preview": "using BloomFilter.Configurations;\nusing EasyCaching.Core;\n\nnamespace BloomFilter.CSRedis.Configurations\n{\n public cl"
},
{
"path": "src/BloomFilter.EasyCaching/Configurations/ServiceCollectionExtensions.cs",
"chars": 1583,
"preview": "using BloomFilter;\nusing BloomFilter.Configurations;\nusing BloomFilter.CSRedis.Configurations;\nusing System;\n\nnamespace"
},
{
"path": "src/BloomFilter.EasyCaching/FilterEasyCachingBuilder.cs",
"chars": 4026,
"preview": "using EasyCaching.Core;\nusing System;\n\nnamespace BloomFilter.EasyCaching;\n\n/// <summary>\n/// BloomFilter EasyCaching Bui"
},
{
"path": "src/BloomFilter.EasyCaching/FilterEasyCachingRedis.cs",
"chars": 9394,
"preview": "using EasyCaching.Core;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks"
},
{
"path": "src/BloomFilter.FreeRedis/BloomFilter.FreeRedis.csproj",
"chars": 736,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\t<PropertyGroup>\n\t\t<AssemblyName>BloomFilter.FreeRedis</AssemblyName>\n\t\t<AssemblyTitl"
},
{
"path": "src/BloomFilter.FreeRedis/Configurations/FilterFreeRedisOptions.cs",
"chars": 1105,
"preview": "using BloomFilter.Configurations;\nusing FreeRedis;\nusing System;\nusing System.Collections.Generic;\n\nnamespace BloomFilt"
},
{
"path": "src/BloomFilter.FreeRedis/Configurations/FilterFreeRedisOptionsExtension.cs",
"chars": 2587,
"preview": "using BloomFilter.Configurations;\nusing FreeRedis;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Exte"
},
{
"path": "src/BloomFilter.FreeRedis/Configurations/ServiceCollectionExtensions.cs",
"chars": 1526,
"preview": "using BloomFilter;\nusing BloomFilter.Configurations;\nusing BloomFilter.FreeRedis.Configurations;\nusing System;\n\nnamespa"
},
{
"path": "src/BloomFilter.FreeRedis/FilterFreeRedis.cs",
"chars": 5889,
"preview": "using FreeRedis;\nusing System;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace BloomFilter.FreeRedis;\n\n/// "
},
{
"path": "src/BloomFilter.FreeRedis/FilterFreeRedisBuilder.cs",
"chars": 3858,
"preview": "using FreeRedis;\nusing System;\n\nnamespace BloomFilter.FreeRedis;\n\n/// <summary>\n/// BloomFilter FreeRedis Builder - Supp"
},
{
"path": "src/BloomFilter.Redis/BloomFilter.Redis.csproj",
"chars": 736,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\t<PropertyGroup>\n\t\t<AssemblyName>BloomFilter.Redis</AssemblyName>\n\t\t<AssemblyTitle>Bl"
},
{
"path": "src/BloomFilter.Redis/Configurations/FilterRedisOptions.cs",
"chars": 2519,
"preview": "using BloomFilter.Configurations;\nusing StackExchange.Redis;\nusing System.Collections.Generic;\n\nnamespace BloomFilter.R"
},
{
"path": "src/BloomFilter.Redis/Configurations/FilterRedisOptionsExtension.cs",
"chars": 2568,
"preview": "using BloomFilter.Configurations;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Dependency"
},
{
"path": "src/BloomFilter.Redis/Configurations/ServiceCollectionExtensions.cs",
"chars": 1494,
"preview": "using BloomFilter;\nusing BloomFilter.Configurations;\nusing BloomFilter.Redis.Configurations;\nusing System;\n\nnamespace M"
},
{
"path": "src/BloomFilter.Redis/FilterRedis.cs",
"chars": 4843,
"preview": "using System;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace BloomFilter.Redis;\n\n/// <summary>\n/// Bloom Fi"
},
{
"path": "src/BloomFilter.Redis/FilterRedisBuilder.cs",
"chars": 25637,
"preview": "using StackExchange.Redis;\nusing System;\n\nnamespace BloomFilter.Redis;\n\n/// <summary>\n/// BloomFilter Redis Builder - S"
},
{
"path": "src/BloomFilter.Redis/IRedisBitOperate.cs",
"chars": 751,
"preview": "using System;\nusing System.Threading.Tasks;\n\nnamespace BloomFilter.Redis;\n\n/// <summary>\n/// Redis BitMap operate Inter"
},
{
"path": "src/BloomFilter.Redis/RedisBitOperate.cs",
"chars": 7461,
"preview": "using StackExchange.Redis;\nusing System;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nname"
},
{
"path": "test/BenchmarkTest/BenchmarkTest.csproj",
"chars": 660,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<OutputType>Exe</OutputType>\n\t\t<TargetFrameworks>net8.0;net9.0;ne"
},
{
"path": "test/BenchmarkTest/FreeRedisBenchmark.cs",
"chars": 1325,
"preview": "using BenchmarkDotNet.Attributes;\nusing BloomFilter;\nusing BloomFilter.FreeRedis;\nusing FreeRedis;\nusing System.Threadi"
},
{
"path": "test/BenchmarkTest/Helper.cs",
"chars": 1612,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Security.Cryptography;\nusing System.Tex"
},
{
"path": "test/BenchmarkTest/MemoryBenchmark.cs",
"chars": 852,
"preview": "using BenchmarkDotNet.Attributes;\nusing BloomFilter;\n\nnamespace BenchmarkTest\n{\n [RPlotExporter, RankColumn]\n [Mi"
},
{
"path": "test/BenchmarkTest/Program.cs",
"chars": 622,
"preview": "using System;\nusing System.Reflection;\nusing BenchmarkDotNet.Configs;\nusing BenchmarkDotNet.Running;\n\nnamespace Benchma"
},
{
"path": "test/BenchmarkTest/RedisBenchmark.cs",
"chars": 1050,
"preview": "using BenchmarkDotNet.Attributes;\nusing BloomFilter;\nusing BloomFilter.Redis;\nusing System.Threading.Tasks;\n\nnamespace "
},
{
"path": "test/BloomFilter.Redis.Test/BloomFilter.Redis.Test.csproj",
"chars": 1176,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>net10.0</TargetFramework>\n </PropertyGroup>\n"
},
{
"path": "test/BloomFilter.Redis.Test/BloomFilterCSRedisTest.cs",
"chars": 2926,
"preview": "using BloomFilter.CSRedis.Configurations;\nusing CSRedis;\nusing Microsoft.Extensions.DependencyInjection;\nusing System.Li"
},
{
"path": "test/BloomFilter.Redis.Test/BloomFilterEasyCachingRedisTest.cs",
"chars": 3002,
"preview": "using BloomFilter.CSRedis.Configurations;\nusing BloomFilter.EasyCaching;\nusing CSRedis;\nusing EasyCaching.Core.Serializa"
},
{
"path": "test/BloomFilter.Redis.Test/BloomFilterFreeRedisTest.cs",
"chars": 2954,
"preview": "using BloomFilter.FreeRedis.Configurations;\nusing FreeRedis;\nusing Microsoft.Extensions.DependencyInjection;\nusing Syste"
},
{
"path": "test/BloomFilter.Redis.Test/BloomFilterRedisTest.cs",
"chars": 13089,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Security.Cryptography;\nusing System.Threading.Tasks;\nusing "
},
{
"path": "test/BloomFilter.Redis.Test/ConfigurationsTest.cs",
"chars": 2965,
"preview": "using BloomFilter.Redis.Configurations;\nusing Microsoft.Extensions.DependencyInjection;\nusing StackExchange.Redis;\nusin"
},
{
"path": "test/BloomFilter.Redis.Test/RedisBitOperateTest.cs",
"chars": 4490,
"preview": "using StackExchange.Redis;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing "
},
{
"path": "test/BloomFilter.Redis.Test/Utilitiy.cs",
"chars": 700,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace BloomFilter.Redis.Test"
},
{
"path": "test/BloomFilterTest/AsyncLockTests.cs",
"chars": 1488,
"preview": "using BloomFilter;\nusing Xunit;\n\nnamespace BloomFilterTest\n{\n [Collection(\"AsyncLock Tests\")]\n [CollectionDefinit"
},
{
"path": "test/BloomFilterTest/BloomFilterTest.cs",
"chars": 4787,
"preview": "using BloomFilter;\nusing BloomFilter.HashAlgorithms;\nusing System;\nusing System.Collections.Generic;\nusing System.Securi"
},
{
"path": "test/BloomFilterTest/BloomFilterTest.csproj",
"chars": 746,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>net10.0</TargetFramework>\n\n <IsPackable>fa"
},
{
"path": "test/BloomFilterTest/ConfigurationsTest.cs",
"chars": 1949,
"preview": "using BloomFilter;\nusing Microsoft.Extensions.DependencyInjection;\nusing System;\nusing System.Collections.Generic;\nusin"
},
{
"path": "test/BloomFilterTest/FluentFilterBuilderTest.cs",
"chars": 6770,
"preview": "using BloomFilter;\nusing System;\nusing Xunit;\n\nnamespace BloomFilterTest\n{\n public class FluentFilterBuilderTest\n "
},
{
"path": "test/BloomFilterTest/HashAlgorithms/Adler32Test.cs",
"chars": 1104,
"preview": "using System;\nusing System.Linq;\nusing BloomFilter.HashAlgorithms.Internal;\nusing Xunit;\n\nnamespace BloomFilterTest.Hash"
},
{
"path": "test/BloomFilterTest/HashAlgorithms/CrcTest.cs",
"chars": 3878,
"preview": "using System;\nusing System.Collections.Generic;\nusing BloomFilter.HashAlgorithms.Internal;\nusing FluentAssertions;\nusing"
},
{
"path": "test/BloomFilterTest/HashAlgorithms/FNVTest.cs",
"chars": 31685,
"preview": "using BloomFilter.HashAlgorithms.Internal;\nusing System;\nusing System.Collections.Generic;\nusing Xunit;\nusing Xunit.Abst"
},
{
"path": "test/BloomFilterTest/HashAlgorithms/Murmur3Test.cs",
"chars": 95713,
"preview": "using BloomFilter.HashAlgorithms.Internal;\nusing System;\nusing System.Buffers.Binary;\nusing System.Collections.Generic;\n"
},
{
"path": "test/BloomFilterTest/HashAlgorithms/TestPayloadParameter.cs",
"chars": 788,
"preview": "using System;\n\nnamespace BloomFilterTest.HashAlgorithms\n{\n public class TestPayloadParameter<TExpected>\n {\n "
},
{
"path": "test/BloomFilterTest/HashAlgorithms/XxHashTest.cs",
"chars": 478696,
"preview": "using System;\nusing System.Collections.Generic;\nusing BloomFilter.HashAlgorithms.Internal;\nusing FluentAssertions;\nusing"
},
{
"path": "test/BloomFilterTest/ImportExportTest.cs",
"chars": 2827,
"preview": "using BloomFilter;\nusing System;\nusing System.Collections;\nusing Xunit;\nusing BloomFilter.Configurations;\nusing System."
},
{
"path": "test/BloomFilterTest/IssuesTest.cs",
"chars": 1199,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Security.Cryptography;\nusing System.Tex"
},
{
"path": "test/BloomFilterTest/SerializerTest.cs",
"chars": 2445,
"preview": "using System;\nusing System.IO;\nusing System.Threading.Tasks;\nusing BloomFilter;\nusing BloomFilter.Configurations;\nusing"
},
{
"path": "test/BloomFilterTest/Utilitiy.cs",
"chars": 1331,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Security.Cryptography;\nusing System.Tex"
},
{
"path": "test/BloomFilterTest/ValueTypeTest.cs",
"chars": 9784,
"preview": "using BloomFilter;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.T"
},
{
"path": "test/BloomFilterTest/xunit.runner.json",
"chars": 188,
"preview": "{\n \"parallelAlgorithm\": \"aggressive\",\n \"parallelizeAssembly\": true,\n \"parallelizeTestCollections\": true,\n \"stopOnFai"
},
{
"path": "test/Demo/BloomFilterMemory.cs",
"chars": 893,
"preview": "using BloomFilter;\nusing System;\n\nnamespace Demo\n{\n public class BloomFilterMemory\n {\n [Test(\"Sample In Me"
},
{
"path": "test/Demo/BloomFilterRedis.cs",
"chars": 973,
"preview": "using BloomFilter.Redis;\nusing BloomFilter;\nusing System;\n\nnamespace Demo\n{\n public class BloomFilterRedis\n {\n "
},
{
"path": "test/Demo/Demo.csproj",
"chars": 360,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <OutputType>Exe</OutputType>\n <TargetFramework>net10.0</Tar"
},
{
"path": "test/Demo/Program.cs",
"chars": 268,
"preview": "using System;\nusing System.Text;\n\nnamespace Demo\n{\n class Program\n {\n static void Main(string[] args)\n "
},
{
"path": "test/Demo/TestExcute.cs",
"chars": 7572,
"preview": "// ==++==\n//\n// Copyright (c) . All rights reserved.\n//\n// ==--==\n/* -------------------------------------------------"
},
{
"path": "test/PerformanceTest/GeneralPerformance.cs",
"chars": 4555,
"preview": "using BloomFilter;\nusing BloomFilter.FreeRedis;\nusing BloomFilter.Redis;\nusing FreeRedis;\nusing StackExchange.Redis;\nus"
},
{
"path": "test/PerformanceTest/HashErrRate.cs",
"chars": 2438,
"preview": "using BloomFilter;\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Text;\n\nnamesp"
},
{
"path": "test/PerformanceTest/HashSpeed.cs",
"chars": 2433,
"preview": "using BloomFilter;\nusing BloomFilter.HashAlgorithms;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;"
},
{
"path": "test/PerformanceTest/Helper.cs",
"chars": 6313,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing System.Runtime.Inter"
},
{
"path": "test/PerformanceTest/Issues_2.cs",
"chars": 891,
"preview": "using BloomFilter;\nusing BloomFilter.Redis;\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nu"
},
{
"path": "test/PerformanceTest/PerformanceTest.csproj",
"chars": 456,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <OutputType>Exe</OutputType>\n <TargetFramework>net10.0</Tar"
},
{
"path": "test/PerformanceTest/Program.cs",
"chars": 278,
"preview": "using System;\nusing System.Text;\n\nnamespace PerformanceTest\n{\n class Program\n {\n static void Main(string[]"
},
{
"path": "test/PerformanceTest/TestExcute.cs",
"chars": 7572,
"preview": "// ==++==\n//\n// Copyright (c) . All rights reserved.\n//\n// ==--==\n/* -------------------------------------------------"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the vla/BloomFilter.NetCore GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 147 files (1.1 MB), approximately 474.2k tokens, and a symbol index with 983 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.