Skip to content

Commit

Permalink
chore: code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
SteveRuble committed Sep 26, 2021
1 parent 7a87dcb commit a94da2f
Show file tree
Hide file tree
Showing 28 changed files with 549 additions and 531 deletions.
4 changes: 2 additions & 2 deletions src/Bloomn/AssemblyAttributes.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
using System.Runtime.CompilerServices;


[assembly:System.Runtime.CompilerServices.InternalsVisibleTo("Bloomn.Tests")]
[assembly: InternalsVisibleTo("Bloomn.Tests")]
60 changes: 31 additions & 29 deletions src/Bloomn/BloomFilterBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ public interface IBloomFilterOptionsBuilder<TKey>
IBloomFilterBuilder<TKey> WithScaling(double capacityScaling = 2, double errorRateScaling = 0.8);
IBloomFilterBuilder<TKey> WithHasher(IKeyHasherFactory<TKey> hasherFactory);
}
public interface IBloomFilterBuilder<TKey>: IBloomFilterOptionsBuilder<TKey>

public interface IBloomFilterBuilder<TKey> : IBloomFilterOptionsBuilder<TKey>
{
IBloomFilterBuilder<TKey> WithOptions(BloomFilterOptions<TKey> options);
IBloomFilterBuilder<TKey> WithProfile(string profile);
Expand All @@ -24,21 +24,22 @@ public interface IBloomFilterBuilder<TKey>: IBloomFilterOptionsBuilder<TKey>
internal class BloomFilterBuilder<TKey> : IBloomFilterBuilder<TKey>
{
private readonly IOptionsSnapshot<BloomFilterOptions<TKey>>? _optionsSnapshot;
internal BloomFilterOptions<TKey> Options { get; set; }

internal BloomFilterState? State { get; set; }

public BloomFilterBuilder(IOptionsSnapshot<BloomFilterOptions<TKey>> options)
{
_optionsSnapshot = options;
Options = options.Value;
}

public BloomFilterBuilder(BloomFilterOptions<TKey> options)
{
Options = options;
}

internal BloomFilterOptions<TKey> Options { get; set; }

internal BloomFilterState? State { get; set; }

public IBloomFilterBuilder<TKey> WithCapacityAndErrorRate(int capacity, double errorRate)
{
return WithDimensions(BloomFilterDimensions.ForCapacityAndErrorRate(capacity, errorRate));
Expand All @@ -53,13 +54,13 @@ public IBloomFilterBuilder<TKey> WithDimensions(BloomFilterDimensions dimensions
BitCount = dimensions.BitCount,
HashCount = dimensions.HashCount
};

return this;
}

public IBloomFilterBuilder<TKey> WithScaling(double capacityScaling = 2, double errorRateScaling = 0.8)
{
Options.Scaling = new BloomFilterScaling()
Options.Scaling = new BloomFilterScaling
{
MaxCapacityBehavior = MaxCapacityBehavior.Scale,
CapacityScaling = capacityScaling,
Expand All @@ -86,32 +87,17 @@ public IBloomFilterBuilder<TKey> WithProfile(string profile)
{
throw new InvalidOperationException("This builder was not ");
}

Options = _optionsSnapshot.Get(profile);
return this;
}

public IBloomFilterBuilder<TKey> WithState(string? serializedState)
{
if (serializedState == null)
{
return this;
}

var state = JsonSerializer.Deserialize<BloomFilterState>(serializedState);
if (state == null)
{
throw new ArgumentException("Serialized state deserialized to null.", nameof(serializedState));
}

return WithState(state);
}

public IBloomFilterBuilder<TKey> WithState(BloomFilterState state)
{
State = state;
return this;
}

public IBloomFilter<TKey> Build()
{
var id = State?.Parameters?.Id ?? Guid.NewGuid().ToString();
Expand All @@ -120,7 +106,7 @@ public IBloomFilter<TKey> Build()
{
Dimensions = Options.GetDimensions(),
Scaling = Options.Scaling,
HashAlgorithm = Options.GetHasher().Algorithm,
HashAlgorithm = Options.GetHasher().Algorithm
};

var state = State;
Expand All @@ -138,7 +124,7 @@ public IBloomFilter<TKey> Build()
state = null;
}

throw new InvalidOperationException($"When state containing parameters are provided it must be consistent with the configured parameters. " +
throw new InvalidOperationException("When state containing parameters are provided it must be consistent with the configured parameters. " +
$"Configured parameters: {configuredParameters}; " +
$"Parameters from state: {parametersFromState}; " +
$"Inconsistencies: {string.Join(", ", inconsistencies)}");
Expand All @@ -148,7 +134,7 @@ public IBloomFilter<TKey> Build()

if (state == null)
{
state = new BloomFilterState()
state = new BloomFilterState
{
Parameters = configuredParameters
};
Expand All @@ -164,7 +150,23 @@ public IBloomFilter<TKey> Build()
return new ScalingBloomFilter<TKey>(Options, state);
}

return new ClassicBloomFilter<TKey>(Options, state);
return new FixedSizeBloomFilter<TKey>(Options, state);
}

public IBloomFilterBuilder<TKey> WithState(string? serializedState)
{
if (serializedState == null)
{
return this;
}

var state = JsonSerializer.Deserialize<BloomFilterState>(serializedState);
if (state == null)
{
throw new ArgumentException("Serialized state deserialized to null.", nameof(serializedState));
}

return WithState(state);
}
}
}
26 changes: 20 additions & 6 deletions src/Bloomn/BloomFilterCheckRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ public BloomFilterKey(string key)
Bytes = MemoryMarshal.AsBytes(key.AsSpan());
}

public static implicit operator BloomFilterKey(string s) => new BloomFilterKey(s);
public static implicit operator BloomFilterKey(string s)
{
return new(s);
}
}

public enum BloomFilterCheckBehavior
Expand All @@ -21,16 +24,27 @@ public enum BloomFilterCheckBehavior
PrepareForAdd,
AddImmediately
}

public readonly ref struct BloomFilterCheckRequest<T>
{
public readonly T Key;
public readonly BloomFilterCheckBehavior Behavior;

public static BloomFilterCheckRequest<T> CheckOnly(T key) => new BloomFilterCheckRequest<T>(key, BloomFilterCheckBehavior.CheckOnly);
public static BloomFilterCheckRequest<T> PrepareForAdd(T key) => new BloomFilterCheckRequest<T>(key, BloomFilterCheckBehavior.PrepareForAdd);
public static BloomFilterCheckRequest<T> AddImmediately(T key) => new BloomFilterCheckRequest<T>(key, BloomFilterCheckBehavior.AddImmediately);

public static BloomFilterCheckRequest<T> CheckOnly(T key)
{
return new(key, BloomFilterCheckBehavior.CheckOnly);
}

public static BloomFilterCheckRequest<T> PrepareForAdd(T key)
{
return new(key, BloomFilterCheckBehavior.PrepareForAdd);
}

public static BloomFilterCheckRequest<T> AddImmediately(T key)
{
return new(key, BloomFilterCheckBehavior.AddImmediately);
}

public BloomFilterCheckRequest(T key, BloomFilterCheckBehavior behavior)
{
Key = key;
Expand Down
105 changes: 59 additions & 46 deletions src/Bloomn/BloomFilterDimensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;

namespace Bloomn
Expand All @@ -15,41 +14,6 @@ public interface IBloomFilterDimensions

public record BloomFilterDimensions : IBloomFilterDimensions
{
/// <summary>
/// These are the equations which relate the bloom filter parameters.
/// n => max items before invariants are broken
/// m => number of bits
/// k => number of hashes
/// p => false positive rate
/// </summary>
internal static class Equations
{
// ReSharper disable InconsistentNaming

// n = ceil(m / (-k / log(1 - exp(log(p) / k))))
// p = pow(1 - exp(-k / (m / n)), k)
// m = ceil((n * log(p)) / log(1 / pow(2, log(2))));
// k = round((m / n) * log(2));


public static int n(int m, int k, double p) => (int) Math.Ceiling(m / (-k / Math.Log(1 - Math.Exp(Math.Log(p) / k))));

public static double p(int m, int n, int k) => Math.Pow(1 - Math.Exp(-k / (m / (double) n)), k);

public static int m(int n, double p) => (int) Math.Ceiling((n * Math.Log(p)) / Math.Log(1 / Math.Pow(2, Math.Log(2))));

public static int k(int m, int n) => (int) Math.Round((m / (double) n) * Math.Log(2));

public static int k(double p) => (int)Math.Round(-Math.Log2(p));

// ReSharper restore InconsistentNaming
}

public double FalsePositiveProbability { get; init; }
public int Capacity { get; init; }
public int BitCount { get; init; }
public int HashCount { get; init; }

public BloomFilterDimensions(double falsePositiveProbability = 0.01, int capacity = 10000, int bitCount = 95851, int hashCount = 7)
{
if (hashCount < 2)
Expand All @@ -63,11 +27,16 @@ public BloomFilterDimensions(double falsePositiveProbability = 0.01, int capacit
HashCount = hashCount;
}

public double FalsePositiveProbability { get; init; }
public int Capacity { get; init; }
public int BitCount { get; init; }
public int HashCount { get; init; }

public static BloomFilterDimensions ForCapacityAndErrorRate(int capacity, double errorRate)
{
return new BloomFilterDimensionsBuilder()
return new BloomFilterDimensionsBuilder
{
Capacity = capacity,
Capacity = capacity,
FalsePositiveProbability = errorRate
}.Build();
}
Expand Down Expand Up @@ -120,6 +89,51 @@ public List<string> Diff(BloomFilterDimensions other)

return diff;
}

/// <summary>
/// These are the equations which relate the bloom filter parameters.
/// n => max items before invariants are broken
/// m => number of bits
/// k => number of hashes
/// p => false positive rate
/// </summary>
internal static class Equations
{
// ReSharper disable InconsistentNaming

// n = ceil(m / (-k / log(1 - exp(log(p) / k))))
// p = pow(1 - exp(-k / (m / n)), k)
// m = ceil((n * log(p)) / log(1 / pow(2, log(2))));
// k = round((m / n) * log(2));


public static int n(int m, int k, double p)
{
return (int) Math.Ceiling(m / (-k / Math.Log(1 - Math.Exp(Math.Log(p) / k))));
}

public static double p(int m, int n, int k)
{
return Math.Pow(1 - Math.Exp(-k / (m / (double) n)), k);
}

public static int m(int n, double p)
{
return (int) Math.Ceiling(n * Math.Log(p) / Math.Log(1 / Math.Pow(2, Math.Log(2))));
}

public static int k(int m, int n)
{
return (int) Math.Round(m / (double) n * Math.Log(2));
}

public static int k(double p)
{
return (int) Math.Round(-Math.Log2(p));
}

// ReSharper restore InconsistentNaming
}
}

public class BloomFilterDimensionsBuilder
Expand All @@ -136,11 +150,11 @@ public class BloomFilterDimensionsBuilder
public bool FullySpecified => FalsePositiveProbability != null && Capacity != null && BitCount != null && HashCount != null;

public bool Buildable =>
(Capacity.HasValue && FalsePositiveProbability.HasValue)
|| (FalsePositiveProbability.HasValue && BitCount.HasValue)
|| (Capacity.HasValue && FalsePositiveProbability.HasValue)
|| (Capacity.HasValue && BitCount.HasValue)
|| (FalsePositiveProbability.HasValue && BitCount.HasValue);
Capacity.HasValue && FalsePositiveProbability.HasValue
|| FalsePositiveProbability.HasValue && BitCount.HasValue
|| Capacity.HasValue && FalsePositiveProbability.HasValue
|| Capacity.HasValue && BitCount.HasValue
|| FalsePositiveProbability.HasValue && BitCount.HasValue;

public BloomFilterDimensions Build()
{
Expand All @@ -158,8 +172,8 @@ public BloomFilterDimensions Build()
HashCount = BloomFilterDimensions.Equations.k(BitCount.Value, Capacity.Value);
makingProgress = true;
continue;
}
}

if (!HashCount.HasValue && FalsePositiveProbability.HasValue)
{
HashCount = BloomFilterDimensions.Equations.k(FalsePositiveProbability.Value);
Expand All @@ -185,7 +199,6 @@ public BloomFilterDimensions Build()
{
FalsePositiveProbability = BloomFilterDimensions.Equations.p(BitCount.Value, Capacity.Value, HashCount.Value);
makingProgress = true;
continue;
}
}

Expand Down
12 changes: 8 additions & 4 deletions src/Bloomn/BloomFilterEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ namespace Bloomn
{
public readonly struct BloomFilterEntry : IDisposable
{
public static readonly BloomFilterEntry MaybePresent = new BloomFilterEntry(false, PreparedAdd.AlreadyAdded);
public static readonly BloomFilterEntry NotPresent = new BloomFilterEntry(true, PreparedAdd.AlreadyAdded);
public static BloomFilterEntry Addable(PreparedAdd preparedAdd) => new BloomFilterEntry(true, preparedAdd);

public static readonly BloomFilterEntry MaybePresent = new(false, PreparedAdd.AlreadyAdded);
public static readonly BloomFilterEntry NotPresent = new(true, PreparedAdd.AlreadyAdded);

public static BloomFilterEntry Addable(PreparedAdd preparedAdd)
{
return new(true, preparedAdd);
}

public readonly bool IsNotPresent;
public readonly PreparedAdd PreparedAdd;

Expand Down
Loading

0 comments on commit a94da2f

Please sign in to comment.