github.com/bytedance/gopkg@v0.0.0-20240514070511-01b2cbcf35e1/internal/wyhash/digest_test.go (about)

     1  // Copyright 2021 ByteDance Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package wyhash
    16  
    17  import (
    18  	"fmt"
    19  	"runtime"
    20  	"testing"
    21  
    22  	_ "unsafe" // for linkname
    23  )
    24  
    25  //go:linkname runtime_fastrand runtime.fastrand
    26  func runtime_fastrand() uint32
    27  
    28  //go:nosplit
    29  func fastrandn(n uint32) uint32 {
    30  	// This is similar to Uint32() % n, but faster.
    31  	// See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
    32  	return uint32(uint64(runtime_fastrand()) * uint64(n) >> 32)
    33  }
    34  
    35  func TestDigest(t *testing.T) {
    36  	d := NewDefault()
    37  	for size := 0; size <= 1024; size++ {
    38  		data := make([]byte, size)
    39  		for i := range data {
    40  			data[i] = byte(fastrandn(256))
    41  		}
    42  		// Random write small data.
    43  		var r int
    44  		if size == 0 {
    45  			r = 0
    46  		} else {
    47  			r = int(fastrandn(uint32(len(data))))
    48  		}
    49  		d.Write(data[:r])
    50  		d.Write(data[r:])
    51  		if d.Sum64() != Sum64(data) {
    52  			t.Fatal(size, d.Sum64(), Sum64(data))
    53  		}
    54  		d.Reset()
    55  	}
    56  
    57  	largedata := make([]byte, 1024*1024)
    58  	for i := range largedata {
    59  		largedata[i] = byte(fastrandn(256))
    60  	}
    61  
    62  	var a, b int
    63  	digest := NewDefault()
    64  	partsizelimit := 300
    65  	for {
    66  		if len(largedata)-a < 300 {
    67  			b = len(largedata) - a
    68  		} else {
    69  			b = int(fastrandn(uint32(partsizelimit)))
    70  		}
    71  		digest.Write(largedata[a : a+b])
    72  		if Sum64(largedata[:a+b]) != digest.Sum64() {
    73  			t.Fatal(a, b)
    74  		}
    75  		a += b
    76  		if a == len(largedata) {
    77  			break
    78  		}
    79  	}
    80  }
    81  
    82  func BenchmarkDigest(b *testing.B) {
    83  	sizes := []int{33, 64, 96, 128, 129, 240, 241,
    84  		512, 1024, 10 * 1024,
    85  	}
    86  
    87  	for _, size := range sizes {
    88  		b.Run(fmt.Sprintf("%d", size), func(b *testing.B) {
    89  			b.SetBytes(int64(size))
    90  			var acc uint64
    91  			data := make([]byte, size)
    92  			b.ReportAllocs()
    93  			b.ResetTimer()
    94  
    95  			for i := 0; i < b.N; i++ {
    96  				d := NewDefault()
    97  				d.Write(data)
    98  				acc = d.Sum64()
    99  			}
   100  			runtime.KeepAlive(acc)
   101  		})
   102  	}
   103  }