Skip to content

Commit

Permalink
experiments with the Enumerate and custom Enumerator
Browse files Browse the repository at this point in the history
  • Loading branch information
maximv committed Nov 24, 2020
1 parent d45635b commit 2065a98
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 57 deletions.
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ for:
- image: Visual Studio 2019

build_script:
- build.bat
- build_with_packaging.bat

artifacts:
- path: .\.dist\packages\*.nupkg
7 changes: 0 additions & 7 deletions build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,6 @@ if %ERRORLEVEL% neq 0 goto :error
echo:
echo:## Finished: TESTS

echo:
echo:## Starting: SOURCE PACKAGING...
echo:
call BuildScripts\NugetPack.bat
if %ERRORLEVEL% neq 0 goto :error
echo:
echo:## Finished: SOURCE PACKAGING
echo:
echo:## Finished: ALL ##
echo:
Expand Down
7 changes: 7 additions & 0 deletions build_no_packaging.bat → build_with_packaging.bat
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ if %ERRORLEVEL% neq 0 goto :error
echo:
echo:## Finished: TESTS

echo:
echo:## Starting: SOURCE PACKAGING...
echo:
call BuildScripts\NugetPack.bat
if %ERRORLEVEL% neq 0 goto :error
echo:
echo:## Finished: SOURCE PACKAGING
echo:
echo:## Finished: ALL ##
echo:
Expand Down
25 changes: 12 additions & 13 deletions playground/ImTools.Benchmarks/ImHashMapBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1444,20 +1444,19 @@ public class Enumerate
### Array instead of List
| Method | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|----------------------------------------- |------ |---------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:|
| V2_ImHashMap_AVL_EnumerateAndToArray | 10 | 649.9 ns | 29.18 ns | 84.19 ns | 1.00 | 0.00 | 0.1125 | - | - | 472 B |
| V3_ImHashMap_234Tree_EnumerateAndToArray | 10 | 871.5 ns | 17.01 ns | 18.90 ns | 1.41 | 0.10 | 0.1278 | - | - | 536 B |
| Method | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|----------------------------------------- |------ |---------:|--------:|--------:|------:|--------:|-------:|------:|------:|----------:|
| V2_ImHashMap_AVL_EnumerateAndToArray | 9 | 524.8 ns | 7.52 ns | 6.28 ns | 1.00 | 0.00 | 0.1087 | - | - | 456 B |
| V3_ImHashMap_234Tree_EnumerateAndToArray | 9 | 586.4 ns | 7.62 ns | 7.13 ns | 1.12 | 0.02 | 0.1163 | - | - | 488 B |
*/
[Params(10)]//, 5, 10, 100, 1_000)]// the 1000 does not add anything as the LookupKey stored higher in the tree, 1000)]
[Params(9)]//, 5, 10, 100, 1_000)]// the 1000 does not add anything as the LookupKey stored higher in the tree, 1000)]
public int Count;

[GlobalSetup]
public void Populate()
{
_map = AddOrUpdate();
_mapV1 = AddOrUpdate_v1();
_mapExp = Experimental_ImHashMap_AddOrUpdate();
_map234 = V3_ImHashMap_234Tree_AddOrUpdate();
_mapSlots = ImHashMapSlots_AddOrUpdate();
Expand All @@ -1476,7 +1475,7 @@ public ImHashMap<Type, string> AddOrUpdate()
foreach (var key in _keys.Take(Count))
map = map.AddOrUpdate(key, "a");

map = map.AddOrUpdate(typeof(ImHashMapBenchmarks), "!");
// map = map.AddOrUpdate(typeof(ImHashMapBenchmarks), "!");
return map;
}

Expand Down Expand Up @@ -1515,7 +1514,7 @@ public ImHashMap<Type, string>[] ImHashMapSlots_AddOrUpdate()
foreach (var key in _keys.Take(Count))
map = map.AddOrUpdate(key.GetHashCode(), key, "a");

return map.AddOrUpdate(typeof(ImHashMapBenchmarks).GetHashCode(), typeof(ImHashMapBenchmarks), "!");
return map;//.AddOrUpdate(typeof(ImHashMapBenchmarks).GetHashCode(), typeof(ImHashMapBenchmarks), "!");
}

private ImTools.Experimental.ImHashMap234<Type, string> _map234;
Expand All @@ -1527,7 +1526,7 @@ public ImTools.Experimental.ImHashMap234<Type, string> V3_ImHashMap_234Tree_AddO
foreach (var key in _keys.Take(Count))
map = map.AddOrUpdate(key.GetHashCode(), key, "a");

return map.AddOrUpdate(typeof(ImHashMapBenchmarks).GetHashCode(), typeof(ImHashMapBenchmarks), "!");
return map;//.AddOrUpdate(typeof(ImHashMapBenchmarks).GetHashCode(), typeof(ImHashMapBenchmarks), "!");
}

private ImHashMap<Type, string>[] _mapSlots;
Expand All @@ -1539,7 +1538,7 @@ public Dictionary<Type, string> Dict()
foreach (var key in _keys.Take(Count))
map.TryAdd(key, "a");

map.TryAdd(typeof(ImHashMapBenchmarks), "!");
// map.TryAdd(typeof(ImHashMapBenchmarks), "!");

return map;
}
Expand All @@ -1553,7 +1552,7 @@ public DictionarySlim<TypeVal, string> DictSlim()
foreach (var key in _keys.Take(Count))
dict.GetOrAddValueRef(key) = "a";

dict.GetOrAddValueRef(typeof(ImHashMapBenchmarks)) = "!";
// dict.GetOrAddValueRef(typeof(ImHashMapBenchmarks)) = "!";
return dict;
}

Expand All @@ -1566,7 +1565,7 @@ public ConcurrentDictionary<Type, string> ConcurrentDict()
foreach (var key in _keys.Take(Count))
map.TryAdd(key, "a");

map.TryAdd(typeof(ImHashMapBenchmarks), "!");
// map.TryAdd(typeof(ImHashMapBenchmarks), "!");
return map;
}

Expand All @@ -1578,7 +1577,7 @@ public ImmutableDictionary<Type, string> ImmutableDict()

foreach (var key in _keys.Take(Count))
builder.Add(key, "a");
builder.Add(typeof(ImHashMapBenchmarks), "!");
// builder.Add(typeof(ImHashMapBenchmarks), "!");
return builder.ToImmutable();
}

Expand Down
4 changes: 2 additions & 2 deletions playground/ImTools.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ static void Main()
//BenchmarkRunner.Run<ImMapBenchmarks.LookupMissing>();
//BenchmarkRunner.Run<ImMapBenchmarks.Enumerate>();

BenchmarkRunner.Run<ImHashMapBenchmarks.Populate>();
// BenchmarkRunner.Run<ImHashMapBenchmarks.Populate>();
// BenchmarkRunner.Run<ImHashMapBenchmarks.Lookup>();
// BenchmarkRunner.Run<ImHashMapBenchmarks.Enumerate>();
BenchmarkRunner.Run<ImHashMapBenchmarks.Enumerate>();

// BenchmarkRunner.Run<ImHashMapBenchmarks_StringString.Populate>();
// BenchmarkRunner.Run<ImHashMapBenchmarks_StringString.Lookup>();
Expand Down
166 changes: 132 additions & 34 deletions src/ImTools/ImTools.ImHashMap234.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Collections;

namespace ImTools.Experimental
{
Expand Down Expand Up @@ -351,18 +352,59 @@ public override Entry GetEntryOrDefault(int hash) =>
/// <inheritdoc />
public override IEnumerable<ValueEntry> Enumerate()
{
if (Entry0 is ValueEntry v0)
yield return v0;
else foreach (var x in ((ConflictsEntry)Entry0).Conflicts)
yield return x;
if (Entry1 is ValueEntry v1)
yield return v1;
else foreach (var x in ((ConflictsEntry)Entry1).Conflicts)
yield return x;
if (Entry2 is ValueEntry v2)
yield return v2;
else foreach (var x in ((ConflictsEntry)Entry2).Conflicts)
yield return x;
return new Enumerable(this);

// if (Entry0 is ValueEntry v0)
// yield return v0;
// else foreach (var x in ((ConflictsEntry)Entry0).Conflicts)
// yield return x;
// if (Entry1 is ValueEntry v1)
// yield return v1;
// else foreach (var x in ((ConflictsEntry)Entry1).Conflicts)
// yield return x;
// if (Entry2 is ValueEntry v2)
// yield return v2;
// else foreach (var x in ((ConflictsEntry)Entry2).Conflicts)
// yield return x;
}


private readonly struct Enumerable : IEnumerable<ValueEntry>
{
private readonly Leaf3 _l;
public Enumerable(Leaf3 l) => _l = l;
public Enumerator GetEnumerator() => new Enumerator(_l, 0);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
IEnumerator<ValueEntry> IEnumerable<ValueEntry>.GetEnumerator() => GetEnumerator();
}

private struct Enumerator : IEnumerator<ValueEntry>
{
private readonly Leaf3 _l;
private byte _i;
public Enumerator(Leaf3 l, byte i)
{
_l = l;
_i = i;
}

public ValueEntry Current
{
[MethodImpl((MethodImplOptions)256)]
get
{
var i = _i;
return (ValueEntry)(
i == 1 ? _l.Entry0 :
i == 2 ? _l.Entry1 :
_l.Entry2);
}
}
object IEnumerator.Current => Current;
public bool MoveNext() => ++_i < 4;

public void Dispose() {}
public void Reset() => _i = 0;
}

/// <inheritdoc />
Expand Down Expand Up @@ -450,7 +492,6 @@ public override IEnumerable<ValueEntry> Enumerate()
var e1 = l.Entry1;
var e2 = l.Entry2;

// [2*, 3, 4]
if (ph < e0.Hash)
{
if (p is ValueEntry v)
Expand Down Expand Up @@ -707,7 +748,7 @@ public override ImHashMap234<K, V> RemoveEntry(int hash, K key)
}

/// <summary>Leaf with 5 entries</summary>
public sealed class Leaf5 : ImHashMap234<K, V>
public sealed class Leaf5 : ImHashMap234<K, V>, IEnumerable<ValueEntry>
{
/// <summary>Left entry</summary>
public readonly Entry Entry0;
Expand Down Expand Up @@ -751,26 +792,75 @@ public override Entry GetEntryOrDefault(int hash) =>
/// <inheritdoc />
public override IEnumerable<ValueEntry> Enumerate()
{
if (Entry0 is ValueEntry v0)
yield return v0;
else foreach (var x in ((ConflictsEntry)Entry0).Conflicts)
yield return x;
if (Entry1 is ValueEntry v1)
yield return v1;
else foreach (var x in ((ConflictsEntry)Entry1).Conflicts)
yield return x;
if (Entry2 is ValueEntry v2)
yield return v2;
else foreach (var x in ((ConflictsEntry)Entry2).Conflicts)
yield return x;
if (Entry3 is ValueEntry v3)
yield return v3;
else foreach (var x in ((ConflictsEntry)Entry3).Conflicts)
yield return x;
if (Entry4 is ValueEntry v4)
yield return v4;
else foreach (var x in ((ConflictsEntry)Entry4).Conflicts)
yield return x;
return this;
// if (Entry0 is ValueEntry v0)
// yield return v0;
// else foreach (var x in ((ConflictsEntry)Entry0).Conflicts)
// yield return x;
// if (Entry1 is ValueEntry v1)
// yield return v1;
// else foreach (var x in ((ConflictsEntry)Entry1).Conflicts)
// yield return x;
// if (Entry2 is ValueEntry v2)
// yield return v2;
// else foreach (var x in ((ConflictsEntry)Entry2).Conflicts)
// yield return x;
// if (Entry3 is ValueEntry v3)
// yield return v3;
// else foreach (var x in ((ConflictsEntry)Entry3).Conflicts)
// yield return x;
// if (Entry4 is ValueEntry v4)
// yield return v4;
// else foreach (var x in ((ConflictsEntry)Entry4).Conflicts)
// yield return x;
}

/// <summary>Returns the left-to-right enumerator</summary>
public IEnumerator<ValueEntry> GetEnumerator() => new Enumerator(this);
IEnumerator<ValueEntry> IEnumerable<ValueEntry>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

private struct Enumerator : IEnumerator<ValueEntry>
{
private readonly Leaf5 _m;
private byte _i, _j;
public Enumerator(Leaf5 m)
{
_m = m;
_i = 0;
_j = 0;
Current = null;
}

public ValueEntry Current { get; private set; }
object IEnumerator.Current => Current;
public bool MoveNext()
{
for (var i = _i; i < 5; ++_i)
{
var e = i == 0 ? _m.Entry0 : i == 1 ? _m.Entry1 : i == 2 ? _m.Entry2 : i == 3 ? _m.Entry3 : _m.Entry4;
if (_j == 0 && e is ValueEntry v0)
{
Current = v0;
++_i;
return true;
}

var ee = ((ConflictsEntry)e).Conflicts;
if (_j < (uint)ee.Length)
{
Current = ee[_j++];
return true;
}

_j = 0;
}

return false;
}

public void Dispose() {}
public void Reset() {}
}

/// <inheritdoc />
Expand Down Expand Up @@ -2123,4 +2213,12 @@ public static void AddOrUpdate<K, V>(this ImHashMap234<K, V>[] parts, K key, V v
public static void RefAddOrUpdatePart<K, V>(ref ImHashMap234<K, V> part, int hash, K key, V value) =>
Ref.Swap(ref part, hash, key, value, (x, h, k, v) => x.AddOrUpdate(h, k, v));
}

/// <summary>Funny enumerable</summary>
public interface IEnumerable<out T, out TEnumerator> : IEnumerable<T>
where TEnumerator : IEnumerator<T>
{
/// <summary>Funny enumerator</summary>
new TEnumerator GetEnumerator();
}
}

0 comments on commit 2065a98

Please sign in to comment.