Files
bl/common/utils/bitset/bitset32_benchmark_test.go

455 lines
10 KiB
Go

// Copyright 2014 Will Fitzgerald. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file tests bit sets
package bitset32
import (
"math/rand"
"testing"
)
func BenchmarkSet(b *testing.B) {
b.StopTimer()
r := rand.New(rand.NewSource(0))
sz := 100000
s := New(uint(sz))
b.StartTimer()
for i := 0; i < b.N; i++ {
s.Set(uint(r.Int31n(int32(sz))))
}
}
func BenchmarkGetTest(b *testing.B) {
b.StopTimer()
r := rand.New(rand.NewSource(0))
sz := 100000
s := New(uint(sz))
b.StartTimer()
for i := 0; i < b.N; i++ {
s.Test(uint(r.Int31n(int32(sz))))
}
}
func BenchmarkSetExpand(b *testing.B) {
b.StopTimer()
sz := uint(100000)
b.StartTimer()
for i := 0; i < b.N; i++ {
var s BitSet32
s.Set(sz)
}
}
// go test -bench=Count
func BenchmarkCount(b *testing.B) {
b.StopTimer()
s := New(100000)
for i := 0; i < 100000; i += 100 {
s.Set(uint(i))
}
b.StartTimer()
for i := 0; i < b.N; i++ {
s.Count()
}
}
// go test -bench=Iterate
func BenchmarkIterate(b *testing.B) {
b.StopTimer()
s := New(10000)
for i := 0; i < 10000; i += 3 {
s.Set(uint(i))
}
b.StartTimer()
for j := 0; j < b.N; j++ {
c := uint(0)
for i, e := s.NextSet(0); e; i, e = s.NextSet(i + 1) {
c++
}
}
}
// go test -bench=SparseIterate
func BenchmarkSparseIterate(b *testing.B) {
b.StopTimer()
s := New(100000)
for i := 0; i < 100000; i += 30 {
s.Set(uint(i))
}
b.StartTimer()
for j := 0; j < b.N; j++ {
c := uint(0)
for i, e := s.NextSet(0); e; i, e = s.NextSet(i + 1) {
c++
}
}
}
// go test -bench=LemireCreate
// see http://lemire.me/blog/2016/09/22/swift-versus-java-the-BitSet32-performance-test/
func BenchmarkLemireCreate(b *testing.B) {
for i := 0; i < b.N; i++ {
bitmap := New(0) // we force dynamic memory allocation
for v := uint(0); v <= 100000000; v += 100 {
bitmap.Set(v)
}
}
}
// go test -bench=LemireCount
// see http://lemire.me/blog/2016/09/22/swift-versus-java-the-BitSet32-performance-test/
func BenchmarkLemireCount(b *testing.B) {
bitmap := New(100000000)
for v := uint(0); v <= 100000000; v += 100 {
bitmap.Set(v)
}
b.ResetTimer()
sum := uint(0)
for i := 0; i < b.N; i++ {
sum += bitmap.Count()
}
if sum == 0 { // added just to fool ineffassign
return
}
}
// go test -bench=LemireIterate
// see http://lemire.me/blog/2016/09/22/swift-versus-java-the-BitSet32-performance-test/
func BenchmarkLemireIterate(b *testing.B) {
bitmap := New(100000000)
for v := uint(0); v <= 100000000; v += 100 {
bitmap.Set(v)
}
b.ResetTimer()
sum := uint(0)
for i := 0; i < b.N; i++ {
for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) {
sum++
}
}
if sum == 0 { // added just to fool ineffassign
return
}
}
// go test -bench=LemireIterateb
// see http://lemire.me/blog/2016/09/22/swift-versus-java-the-BitSet32-performance-test/
func BenchmarkLemireIterateb(b *testing.B) {
bitmap := New(100000000)
for v := uint(0); v <= 100000000; v += 100 {
bitmap.Set(v)
}
b.ResetTimer()
sum := uint(0)
for i := 0; i < b.N; i++ {
for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) {
sum += j
}
}
if sum == 0 { // added just to fool ineffassign
return
}
}
// go test -bench=BenchmarkLemireIterateManyb
// see http://lemire.me/blog/2016/09/22/swift-versus-java-the-BitSet32-performance-test/
func BenchmarkLemireIterateManyb(b *testing.B) {
bitmap := New(100000000)
for v := uint(0); v <= 100000000; v += 100 {
bitmap.Set(v)
}
buffer := make([]uint, 256)
b.ResetTimer()
sum := uint(0)
for i := 0; i < b.N; i++ {
j := uint(0)
j, buffer = bitmap.NextSetMany(j, buffer)
for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j, buffer) {
for k := range buffer {
sum += buffer[k]
}
j++
}
}
if sum == 0 { // added just to fool ineffassign
return
}
}
func setRnd(bits []uint32, halfings int) {
var rndsource = rand.NewSource(0)
var rnd = rand.New(rndsource)
for i := range bits {
bits[i] = 0xFFFFFFFF
for j := 0; j < halfings; j++ {
bits[i] &= rnd.Uint32()
}
}
}
// go test -bench=BenchmarkFlorianUekermannIterateMany
func BenchmarkFlorianUekermannIterateMany(b *testing.B) {
var input = make([]uint32, 68)
setRnd(input, 4)
var bitmap = From(input)
buffer := make([]uint, 256)
b.ResetTimer()
var checksum = uint(0)
for i := 0; i < b.N; i++ {
var last, batch = bitmap.NextSetMany(0, buffer)
for len(batch) > 0 {
for _, idx := range batch {
checksum += idx
}
last, batch = bitmap.NextSetMany(last+1, batch)
}
}
if checksum == 0 { // added just to fool ineffassign
return
}
}
func BenchmarkFlorianUekermannIterateManyReg(b *testing.B) {
var input = make([]uint32, 68)
setRnd(input, 4)
var bitmap = From(input)
b.ResetTimer()
var checksum = uint(0)
for i := 0; i < b.N; i++ {
for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) {
checksum += j
}
}
if checksum == 0 { // added just to fool ineffassign
return
}
}
// function provided by FlorianUekermann
func good(set []uint32) (checksum uint) {
for wordIdx, word := range set {
var wordIdx = uint(wordIdx * 64)
for word != 0 {
var bitIdx = uint(trailingZeroes32(word))
word ^= 1 << bitIdx
var index = wordIdx + bitIdx
checksum += index
}
}
return checksum
}
func BenchmarkFlorianUekermannIterateManyComp(b *testing.B) {
var input = make([]uint32, 68)
setRnd(input, 4)
b.ResetTimer()
var checksum = uint(0)
for i := 0; i < b.N; i++ {
checksum += good(input)
}
if checksum == 0 { // added just to fool ineffassign
return
}
}
/////// Mid density
// go test -bench=BenchmarkFlorianUekermannLowDensityIterateMany
func BenchmarkFlorianUekermannLowDensityIterateMany(b *testing.B) {
var input = make([]uint32, 1000000)
var rnd = rand.NewSource(0).(rand.Source64)
for i := 0; i < 50000; i++ {
input[rnd.Uint64()%1000000] = 1
}
var bitmap = From(input)
buffer := make([]uint, 256)
b.ResetTimer()
var sum = uint(0)
for i := 0; i < b.N; i++ {
j := uint(0)
j, buffer = bitmap.NextSetMany(j, buffer)
for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j, buffer) {
for k := range buffer {
sum += buffer[k]
}
j++
}
}
if sum == 0 { // added just to fool ineffassign
return
}
}
func BenchmarkFlorianUekermannLowDensityIterateManyReg(b *testing.B) {
var input = make([]uint32, 1000000)
var rnd = rand.NewSource(0).(rand.Source64)
for i := 0; i < 50000; i++ {
input[rnd.Uint64()%1000000] = 1
}
var bitmap = From(input)
b.ResetTimer()
var checksum = uint(0)
for i := 0; i < b.N; i++ {
for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) {
checksum += j
}
}
if checksum == 0 { // added just to fool ineffassign
return
}
}
func BenchmarkFlorianUekermannLowDensityIterateManyComp(b *testing.B) {
var input = make([]uint32, 1000000)
var rnd = rand.NewSource(0).(rand.Source64)
for i := 0; i < 50000; i++ {
input[rnd.Uint64()%1000000] = 1
}
b.ResetTimer()
var checksum = uint(0)
for i := 0; i < b.N; i++ {
checksum += good(input)
}
if checksum == 0 { // added just to fool ineffassign
return
}
}
/////// Mid density
// go test -bench=BenchmarkFlorianUekermannMidDensityIterateMany
func BenchmarkFlorianUekermannMidDensityIterateMany(b *testing.B) {
var input = make([]uint32, 1000000)
var rndSource = rand.NewSource(0)
var rnd = rand.New(rndSource)
for i := 0; i < 3000000; i++ {
input[rnd.Uint32()%1000000] |= uint32(1) << (rnd.Uint32() % 32)
}
var bitmap = From(input)
buffer := make([]uint, 256)
b.ResetTimer()
sum := uint(0)
for i := 0; i < b.N; i++ {
j := uint(0)
j, buffer = bitmap.NextSetMany(j, buffer)
for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j, buffer) {
for k := range buffer {
sum += buffer[k]
}
j++
}
}
if sum == 0 { // added just to fool ineffassign
return
}
}
func BenchmarkFlorianUekermannMidDensityIterateManyReg(b *testing.B) {
var input = make([]uint32, 1000000)
var rndSource = rand.NewSource(0)
var rnd = rand.New(rndSource)
for i := 0; i < 3000000; i++ {
input[rnd.Uint32()%1000000] |= uint32(1) << (rnd.Uint32() % 32)
}
var bitmap = From(input)
b.ResetTimer()
var checksum = uint(0)
for i := 0; i < b.N; i++ {
for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) {
checksum += j
}
}
if checksum == 0 { // added just to fool ineffassign
return
}
}
func BenchmarkFlorianUekermannMidDensityIterateManyComp(b *testing.B) {
var input = make([]uint32, 1000000)
var rndSource = rand.NewSource(0)
var rnd = rand.New(rndSource)
for i := 0; i < 3000000; i++ {
input[rnd.Uint32()%1000000] |= uint32(1) << (rnd.Uint32() % 32)
}
b.ResetTimer()
var checksum = uint(0)
for i := 0; i < b.N; i++ {
checksum += good(input)
}
if checksum == 0 { // added just to fool ineffassign
return
}
}
////////// High density
func BenchmarkFlorianUekermannMidStrongDensityIterateMany(b *testing.B) {
var input = make([]uint32, 1000000)
var rndSource = rand.NewSource(0)
var rnd = rand.New(rndSource)
for i := 0; i < 20000000; i++ {
input[rnd.Uint32()%1000000] |= uint32(1) << (rnd.Uint32() % 64)
}
var bitmap = From(input)
buffer := make([]uint, 256)
b.ResetTimer()
sum := uint(0)
for i := 0; i < b.N; i++ {
j := uint(0)
j, buffer = bitmap.NextSetMany(j, buffer)
for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j, buffer) {
for k := range buffer {
sum += buffer[k]
}
j++
}
}
if sum == 0 { // added just to fool ineffassign
return
}
}
func BenchmarkFlorianUekermannMidStrongDensityIterateManyReg(b *testing.B) {
var input = make([]uint32, 1000000)
var rndSource = rand.NewSource(0)
var rnd = rand.New(rndSource)
for i := 0; i < 20000000; i++ {
input[rnd.Uint32()%1000000] |= uint32(1) << (rnd.Uint32() % 32)
}
var bitmap = From(input)
b.ResetTimer()
var checksum = uint(0)
for i := 0; i < b.N; i++ {
for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) {
checksum += j
}
}
if checksum == 0 { // added just to fool ineffassign
return
}
}
func BenchmarkFlorianUekermannMidStrongDensityIterateManyComp(b *testing.B) {
var input = make([]uint32, 1000000)
var rndSource = rand.NewSource(0)
var rnd = rand.New(rndSource)
for i := 0; i < 20000000; i++ {
input[rnd.Uint32()%1000000] |= uint32(1) << (rnd.Uint32() % 32)
}
b.ResetTimer()
var checksum = uint(0)
for i := 0; i < b.N; i++ {
checksum += good(input)
}
if checksum == 0 { // added just to fool ineffassign
return
}
}