From c75a82ecf169d28fd66e06ffaadb584262508356 Mon Sep 17 00:00:00 2001 From: bitver Date: Sun, 4 May 2025 14:35:49 +0500 Subject: [PATCH 1/2] fastest log2 on wild west --- pkg/ecs/int-log.go | 4 ++-- pkg/ecs/int-log_test.go | 41 +++++++++++++++++++++++++++-------------- pkg/ecs/slice.go | 2 +- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/pkg/ecs/int-log.go b/pkg/ecs/int-log.go index 929a8f82..f47a5773 100644 --- a/pkg/ecs/int-log.go +++ b/pkg/ecs/int-log.go @@ -8,6 +8,6 @@ package ecs import "math/bits" -func FastIntLog2(value int) int { - return bits.Len64(uint64(value)) - 1 +func FastIntLog2(value uint64) int { + return bits.Len64(value) - 1 } diff --git a/pkg/ecs/int-log_test.go b/pkg/ecs/int-log_test.go index 62ebb2f2..ec5d056b 100644 --- a/pkg/ecs/int-log_test.go +++ b/pkg/ecs/int-log_test.go @@ -8,28 +8,41 @@ package ecs import ( "math" + "math/bits" "testing" ) -func TesCalcIndex(t *testing.T) { - for i := 0; i <= 100_000_000; i++ { - value := i>>10 + 1 - want := int(math.Log2(float64(value))) - have := FastIntLog2(value) - if want != have { - t.Fatalf("i: %v, want: %v, got: %v", i, want, have) - } +//func TesCalcIndex(t *testing.T) { +// for i := 0; i <= 100_000_000; i++ { +// value := i>>10 + 1 +// want := uint64(math.Log2(float64(value))) +// have := FastIntLog2(value) +// if want != have { +// t.Fatalf("i: %v, want: %v, got: %v", i, want, have) +// } +// } +//} + +func BenchmarkFastestLog2(b *testing.B) { + var i uint64 = 1 + for b.Loop() { + _ = bits.LeadingZeros64(i/10 + 1) + i++ } } -func BenchmarkFastLog2(t *testing.B) { - for range t.N { - _ = FastIntLog2(t.N/10 + 1) +func BenchmarkFastLog2(b *testing.B) { + var i uint64 = 1 + for b.Loop() { + _ = FastIntLog2(i/10 + 1) + i++ } } -func BenchmarkStdMathLog2(t *testing.B) { - for range t.N { - _ = int(math.Log2(float64(t.N/10 + 1))) +func BenchmarkStdMathLog2(b *testing.B) { + var i uint64 = 1 + for b.Loop() { + _ = math.Log2(float64(i/10 + 1)) + i++ } } diff --git a/pkg/ecs/slice.go b/pkg/ecs/slice.go index 4a3c5785..5cfe0117 100644 --- a/pkg/ecs/slice.go +++ b/pkg/ecs/slice.go @@ -60,7 +60,7 @@ func (a *Slice[T]) Set(index int, value T) *T { func (a *Slice[T]) Append(values ...T) []T { a.data = append(a.data, values...) - disCap := 1 << (FastIntLog2(len(a.data)) + 1) + disCap := 1 << (FastIntLog2(uint64(len(a.data))) + 1) if cap(a.data) > disCap { a.data = a.data[:len(a.data):disCap] } From ca8bdc8853b8327c6e1f670dc7d471bc5babfbc8 Mon Sep 17 00:00:00 2001 From: bitver Date: Sun, 4 May 2025 14:50:23 +0500 Subject: [PATCH 2/2] fastest log2 on wild west --- pkg/ecs/int-log.go | 4 ++++ pkg/ecs/int-log_test.go | 26 +++++++++++++++----------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/pkg/ecs/int-log.go b/pkg/ecs/int-log.go index f47a5773..42444808 100644 --- a/pkg/ecs/int-log.go +++ b/pkg/ecs/int-log.go @@ -11,3 +11,7 @@ import "math/bits" func FastIntLog2(value uint64) int { return bits.Len64(value) - 1 } + +func FastestIntLog2(value uint64) int { + return bits.LeadingZeros64(value) ^ 63 +} diff --git a/pkg/ecs/int-log_test.go b/pkg/ecs/int-log_test.go index ec5d056b..5085b9be 100644 --- a/pkg/ecs/int-log_test.go +++ b/pkg/ecs/int-log_test.go @@ -12,21 +12,25 @@ import ( "testing" ) -//func TesCalcIndex(t *testing.T) { -// for i := 0; i <= 100_000_000; i++ { -// value := i>>10 + 1 -// want := uint64(math.Log2(float64(value))) -// have := FastIntLog2(value) -// if want != have { -// t.Fatalf("i: %v, want: %v, got: %v", i, want, have) -// } -// } -//} +func TestCalcIndex(t *testing.T) { + for i := uint64(0); i <= 100_000_000; i++ { + var value uint64 = i>>10 + 1 + want := int(math.Log2(float64(value))) + want2 := int(bits.LeadingZeros64(value) ^ 63) + have := bits.Len64(value) - 1 + if want != have { + t.Fatalf("i: %v, want: %v, got: %v", i, want, have) + } + if want2 != have { + t.Fatalf("i: %v, want: %v, got: %v", i, want2, have) + } + } +} func BenchmarkFastestLog2(b *testing.B) { var i uint64 = 1 for b.Loop() { - _ = bits.LeadingZeros64(i/10 + 1) + _ = FastestIntLog2(i/10 + 1) i++ } }