Using the multi value slice for the beacon state (#12549)

* in progress...

* in progress...

* remove log

* log root

* Revert "Auxiliary commit to revert individual files from f12a609ea2a2f1e87e97321f3a717cd324b5ae97"

This reverts commit 5ae35edb6477d8d0ea4e94b273efc6590484da85.

* cleanup

* remove log

* remove whitespace

* remove logs

* more stuff

* copy

* always rebuild trie

* revert

* add state

* init state

* fix all

* uintptr

* move slice to new package

* lock in `Detach`

* remove constraint

* reorder

* blockroots and stateroots

* fill roots in empty()

* fix hasher

* implement slice for balances and inactivity scores

* detach in setters

* Revert "implement slice for balances and inactivity scores"

This reverts commit 59eb9df8d7.

# Conflicts:
#	beacon-chain/state/state-native/setters_validator.go

* use counter to track states

* typos

* rename interface

* balances

* gauge

* some improvements

* first try with map

* fix

* inactivity scores in progress

* fix test

# Conflicts:
#	beacon-chain/state/state-native/helpers_test.go

* test fixes

* ToProto fix

* copy roots

* validators

* build fixes

* fix bug in `ToProto`

* fix fuzz test

* fix bug in slice getters

* fix state equality checks

* make tests pass

* make tests pass

* more test updates

* Revert "Auxiliary commit to revert individual files from 34e7344bff08a589e6341bb1829e3cb74159e878"

This reverts commit ecd64efa8917f37ca41460e0356ff007fe55dd9d.

* Revert "make tests pass"

This reverts commit 0cf00f19ee.

* Revert "make tests pass"

This reverts commit 521b65e1d2.

* pass tests

* deepequal identifiable types

* Deflake `cloners_test.go`

* feature flag for block roots

* feature flag

* remove recursive locks

* reduce complexity of rootSelector

* fix randao mixes root

* some fixes

* revisit tests

* revert change to field trie helpers

* initialize field map for tests

* remove whitespace

* initialize roots with proper length

* more fixes

* out of bounds message fix

* optimize length calculation

* remove call to Len in PubkeyAtIndex

* don't log deposits

* unit tests

* unit tests

* fix

* comments

* test fixes

* id

* remove Enumerator interface

* review feedback

* simplify field trie

* bring back fieldtrie package

* fix bazel file

* use handle32ByteArrays for root computation

* fix locks

* metrics

* bzl

* simplify some things

* use htr in state test

* remove code from require package

* gzl

* more htr

* Fuzzing of the multi-value slice

* assert values

* getter optimizations

* use At when reading from validators

* Nishant's review

* restore safe copy

* remove empty line

* build fix

* restore how we get root at index for deafult mode

* more review comments

* optimize default behavior

* simplify Slice calls

* test fix

* remove unnecessary package

* remove unused setter

* make fieldMap unexported

* some improvements in state package

* call `Slice` instead of manually copying

* unlock in ReadFromEveryValidator

* Potuz's comments

* lock the state when reading from all validators

# Conflicts:
#	beacon-chain/state/state-native/getters_validator.go

* add back preston's changes

* add index

---------

Co-authored-by: Potuz <potuz@prysmaticlabs.com>
Co-authored-by: nisdas <nishdas93@gmail.com>
Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
This commit is contained in:
Radosław Kapka
2023-10-06 03:10:05 +02:00
committed by GitHub
parent de0c7e6256
commit 44973b0bb3
60 changed files with 1742 additions and 984 deletions

View File

@@ -5,10 +5,6 @@ go_library(
srcs = ["multi_value_slice.go"],
importpath = "github.com/prysmaticlabs/prysm/v4/container/multi-value-slice",
visibility = ["//visibility:public"],
deps = [
"//container/multi-value-slice/interfaces:go_default_library",
"@com_github_google_uuid//:go_default_library",
],
)
go_test(
@@ -18,6 +14,5 @@ go_test(
deps = [
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"@com_github_google_uuid//:go_default_library",
],
)

View File

@@ -1,9 +0,0 @@
load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["interfaces.go"],
importpath = "github.com/prysmaticlabs/prysm/v4/container/multi-value-slice/interfaces",
visibility = ["//visibility:public"],
deps = ["@com_github_google_uuid//:go_default_library"],
)

View File

@@ -1,9 +0,0 @@
package interfaces
import "github.com/google/uuid"
// Identifiable represents an object that can be uniquely identified by its Id.
type Identifiable interface {
Id() uuid.UUID
SetId(id uuid.UUID)
}

View File

@@ -92,20 +92,25 @@ package mvslice
import (
"fmt"
"sync"
"github.com/google/uuid"
"github.com/prysmaticlabs/prysm/v4/container/multi-value-slice/interfaces"
)
// Id is an object identifier.
type Id = uint64
// Identifiable represents an object that can be uniquely identified by its Id.
type Identifiable interface {
Id() Id
}
// MultiValueSlice defines an abstraction over all concrete implementations of the generic Slice.
type MultiValueSlice[O interfaces.Identifiable] interface {
Len(obj O) uuid.UUID
type MultiValueSlice[O Identifiable] interface {
Len(obj O) int
}
// Value defines a single value along with one or more IDs that share this value.
type Value[V any] struct {
val V
ids []uuid.UUID
ids []uint64
}
// MultiValueItem defines a collection of Value items.
@@ -119,11 +124,11 @@ type MultiValueItem[V any] struct {
// - O interfaces.Identifiable - the type of objects sharing the slice. The constraint is required
// because we need a way to compare objects against each other in order to know which objects
// values should be accessed.
type Slice[V comparable, O interfaces.Identifiable] struct {
type Slice[V comparable, O Identifiable] struct {
sharedItems []V
individualItems map[uint64]*MultiValueItem[V]
appendedItems []*MultiValueItem[V]
cachedLengths map[uuid.UUID]int
cachedLengths map[uint64]int
lock sync.RWMutex
}
@@ -132,7 +137,7 @@ func (s *Slice[V, O]) Init(items []V) {
s.sharedItems = items
s.individualItems = map[uint64]*MultiValueItem[V]{}
s.appendedItems = []*MultiValueItem[V]{}
s.cachedLengths = map[uuid.UUID]int{}
s.cachedLengths = map[uint64]int{}
}
// Len returns the number of items for the input object.
@@ -283,7 +288,7 @@ func (s *Slice[V, O]) Append(obj O, val V) {
defer s.lock.Unlock()
if len(s.appendedItems) == 0 {
s.appendedItems = append(s.appendedItems, &MultiValueItem[V]{Values: []*Value[V]{{val: val, ids: []uuid.UUID{obj.Id()}}}})
s.appendedItems = append(s.appendedItems, &MultiValueItem[V]{Values: []*Value[V]{{val: val, ids: []uint64{obj.Id()}}}})
s.cachedLengths[obj.Id()] = len(s.sharedItems) + 1
return
}
@@ -306,7 +311,7 @@ func (s *Slice[V, O]) Append(obj O, val V) {
}
}
if newValue {
item.Values = append(item.Values, &Value[V]{val: val, ids: []uuid.UUID{obj.Id()}})
item.Values = append(item.Values, &Value[V]{val: val, ids: []uint64{obj.Id()}})
}
l, ok := s.cachedLengths[obj.Id()]
@@ -320,7 +325,7 @@ func (s *Slice[V, O]) Append(obj O, val V) {
}
}
s.appendedItems = append(s.appendedItems, &MultiValueItem[V]{Values: []*Value[V]{{val: val, ids: []uuid.UUID{obj.Id()}}}})
s.appendedItems = append(s.appendedItems, &MultiValueItem[V]{Values: []*Value[V]{{val: val, ids: []uint64{obj.Id()}}}})
s.cachedLengths[obj.Id()] = s.cachedLengths[obj.Id()] + 1
}
@@ -419,7 +424,7 @@ func (s *Slice[V, O]) updateOriginalItem(obj O, index uint64, val V) {
}
if !ok {
s.individualItems[index] = &MultiValueItem[V]{Values: []*Value[V]{{val: val, ids: []uuid.UUID{obj.Id()}}}}
s.individualItems[index] = &MultiValueItem[V]{Values: []*Value[V]{{val: val, ids: []uint64{obj.Id()}}}}
} else {
newValue := true
for _, v := range ind.Values {
@@ -430,7 +435,7 @@ func (s *Slice[V, O]) updateOriginalItem(obj O, index uint64, val V) {
}
}
if newValue {
ind.Values = append(ind.Values, &Value[V]{val: val, ids: []uuid.UUID{obj.Id()}})
ind.Values = append(ind.Values, &Value[V]{val: val, ids: []uint64{obj.Id()}})
}
}
}
@@ -464,13 +469,13 @@ func (s *Slice[V, O]) updateAppendedItem(obj O, index uint64, val V) error {
}
}
if newValue {
item.Values = append(item.Values, &Value[V]{val: val, ids: []uuid.UUID{obj.Id()}})
item.Values = append(item.Values, &Value[V]{val: val, ids: []uint64{obj.Id()}})
}
return nil
}
func containsId(ids []uuid.UUID, wanted uuid.UUID) (int, bool) {
func containsId(ids []uint64, wanted uint64) (int, bool) {
for i, id := range ids {
if id == wanted {
return i, true

View File

@@ -4,40 +4,31 @@ import (
"math/rand"
"testing"
"github.com/google/uuid"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
)
var (
id1 = uuid.New()
id2 = uuid.New()
id999 = uuid.New()
)
type testObject struct {
id uuid.UUID
slice *Slice[int, *testObject]
id uint64
}
func (o *testObject) Id() uuid.UUID {
func (o *testObject) Id() uint64 {
return o.id
}
func (o *testObject) SetId(id uuid.UUID) {
func (o *testObject) SetId(id uint64) {
o.id = id
}
func TestLen(t *testing.T) {
s := &Slice[int, *testObject]{}
s.Init([]int{1, 2, 3})
id := uuid.New()
s.cachedLengths[id] = 123
s.cachedLengths[1] = 123
t.Run("cached", func(t *testing.T) {
assert.Equal(t, 123, s.Len(&testObject{id: id}))
assert.Equal(t, 123, s.Len(&testObject{id: 1}))
})
t.Run("not cached", func(t *testing.T) {
assert.Equal(t, 3, s.Len(&testObject{id: uuid.New()}))
assert.Equal(t, 3, s.Len(&testObject{id: 999}))
})
}
@@ -51,12 +42,12 @@ func TestCopy(t *testing.T) {
// - length of destination object is cached
s := setup()
src := &testObject{id: id1, slice: s}
dst := &testObject{id: id999, slice: s}
src := &testObject{id: 1}
dst := &testObject{id: 999}
s.Copy(src, dst)
assert.Equal(t, (*MultiValueItem[int])(nil), dst.slice.individualItems[0])
assert.Equal(t, (*MultiValueItem[int])(nil), s.individualItems[0])
assertIndividualFound(t, s, dst.id, 1, 1)
assertIndividualFound(t, s, dst.id, 2, 3)
assertIndividualFound(t, s, dst.id, 3, 1)
@@ -64,7 +55,7 @@ func TestCopy(t *testing.T) {
assertAppendedFound(t, s, dst.id, 0, 1)
assertAppendedFound(t, s, dst.id, 1, 3)
assertAppendedNotFound(t, s, dst.id, 2)
l, ok := s.cachedLengths[id999]
l, ok := s.cachedLengths[999]
require.Equal(t, true, ok)
assert.Equal(t, 7, l)
}
@@ -76,8 +67,8 @@ func TestValue(t *testing.T) {
// - correct values are returned for an object without appended items
s := setup()
first := &testObject{id: id1, slice: s}
second := &testObject{id: id2, slice: s}
first := &testObject{id: 1}
second := &testObject{id: 2}
v := s.Value(first)
@@ -104,9 +95,8 @@ func TestValue(t *testing.T) {
s = &Slice[int, *testObject]{}
s.Init([]int{1, 2, 3})
id := uuid.New()
v = s.Value(&testObject{id: id})
v = s.Value(&testObject{id: 999})
require.Equal(t, 3, len(v))
assert.Equal(t, 1, v[0])
@@ -122,8 +112,8 @@ func TestAt(t *testing.T) {
// - ERROR when index not too large in general, but too large for an object
s := setup()
first := &testObject{id: id1, slice: s}
second := &testObject{id: id2, slice: s}
first := &testObject{id: 1}
second := &testObject{id: 2}
v, err := s.At(first, 0)
require.NoError(t, err)
@@ -194,8 +184,8 @@ func TestUpdateAt(t *testing.T) {
// - ERROR when index not too large in general, but too large for an object
s := setup()
first := &testObject{id: id1, slice: s}
second := &testObject{id: id2, slice: s}
first := &testObject{id: 1}
second := &testObject{id: 2}
require.NoError(t, s.UpdateAt(first, 0, 999))
assert.Equal(t, 123, s.sharedItems[0])
@@ -258,8 +248,8 @@ func TestAppend(t *testing.T) {
// we want to start with the simplest slice possible
s := &Slice[int, *testObject]{}
s.Init([]int{0})
first := &testObject{id: id1, slice: s}
second := &testObject{id: id2, slice: s}
first := &testObject{id: 1}
second := &testObject{id: 2}
// append first value ever
s.Append(first, 1)
@@ -306,7 +296,7 @@ func TestDetach(t *testing.T) {
// - length removed from cache
s := setup()
obj := &testObject{id: id1, slice: s}
obj := &testObject{id: 1}
s.Detach(obj)
@@ -352,11 +342,11 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 1,
ids: []uuid.UUID{id1},
ids: []uint64{1},
},
{
val: 2,
ids: []uuid.UUID{id2},
ids: []uint64{2},
},
},
}
@@ -364,7 +354,7 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 3,
ids: []uuid.UUID{id1, id2},
ids: []uint64{1, 2},
},
},
}
@@ -372,7 +362,7 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 1,
ids: []uuid.UUID{id1},
ids: []uint64{1},
},
},
}
@@ -380,7 +370,7 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 2,
ids: []uuid.UUID{id2},
ids: []uint64{2},
},
},
}
@@ -389,11 +379,11 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 1,
ids: []uuid.UUID{id1},
ids: []uint64{1},
},
{
val: 2,
ids: []uuid.UUID{id2},
ids: []uint64{2},
},
},
},
@@ -401,7 +391,7 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 3,
ids: []uuid.UUID{id1, id2},
ids: []uint64{1, 2},
},
},
},
@@ -409,18 +399,18 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 2,
ids: []uuid.UUID{id2},
ids: []uint64{2},
},
},
},
}
s.cachedLengths[id1] = 7
s.cachedLengths[id2] = 8
s.cachedLengths[1] = 7
s.cachedLengths[2] = 8
return s
}
func assertIndividualFound(t *testing.T, slice *Slice[int, *testObject], id uuid.UUID, itemIndex uint64, expected int) {
func assertIndividualFound(t *testing.T, slice *Slice[int, *testObject], id uint64, itemIndex uint64, expected int) {
found := false
for _, v := range slice.individualItems[itemIndex].Values {
for _, o := range v.ids {
@@ -433,7 +423,7 @@ func assertIndividualFound(t *testing.T, slice *Slice[int, *testObject], id uuid
assert.Equal(t, true, found)
}
func assertIndividualNotFound(t *testing.T, slice *Slice[int, *testObject], id uuid.UUID, itemIndex uint64) {
func assertIndividualNotFound(t *testing.T, slice *Slice[int, *testObject], id uint64, itemIndex uint64) {
found := false
for _, v := range slice.individualItems[itemIndex].Values {
for _, o := range v.ids {
@@ -445,7 +435,7 @@ func assertIndividualNotFound(t *testing.T, slice *Slice[int, *testObject], id u
assert.Equal(t, false, found)
}
func assertAppendedFound(t *testing.T, slice *Slice[int, *testObject], id uuid.UUID, itemIndex uint64, expected int) {
func assertAppendedFound(t *testing.T, slice *Slice[int, *testObject], id uint64, itemIndex uint64, expected int) {
found := false
for _, v := range slice.appendedItems[itemIndex].Values {
for _, o := range v.ids {
@@ -458,7 +448,7 @@ func assertAppendedFound(t *testing.T, slice *Slice[int, *testObject], id uuid.U
assert.Equal(t, true, found)
}
func assertAppendedNotFound(t *testing.T, slice *Slice[int, *testObject], id uuid.UUID, itemIndex uint64) {
func assertAppendedNotFound(t *testing.T, slice *Slice[int, *testObject], id uint64, itemIndex uint64) {
found := false
for _, v := range slice.appendedItems[itemIndex].Values {
for _, o := range v.ids {
@@ -485,12 +475,11 @@ func BenchmarkValue(b *testing.B) {
b.Run("100,000 equal individual items", func(b *testing.B) {
s := &Slice[int, *testObject]{}
s.Init(make([]int, _100k))
s.individualItems[0] = &MultiValueItem[int]{Values: []*Value[int]{{val: 999, ids: []uuid.UUID{}}}}
s.individualItems[0] = &MultiValueItem[int]{Values: []*Value[int]{{val: 999, ids: []uint64{}}}}
objs := make([]*testObject, _100k)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.individualItems[0].Values[0].ids = append(s.individualItems[0].Values[0].ids, id)
objs[i] = &testObject{id: uint64(i)}
s.individualItems[0].Values[0].ids = append(s.individualItems[0].Values[0].ids, uint64(i))
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_100k)])
@@ -501,9 +490,8 @@ func BenchmarkValue(b *testing.B) {
s.Init(make([]int, _100k))
objs := make([]*testObject, _100k)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.individualItems[uint64(i)] = &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uuid.UUID{id}}}}
objs[i] = &testObject{id: uint64(i)}
s.individualItems[uint64(i)] = &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uint64{uint64(i)}}}}
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_100k)])
@@ -512,12 +500,11 @@ func BenchmarkValue(b *testing.B) {
b.Run("100,000 shared items and 100,000 equal appended items", func(b *testing.B) {
s := &Slice[int, *testObject]{}
s.Init(make([]int, _100k))
s.appendedItems = []*MultiValueItem[int]{{Values: []*Value[int]{{val: 999, ids: []uuid.UUID{}}}}}
s.appendedItems = []*MultiValueItem[int]{{Values: []*Value[int]{{val: 999, ids: []uint64{}}}}}
objs := make([]*testObject, _100k)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.appendedItems[0].Values[0].ids = append(s.appendedItems[0].Values[0].ids, id)
objs[i] = &testObject{id: uint64(i)}
s.appendedItems[0].Values[0].ids = append(s.appendedItems[0].Values[0].ids, uint64(i))
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_100k)])
@@ -529,9 +516,8 @@ func BenchmarkValue(b *testing.B) {
s.appendedItems = []*MultiValueItem[int]{}
objs := make([]*testObject, _100k)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.appendedItems = append(s.appendedItems, &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uuid.UUID{id}}}})
objs[i] = &testObject{id: uint64(i)}
s.appendedItems = append(s.appendedItems, &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uint64{uint64(i)}}}})
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_100k)])
@@ -547,12 +533,11 @@ func BenchmarkValue(b *testing.B) {
b.Run("1,000,000 equal individual items", func(b *testing.B) {
s := &Slice[int, *testObject]{}
s.Init(make([]int, _1m))
s.individualItems[0] = &MultiValueItem[int]{Values: []*Value[int]{{val: 999, ids: []uuid.UUID{}}}}
s.individualItems[0] = &MultiValueItem[int]{Values: []*Value[int]{{val: 999, ids: []uint64{}}}}
objs := make([]*testObject, _1m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.individualItems[0].Values[0].ids = append(s.individualItems[0].Values[0].ids, id)
objs[i] = &testObject{id: uint64(i)}
s.individualItems[0].Values[0].ids = append(s.individualItems[0].Values[0].ids, uint64(i))
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_1m)])
@@ -563,9 +548,8 @@ func BenchmarkValue(b *testing.B) {
s.Init(make([]int, _1m))
objs := make([]*testObject, _1m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.individualItems[uint64(i)] = &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uuid.UUID{id}}}}
objs[i] = &testObject{id: uint64(i)}
s.individualItems[uint64(i)] = &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uint64{uint64(i)}}}}
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_1m)])
@@ -574,12 +558,11 @@ func BenchmarkValue(b *testing.B) {
b.Run("1,000,000 shared items and 1,000,000 equal appended items", func(b *testing.B) {
s := &Slice[int, *testObject]{}
s.Init(make([]int, _1m))
s.appendedItems = []*MultiValueItem[int]{{Values: []*Value[int]{{val: 999, ids: []uuid.UUID{}}}}}
s.appendedItems = []*MultiValueItem[int]{{Values: []*Value[int]{{val: 999, ids: []uint64{}}}}}
objs := make([]*testObject, _1m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.appendedItems[0].Values[0].ids = append(s.appendedItems[0].Values[0].ids, id)
objs[i] = &testObject{id: uint64(i)}
s.appendedItems[0].Values[0].ids = append(s.appendedItems[0].Values[0].ids, uint64(i))
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_1m)])
@@ -591,9 +574,8 @@ func BenchmarkValue(b *testing.B) {
s.appendedItems = []*MultiValueItem[int]{}
objs := make([]*testObject, _1m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.appendedItems = append(s.appendedItems, &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uuid.UUID{id}}}})
objs[i] = &testObject{id: uint64(i)}
s.appendedItems = append(s.appendedItems, &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uint64{uint64(i)}}}})
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_1m)])
@@ -609,12 +591,11 @@ func BenchmarkValue(b *testing.B) {
b.Run("10,000,000 equal individual items", func(b *testing.B) {
s := &Slice[int, *testObject]{}
s.Init(make([]int, _10m))
s.individualItems[0] = &MultiValueItem[int]{Values: []*Value[int]{{val: 999, ids: []uuid.UUID{}}}}
s.individualItems[0] = &MultiValueItem[int]{Values: []*Value[int]{{val: 999, ids: []uint64{}}}}
objs := make([]*testObject, _10m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.individualItems[0].Values[0].ids = append(s.individualItems[0].Values[0].ids, id)
objs[i] = &testObject{id: uint64(i)}
s.individualItems[0].Values[0].ids = append(s.individualItems[0].Values[0].ids, uint64(i))
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_10m)])
@@ -625,9 +606,8 @@ func BenchmarkValue(b *testing.B) {
s.Init(make([]int, _10m))
objs := make([]*testObject, _10m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.individualItems[uint64(i)] = &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uuid.UUID{id}}}}
objs[i] = &testObject{id: uint64(i)}
s.individualItems[uint64(i)] = &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uint64{uint64(i)}}}}
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_10m)])
@@ -636,12 +616,11 @@ func BenchmarkValue(b *testing.B) {
b.Run("10,000,000 shared items and 10,000,000 equal appended items", func(b *testing.B) {
s := &Slice[int, *testObject]{}
s.Init(make([]int, _10m))
s.appendedItems = []*MultiValueItem[int]{{Values: []*Value[int]{{val: 999, ids: []uuid.UUID{}}}}}
s.appendedItems = []*MultiValueItem[int]{{Values: []*Value[int]{{val: 999, ids: []uint64{}}}}}
objs := make([]*testObject, _10m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.appendedItems[0].Values[0].ids = append(s.appendedItems[0].Values[0].ids, id)
objs[i] = &testObject{id: uint64(i)}
s.appendedItems[0].Values[0].ids = append(s.appendedItems[0].Values[0].ids, uint64(i))
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_10m)])
@@ -653,9 +632,8 @@ func BenchmarkValue(b *testing.B) {
s.appendedItems = []*MultiValueItem[int]{}
objs := make([]*testObject, _10m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.appendedItems = append(s.appendedItems, &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uuid.UUID{id}}}})
objs[i] = &testObject{id: uint64(i)}
s.appendedItems = append(s.appendedItems, &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uint64{uint64(i)}}}})
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_10m)])