mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 23:18:15 -05:00
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 commit59eb9df8d7. # 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 commit0cf00f19ee. * Revert "make tests pass" This reverts commit521b65e1d2. * 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:
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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"],
|
||||
)
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)])
|
||||
|
||||
Reference in New Issue
Block a user