mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-22 02:48:59 +00:00
lib/rand: Optimizations (#7964)
rand.secureSource.Uint64 no longer allocates. rand.String uses a strings.Builder. Benchmark results on linux/amd64: name old time/op new time/op delta SecureSource-8 69.1ns ± 3% 51.7ns ± 3% -25.21% (p=0.000 n=20+10) String-8 2.66µs ± 2% 1.95µs ± 1% -26.61% (p=0.000 n=10+10) name old alloc/op new alloc/op delta SecureSource-8 8.00B ± 0% 0.00B -100.00% (p=0.000 n=20+10) String-8 288B ± 0% 32B ± 0% -88.89% (p=0.000 n=10+10) name old allocs/op new allocs/op delta SecureSource-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=20+10) String-8 33.0 ± 0% 1.0 ± 0% -96.97% (p=0.000 n=10+10)
This commit is contained in:
parent
c5ec6cd7ef
commit
198028d627
@ -12,6 +12,7 @@ import (
|
||||
"io"
|
||||
mathRand "math/rand"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Reader is the standard crypto/rand.Reader with added buffering.
|
||||
@ -37,11 +38,13 @@ var (
|
||||
// (taken from randomCharset) of the specified length. The returned string
|
||||
// contains ~5.8 bits of entropy per character, due to the character set used.
|
||||
func String(l int) string {
|
||||
bs := make([]byte, l)
|
||||
for i := range bs {
|
||||
bs[i] = randomCharset[defaultSecureRand.Intn(len(randomCharset))]
|
||||
var sb strings.Builder
|
||||
sb.Grow(l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
sb.WriteByte(randomCharset[defaultSecureRand.Intn(len(randomCharset))])
|
||||
}
|
||||
return string(bs)
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// Int63 returns a cryptographically secure random int63.
|
||||
|
@ -44,3 +44,10 @@ func TestRandomUint64(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkString(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
String(32)
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
type secureSource struct {
|
||||
rd io.Reader
|
||||
mut sync.Mutex
|
||||
buf [8]byte
|
||||
}
|
||||
|
||||
func newSecureSource() *secureSource {
|
||||
@ -47,18 +48,15 @@ func (s *secureSource) Read(p []byte) (int, error) {
|
||||
}
|
||||
|
||||
func (s *secureSource) Uint64() uint64 {
|
||||
var buf [8]byte
|
||||
|
||||
// Read eight bytes of entropy from the buffered, secure random number
|
||||
// generator. The buffered reader isn't concurrency safe, so we lock
|
||||
// around that.
|
||||
s.mut.Lock()
|
||||
_, err := io.ReadFull(s.rd, buf[:])
|
||||
s.mut.Unlock()
|
||||
defer s.mut.Unlock()
|
||||
|
||||
_, err := io.ReadFull(s.rd, s.buf[:])
|
||||
if err != nil {
|
||||
panic("randomness failure: " + err.Error())
|
||||
}
|
||||
|
||||
// Grab those bytes as an uint64
|
||||
return binary.BigEndian.Uint64(buf[:])
|
||||
return binary.LittleEndian.Uint64(s.buf[:])
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user