mirror of
https://github.com/cubefs/cubefs.git
synced 2026-08-02 02:00:56 +00:00
feat(common): add zero buffer checker
cpu: Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz BenchmarkIsZeroBuffer BenchmarkIsZeroBuffer/1M-zero-all BenchmarkIsZeroBuffer/1M-zero-all-4 50384 23927 ns/op 0 B/op 0 allocs/op BenchmarkIsZeroBuffer/1M-not-zero-first BenchmarkIsZeroBuffer/1M-not-zero-first-4 1000000000 0.4 ns/op 0 B/op 0 allocs/op BenchmarkIsZeroBuffer/1M-not-zero-mid BenchmarkIsZeroBuffer/1M-not-zero-mid-4 108770 10617 ns/op 0 B/op 0 allocs/op BenchmarkIsZeroBuffer/1M-not-zero-last BenchmarkIsZeroBuffer/1M-not-zero-last-4 48726 22504 ns/op 0 B/op 0 allocs/op . #1000180877 Signed-off-by: slasher <shenjie1@oppo.com>
This commit is contained in:
parent
22bb533794
commit
ed1b827156
@ -15,10 +15,14 @@
|
||||
package crc32block
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/cubefs/cubefs/blobstore/util"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -115,6 +119,7 @@ func readFullOrToEnd(r io.Reader, buffer []byte) (n int, err error) {
|
||||
var (
|
||||
_k16 = 16 << 10
|
||||
_buffer16k = make([]byte, _k16)
|
||||
_bufferZero = make([]byte, _k16)
|
||||
_mapZeroCrc = sync.Map{}
|
||||
)
|
||||
|
||||
@ -141,3 +146,20 @@ func ConstZeroCrc(size int) uint32 {
|
||||
_mapZeroCrc.Store(size, crc)
|
||||
return crc
|
||||
}
|
||||
|
||||
func IsZeroBuffer(buffer []byte) bool {
|
||||
const width = 8
|
||||
if len(buffer) > width {
|
||||
if binary.BigEndian.Uint64(buffer[:width]) != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for len(buffer) > 0 {
|
||||
minl := util.Min(len(buffer), _k16)
|
||||
if !bytes.Equal(buffer[:minl], _bufferZero[:minl]) {
|
||||
return false
|
||||
}
|
||||
buffer = buffer[minl:]
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
package crc32block
|
||||
|
||||
import (
|
||||
crand "crypto/rand"
|
||||
"hash/crc32"
|
||||
"math/rand"
|
||||
"testing"
|
||||
@ -92,3 +93,54 @@ func TestConstZeroCrc(t *testing.T) {
|
||||
require.Equal(t, act, get2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsZeroBuffer(t *testing.T) {
|
||||
require.True(t, IsZeroBuffer(nil))
|
||||
for _, size := range []int{1, 3, 1 << 10, 1 << 19} {
|
||||
buffer := make([]byte, size)
|
||||
require.True(t, IsZeroBuffer(buffer))
|
||||
buffer[0] = 'a'
|
||||
require.False(t, IsZeroBuffer(buffer))
|
||||
buffer[0] = 0
|
||||
buffer[len(buffer)-1] = 'z'
|
||||
require.False(t, IsZeroBuffer(buffer))
|
||||
buffer[len(buffer)-1] = 0
|
||||
require.True(t, IsZeroBuffer(buffer))
|
||||
crand.Read(buffer)
|
||||
require.False(t, IsZeroBuffer(buffer))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIsZeroBuffer(b *testing.B) {
|
||||
b.Run("1M-zero-all", func(b *testing.B) {
|
||||
buffer := make([]byte, 1<<20)
|
||||
b.ResetTimer()
|
||||
for ii := 0; ii <= b.N; ii++ {
|
||||
IsZeroBuffer(buffer)
|
||||
}
|
||||
})
|
||||
b.Run("1M-not-zero-first", func(b *testing.B) {
|
||||
buffer := make([]byte, 1<<20)
|
||||
buffer[7] = 1
|
||||
b.ResetTimer()
|
||||
for ii := 0; ii <= b.N; ii++ {
|
||||
IsZeroBuffer(buffer)
|
||||
}
|
||||
})
|
||||
b.Run("1M-not-zero-mid", func(b *testing.B) {
|
||||
buffer := make([]byte, 1<<20)
|
||||
buffer[1<<19] = 1
|
||||
b.ResetTimer()
|
||||
for ii := 0; ii <= b.N; ii++ {
|
||||
IsZeroBuffer(buffer)
|
||||
}
|
||||
})
|
||||
b.Run("1M-not-zero-last", func(b *testing.B) {
|
||||
buffer := make([]byte, 1<<20)
|
||||
buffer[(1<<20)-1] = 1
|
||||
b.ResetTimer()
|
||||
for ii := 0; ii <= b.N; ii++ {
|
||||
IsZeroBuffer(buffer)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user