speedups maybe
changed Set function and Find(routing)Index) to specialize on class (no virtual dispatch) or using generics.
This commit is contained in:
parent
a2458e727a
commit
7ee2238248
2 changed files with 21 additions and 18 deletions
|
|
@ -1,4 +1,3 @@
|
||||||
using System.Numerics;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|
@ -42,27 +41,28 @@ namespace PersistentOrderedMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Node<K> Set<K, V>(Node<K> root, K key, V value, IKeyStrategy<K> strategy, OwnerId owner, out bool countChanged)
|
public static Node<K> Set<K, V, TStrategy>(Node<K> root, K key, V value, TStrategy strategy, OwnerId owner, out bool countChanged)
|
||||||
|
where TStrategy : IKeyStrategy<K>
|
||||||
{
|
{
|
||||||
root = root.EnsureEditable(owner);
|
root = root.EnsureEditable(owner);
|
||||||
|
|
||||||
// Todo, this should really be made a tuple return value to not stress the GC
|
// Todo, this should really be made a tuple return value to not stress the GC
|
||||||
var splitResult = InsertRecursive(root, key, value, strategy, owner, out countChanged);
|
var (newNode, sep) = InsertRecursive(root, key, value, strategy, owner, out countChanged);
|
||||||
|
|
||||||
if (splitResult != null)
|
if (newNode != null)
|
||||||
{
|
{
|
||||||
var newRoot = strategy.UsesPrefixes
|
var newRoot = strategy.UsesPrefixes
|
||||||
? new PrefixInternalNode<K>(owner)
|
? new PrefixInternalNode<K>(owner)
|
||||||
: new InternalNode<K>(owner);
|
: new InternalNode<K>(owner);
|
||||||
|
|
||||||
newRoot.Keys[0] = splitResult.Separator;
|
newRoot.Keys[0] = sep;
|
||||||
newRoot.Children[0] = root;
|
newRoot.Children[0] = root;
|
||||||
newRoot.Children[1] = splitResult.NewNode;
|
newRoot.Children[1] = newNode;
|
||||||
newRoot.SetCount(1);
|
newRoot.SetCount(1);
|
||||||
|
|
||||||
if (strategy.UsesPrefixes)
|
if (strategy.UsesPrefixes)
|
||||||
{
|
{
|
||||||
newRoot.AllPrefixes[0] = strategy.GetPrefix(splitResult.Separator);
|
newRoot.AllPrefixes[0] = strategy.GetPrefix(sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newRoot;
|
return newRoot;
|
||||||
|
|
@ -71,7 +71,7 @@ namespace PersistentOrderedMap
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SplitResult<K>? InsertRecursive<K, V>(Node<K> node, K key, V value, IKeyStrategy<K> strategy, OwnerId owner, out bool added)
|
private static (Node<K>? newNode, K separator ) InsertRecursive<K, V>(Node<K> node, K key, V value, IKeyStrategy<K> strategy, OwnerId owner, out bool added)
|
||||||
{
|
{
|
||||||
long keyPrefix = strategy.UsesPrefixes ? strategy.GetPrefix(key) : 0;
|
long keyPrefix = strategy.UsesPrefixes ? strategy.GetPrefix(key) : 0;
|
||||||
|
|
||||||
|
|
@ -84,14 +84,14 @@ namespace PersistentOrderedMap
|
||||||
{
|
{
|
||||||
leaf.Values[index] = value;
|
leaf.Values[index] = value;
|
||||||
added = false;
|
added = false;
|
||||||
return null;
|
return (null, default);
|
||||||
}
|
}
|
||||||
|
|
||||||
added = true;
|
added = true;
|
||||||
if (leaf.Header.Count < LeafNode<K, V>.Capacity)
|
if (leaf.Header.Count < LeafNode<K, V>.Capacity)
|
||||||
{
|
{
|
||||||
InsertIntoLeaf(leaf, index, key, value, strategy);
|
InsertIntoLeaf(leaf, index, key, value, strategy);
|
||||||
return null;
|
return (null, default);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -106,21 +106,21 @@ namespace PersistentOrderedMap
|
||||||
var child = internalNode.Children[index]!.EnsureEditable(owner);
|
var child = internalNode.Children[index]!.EnsureEditable(owner);
|
||||||
internalNode.Children[index] = child;
|
internalNode.Children[index] = child;
|
||||||
|
|
||||||
var split = InsertRecursive(child, key, value, strategy, owner, out added);
|
var (newNode, sep) = InsertRecursive(child, key, value, strategy, owner, out added);
|
||||||
|
|
||||||
if (split != null)
|
if (newNode != null)
|
||||||
{
|
{
|
||||||
if (internalNode.Header.Count < InternalNode<K>.Capacity - 1)
|
if (internalNode.Header.Count < InternalNode<K>.Capacity - 1)
|
||||||
{
|
{
|
||||||
InsertIntoInternal(internalNode, index, split.Separator, split.NewNode, strategy);
|
InsertIntoInternal(internalNode, index, sep, newNode, strategy);
|
||||||
return null;
|
return (null, default);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return SplitInternal(internalNode, index, split.Separator, split.NewNode, strategy, owner);
|
return SplitInternal(internalNode, index, sep, newNode, strategy, owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return (null, default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -189,7 +189,7 @@ namespace PersistentOrderedMap
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static int FindIndex<K, TStrategy>(Node<K> node, K key, long keyPrefix, TStrategy strategy)
|
internal static int FindIndex<K,V, TStrategy>(LeafNode<K,V> node, K key, long keyPrefix, TStrategy strategy)
|
||||||
where TStrategy : IKeyStrategy<K>
|
where TStrategy : IKeyStrategy<K>
|
||||||
{
|
{
|
||||||
if (typeof(K) == typeof(int))
|
if (typeof(K) == typeof(int))
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,9 @@ where TStrategy : IKeyStrategy<K>
|
||||||
|
|
||||||
// Fixed-size buffer for the path.
|
// Fixed-size buffer for the path.
|
||||||
// Depth 16 * 32 (branching factor) = Exabytes of capacity.
|
// Depth 16 * 32 (branching factor) = Exabytes of capacity.
|
||||||
|
// The B tree is, theoretically, not limited by the size of an int, like
|
||||||
|
// all int-indexed data structures (or bit partitioned ones).
|
||||||
|
// This should be enough for anyone.
|
||||||
[InlineArray(16)]
|
[InlineArray(16)]
|
||||||
internal struct IterNodeBuffer<K>
|
internal struct IterNodeBuffer<K>
|
||||||
{
|
{
|
||||||
|
|
@ -138,7 +141,7 @@ public struct BTreeEnumerator<K, V, TStrategy> : IEnumerator<KeyValuePair<K, V>>
|
||||||
|
|
||||||
// Find index in Leaf
|
// Find index in Leaf
|
||||||
_currentLeaf = node.AsLeaf<V>();
|
_currentLeaf = node.AsLeaf<V>();
|
||||||
int index = BTreeFunctions.FindIndex<K, TStrategy>(_currentLeaf, key, keyPrefix, _strategy);
|
int index = BTreeFunctions.FindIndex<K,V, TStrategy>(_currentLeaf, key, keyPrefix, _strategy);
|
||||||
|
|
||||||
// Set position to (index - 1) so that the first MoveNext() lands on 'index'
|
// Set position to (index - 1) so that the first MoveNext() lands on 'index'
|
||||||
_currentLeafIndex = index - 1;
|
_currentLeafIndex = index - 1;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue