From 72873a072f05c0ecc67b84d757fef4559f541d16 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 1 May 2021 04:08:14 +0700 Subject: [PATCH] crypto/types: optimize compact bit array one count (#9216) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By using bits.OnesCount8 instead of bitwise operations. Benchmark result on Apple M1: name old time/op new time/op delta NumTrueBitsBefore/new-8 88.5ns ± 1% 9.1ns ± 0% -89.68% (p=0.000 n=10+10) name old alloc/op new alloc/op delta NumTrueBitsBefore/new-8 0.00B 0.00B ~ (all equal) name old allocs/op new allocs/op delta NumTrueBitsBefore/new-8 0.00 0.00 ~ (all equal) Fixes #9125 --- crypto/types/compact_bit_array.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/crypto/types/compact_bit_array.go b/crypto/types/compact_bit_array.go index 02d02e811b..1bbd5ec07d 100644 --- a/crypto/types/compact_bit_array.go +++ b/crypto/types/compact_bit_array.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "math" + "math/bits" "regexp" "strings" ) @@ -85,23 +86,18 @@ func (bA *CompactBitArray) SetIndex(i int, v bool) bool { // given index. e.g. if bA = _XX__XX, NumOfTrueBitsBefore(4) = 2, since // there are two bits set to true before index 4. func (bA *CompactBitArray) NumTrueBitsBefore(index int) int { - numTrueValues := 0 + onesCount := 0 max := bA.Count() if index > max { index = max } // below we iterate over the bytes then over bits (in low endian) and count bits set to 1 - var i = 0 for elem := 0; ; elem++ { - for b := 7; b >= 0; b-- { - if i >= index { - return numTrueValues - } - i++ - if (bA.Elems[elem]>>b)&1 == 1 { - numTrueValues++ - } + if elem*8+7 >= index { + onesCount += bits.OnesCount8(bA.Elems[elem] >> (7 - (index % 8) + 1)) + return onesCount } + onesCount += bits.OnesCount8(bA.Elems[elem]) } }