From db5f899dc06fd2fe64b46be2adef9a68e8f35be1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Ma=C5=82ota-W=C3=B3jcik?= <59281144+outofforest@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:40:12 +0200 Subject: [PATCH] Pass node allocators by pointers (#59) --- alloc/allocator.go | 4 ++-- benchmark_test.go | 2 +- db.go | 10 +++++----- list/alloc.go | 16 ++++++++-------- list/list.go | 2 +- list/list_test.go | 2 +- space/alloc.go | 22 +++++++++++----------- space/space.go | 4 ++-- space/space_test.go | 7 +++---- 9 files changed, 34 insertions(+), 35 deletions(-) diff --git a/alloc/allocator.go b/alloc/allocator.go index 0b1d98a..a82c4da 100644 --- a/alloc/allocator.go +++ b/alloc/allocator.go @@ -147,7 +147,7 @@ func NewSnapshotAllocator( allocator types.Allocator, deallocationListCache map[types.SnapshotID]ListToCommit, availableSnapshots map[types.SnapshotID]struct{}, - listNodeAllocator list.NodeAllocator, + listNodeAllocator *list.NodeAllocator, ) *SnapshotAllocator { sa := &SnapshotAllocator{ allocator: allocator, @@ -166,7 +166,7 @@ type SnapshotAllocator struct { immediateAllocator types.SnapshotAllocator deallocationListCache map[types.SnapshotID]ListToCommit availableSnapshots map[types.SnapshotID]struct{} - listNodeAllocator list.NodeAllocator + listNodeAllocator *list.NodeAllocator } // SnapshotID returns snapshot ID. diff --git a/benchmark_test.go b/benchmark_test.go index bcbb299..173e24f 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -17,7 +17,7 @@ import ( func BenchmarkBalanceTransfer(b *testing.B) { const ( spaceID = 0x00 - numOfAddresses = 50_000_000 + numOfAddresses = 10_000_000 txsPerCommit = 2000 balance = 100_000 ) diff --git a/db.go b/db.go index 7cd57e7..e44d369 100644 --- a/db.go +++ b/db.go @@ -130,11 +130,11 @@ type DB struct { spaces *space.Space[types.SpaceID, types.SpaceInfo] deallocationLists *space.Space[types.SnapshotID, types.NodeAddress] - pointerNodeAllocator space.NodeAllocator[types.Pointer] - snapshotInfoNodeAllocator space.NodeAllocator[types.DataItem[types.SnapshotID, types.SnapshotInfo]] - spaceInfoNodeAllocator space.NodeAllocator[types.DataItem[types.SpaceID, types.SpaceInfo]] - snapshotToNodeNodeAllocator space.NodeAllocator[types.DataItem[types.SnapshotID, types.NodeAddress]] - listNodeAllocator list.NodeAllocator + pointerNodeAllocator *space.NodeAllocator[types.Pointer] + snapshotInfoNodeAllocator *space.NodeAllocator[types.DataItem[types.SnapshotID, types.SnapshotInfo]] + spaceInfoNodeAllocator *space.NodeAllocator[types.DataItem[types.SpaceID, types.SpaceInfo]] + snapshotToNodeNodeAllocator *space.NodeAllocator[types.DataItem[types.SnapshotID, types.NodeAddress]] + listNodeAllocator *list.NodeAllocator spacesToCommit map[types.SpaceID]SpaceToCommit deallocationListsToCommit map[types.SnapshotID]alloc.ListToCommit diff --git a/list/alloc.go b/list/alloc.go index 6f19985..a81eac0 100644 --- a/list/alloc.go +++ b/list/alloc.go @@ -10,21 +10,21 @@ import ( ) // NewNodeAllocator creates new list node allocator. -func NewNodeAllocator(allocator types.Allocator) (NodeAllocator, error) { +func NewNodeAllocator(allocator types.Allocator) (*NodeAllocator, error) { nodeSize := allocator.NodeSize() headerSize := uint64(unsafe.Sizeof(types.ListNodeHeader{})) headerSize = (headerSize + types.UInt64Length - 1) / types.UInt64Length * types.UInt64Length // memory alignment if headerSize >= nodeSize { - return NodeAllocator{}, errors.New("node size is too small") + return nil, errors.New("node size is too small") } numOfItems := (nodeSize - headerSize) / types.UInt64Length if numOfItems < 2 { - return NodeAllocator{}, errors.New("node size is too small") + return nil, errors.New("node size is too small") } - return NodeAllocator{ + return &NodeAllocator{ allocator: allocator, numOfItems: int(numOfItems), itemOffset: headerSize, @@ -40,12 +40,12 @@ type NodeAllocator struct { } // Get returns object for node. -func (na NodeAllocator) Get(nodeAddress types.NodeAddress) types.ListNode { +func (na *NodeAllocator) Get(nodeAddress types.NodeAddress) types.ListNode { return na.project(na.allocator.Node(nodeAddress)) } // Allocate allocates new object. -func (na NodeAllocator) Allocate(allocator types.SnapshotAllocator) (types.NodeAddress, types.ListNode, error) { +func (na *NodeAllocator) Allocate(allocator types.SnapshotAllocator) (types.NodeAddress, types.ListNode, error) { n, node, err := allocator.Allocate() if err != nil { return 0, types.ListNode{}, err @@ -54,7 +54,7 @@ func (na NodeAllocator) Allocate(allocator types.SnapshotAllocator) (types.NodeA } // Copy allocates copy of existing object. -func (na NodeAllocator) Copy( +func (na *NodeAllocator) Copy( allocator types.SnapshotAllocator, nodeAddress types.NodeAddress, ) (types.NodeAddress, types.ListNode, error) { @@ -65,7 +65,7 @@ func (na NodeAllocator) Copy( return n, na.project(node), nil } -func (na NodeAllocator) project(node unsafe.Pointer) types.ListNode { +func (na *NodeAllocator) project(node unsafe.Pointer) types.ListNode { return types.ListNode{ Header: photon.FromPointer[types.ListNodeHeader](node), Items: photon.SliceFromPointer[types.NodeAddress](unsafe.Add(node, na.itemOffset), na.numOfItems), diff --git a/list/list.go b/list/list.go index fd26671..d7e6de0 100644 --- a/list/list.go +++ b/list/list.go @@ -9,7 +9,7 @@ import ( // Config stores list configuration. type Config struct { Item *types.NodeAddress - NodeAllocator NodeAllocator + NodeAllocator *NodeAllocator Allocator types.SnapshotAllocator } diff --git a/list/list_test.go b/list/list_test.go index efbc6e5..cff59ae 100644 --- a/list/list_test.go +++ b/list/list_test.go @@ -240,7 +240,7 @@ type env struct { snapshotID types.SnapshotID snapshotAllocator types.SnapshotAllocator - nodeAllocator list.NodeAllocator + nodeAllocator *list.NodeAllocator } func (e *env) NextSnapshot() { diff --git a/space/alloc.go b/space/alloc.go index 2460334..8f0bf3d 100644 --- a/space/alloc.go +++ b/space/alloc.go @@ -10,13 +10,13 @@ import ( ) // NewNodeAllocator creates new space node allocator. -func NewNodeAllocator[T comparable](allocator types.Allocator) (NodeAllocator[T], error) { +func NewNodeAllocator[T comparable](allocator types.Allocator) (*NodeAllocator[T], error) { nodeSize := allocator.NodeSize() headerSize := uint64(unsafe.Sizeof(types.SpaceNodeHeader{})) headerSize = (headerSize + types.UInt64Length - 1) / types.UInt64Length * types.UInt64Length // memory alignment if headerSize >= allocator.NodeSize() { - return NodeAllocator[T]{}, errors.New("node size is too small") + return nil, errors.New("node size is too small") } spaceLeft := nodeSize - headerSize @@ -27,17 +27,17 @@ func NewNodeAllocator[T comparable](allocator types.Allocator) (NodeAllocator[T] numOfItems := spaceLeft / (itemSize + 1) // 1 is for slot state if numOfItems == 0 { - return NodeAllocator[T]{}, errors.New("node size is too small") + return nil, errors.New("node size is too small") } stateSize := (numOfItems + types.UInt64Length - 1) / types.UInt64Length * types.UInt64Length spaceLeft -= stateSize numOfItems = spaceLeft / itemSize if numOfItems == 0 { - return NodeAllocator[T]{}, errors.New("node size is too small") + return nil, errors.New("node size is too small") } - return NodeAllocator[T]{ + return &NodeAllocator[T]{ allocator: allocator, itemSize: itemSize, numOfItems: int(numOfItems), @@ -57,12 +57,12 @@ type NodeAllocator[T comparable] struct { } // Get returns object for node. -func (na NodeAllocator[T]) Get(nodeAddress types.NodeAddress) types.SpaceNode[T] { +func (na *NodeAllocator[T]) Get(nodeAddress types.NodeAddress) types.SpaceNode[T] { return na.project(na.allocator.Node(nodeAddress)) } // Allocate allocates new object. -func (na NodeAllocator[T]) Allocate(allocator types.SnapshotAllocator) (types.NodeAddress, types.SpaceNode[T], error) { +func (na *NodeAllocator[T]) Allocate(allocator types.SnapshotAllocator) (types.NodeAddress, types.SpaceNode[T], error) { n, node, err := allocator.Allocate() if err != nil { return 0, types.SpaceNode[T]{}, err @@ -71,7 +71,7 @@ func (na NodeAllocator[T]) Allocate(allocator types.SnapshotAllocator) (types.No } // Copy allocates copy of existing object. -func (na NodeAllocator[T]) Copy( +func (na *NodeAllocator[T]) Copy( allocator types.SnapshotAllocator, nodeAddress types.NodeAddress, ) (types.NodeAddress, types.SpaceNode[T], error) { @@ -83,16 +83,16 @@ func (na NodeAllocator[T]) Copy( } // Index returns element index based on hash. -func (na NodeAllocator[T]) Index(hash types.Hash) uint64 { +func (na *NodeAllocator[T]) Index(hash types.Hash) uint64 { return uint64(hash) % uint64(na.numOfItems) } // Shift shifts bits in hash. -func (na NodeAllocator[T]) Shift(hash types.Hash) types.Hash { +func (na *NodeAllocator[T]) Shift(hash types.Hash) types.Hash { return hash / types.Hash(na.numOfItems) } -func (na NodeAllocator[T]) project(node unsafe.Pointer) types.SpaceNode[T] { +func (na *NodeAllocator[T]) project(node unsafe.Pointer) types.SpaceNode[T] { return types.SpaceNode[T]{ Header: photon.FromPointer[types.SpaceNodeHeader](node), States: photon.SliceFromPointer[types.State](unsafe.Add(node, na.stateOffset), na.numOfItems), diff --git a/space/space.go b/space/space.go index ce1d88f..4e5e051 100644 --- a/space/space.go +++ b/space/space.go @@ -16,8 +16,8 @@ const trials = 50 type Config[K, V comparable] struct { HashMod *uint64 SpaceRoot types.ParentInfo - PointerNodeAllocator NodeAllocator[types.Pointer] - DataNodeAllocator NodeAllocator[types.DataItem[K, V]] + PointerNodeAllocator *NodeAllocator[types.Pointer] + DataNodeAllocator *NodeAllocator[types.DataItem[K, V]] Allocator types.SnapshotAllocator } diff --git a/space/space_test.go b/space/space_test.go index 7a40314..0ed7e2d 100644 --- a/space/space_test.go +++ b/space/space_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/require" "github.com/outofforest/quantum/alloc" - "github.com/outofforest/quantum/list" "github.com/outofforest/quantum/space" "github.com/outofforest/quantum/test" "github.com/outofforest/quantum/types" @@ -454,7 +453,7 @@ func newEnv(requireT *require.Assertions) *env { allocator, map[types.SnapshotID]alloc.ListToCommit{}, map[types.SnapshotID]struct{}{}, - list.NodeAllocator{}, + nil, )), spaceRoot: types.ParentInfo{ State: lo.ToPtr(types.StateFree), @@ -484,8 +483,8 @@ type env struct { snapshotID types.SnapshotID spaceRoot types.ParentInfo spaceHashMod *uint64 - pointerNodeAllocator space.NodeAllocator[types.Pointer] - dataNodeAllocator space.NodeAllocator[types.DataItem[int, int]] + pointerNodeAllocator *space.NodeAllocator[types.Pointer] + dataNodeAllocator *space.NodeAllocator[types.DataItem[int, int]] } func (e *env) NextSnapshot() {