Documentation
¶
Overview ¶
Package randbp provides some random generator related features:
1. A thread-safe, properly seeded global *math/rand.Rand implementation.
2. Helper functions for common use cases.
Index ¶
Constants ¶
const Base64Runes = `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_+/=`
Base64Runes are all the runes allowed in standard and url safe base64 encodings.
This is a common, safe to use set of runes to be used with GenerateRandomString.
Variables ¶
var R = New(GetSeed())
R is a global thread-safe rng.
It embeds *math/rand.Rand, but properly seeded and safe for concurrent use.
It should be used instead of the global functions inside math/rand package.
For example, instead of this:
import "math/rand" i := rand.Uint64()
Use this:
import "github.com/reddit/baseplate.go/randbp" i := randbp.R.Uint64()
NOTE: Its Read function has worse performance comparing to rand's global rander or rand.Rand created with non-thread-safe source for small buffers. See the doc of Rand.Read for more details. All other functions (Uint64, Float64, etc.) have comparable performance to math/rand's implementations.
Functions ¶
func GenerateRandomString ¶
GenerateRandomString generates a random string with length [0, maxLength), and all characters limited to runes.
It could be used to help implement testing/quick.Generator interface.
func GetSeed ¶
func GetSeed() int64
GetSeed returns a seed for pseudo-random generator.
It tries to use crypto/rand to read an int64, and fallback to use current time if that fails for whatever reason.
func ShouldSampleWithRate ¶
ShouldSampleWithRate generates a random float64 in [0, 1) and check it against rate.
rate should be in the range of [0, 1]. When rate <= 0 this function always returns false; When rate >= 1 this function always returns true.
Types ¶
type LockedSource64 ¶
type LockedSource64 struct {
// contains filtered or unexported fields
}
LockedSource64 is a thread-safe implementation of rand.Source64.
NOTE: When using *LockedSource64 to create rand.Rand, its Read function will have a much worse performance comparing to rand's global rander or rand.Rand created with non-thread-safe source.
func NewLockedSource64 ¶
func NewLockedSource64(src rand.Source) *LockedSource64
NewLockedSource64 creates a *LockedSource64 from the given src.
func (*LockedSource64) Int63 ¶
func (ls *LockedSource64) Int63() (n int64)
Int63 implements rand.Source64.
It calls underlying source's Int63 with lock.
func (*LockedSource64) Seed ¶
func (ls *LockedSource64) Seed(seed int64)
Seed implements rand.Source64.
It calls underlying source's Seed with lock.
func (*LockedSource64) Uint64 ¶
func (ls *LockedSource64) Uint64() (n uint64)
Uint64 implements rand.Source64.
If the underlying source implements rand.Source64, it calls its Uint64 with lock. Otherwise, it calls its Int64 twice with lock.
type Rand ¶
Rand embeds *math/rand.Rand.
All functions besides Read are directly calling the embedded rand.Rand. When initialized with New(), all functions are safe for concurrent use, and have comparable performance to the top level math/rand functions.
See the doc of Read function for more details on that one.
func (Rand) Read ¶
Read overrides math/rand's Read implementation with thread-safety.
It's safe for concurrent use and always returns len(p) with nil error.
Compare to math/rand.Read (the top level one) performance-wise, it has a constant ~1us overhead, which is significant when len(p) is small, but less significant when len(p) grows larger, and starts to outperform math/rand.Read when len(p) is very large because it only need to lock once. See the following sample benchmark result:
$ go test -bench Rand/Read -benchmem goos: darwin goarch: amd64 pkg: github.com/reddit/baseplate.go/randbp BenchmarkRand/Read/size-16/math/rand-8 8213564 138 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-16/crypto/rand-8 9739500 123 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-16/randbp-8 979442 1329 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-64/math/rand-8 5289319 227 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-64/crypto/rand-8 6050103 197 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-64/randbp-8 911760 1301 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-256/math/rand-8 4223463 274 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-256/crypto/rand-8 2263252 534 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-256/randbp-8 940459 1333 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-512/math/rand-8 2455426 481 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-512/crypto/rand-8 1000000 1008 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-512/randbp-8 885555 1445 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-1024/math/rand-8 1275535 925 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-1024/crypto/rand-8 636202 1980 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-1024/randbp-8 800511 1630 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-4096/math/rand-8 310982 3765 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-4096/crypto/rand-8 159490 7538 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-4096/randbp-8 511124 2319 ns/op 0 B/op 0 allocs/op BenchmarkRand/Read/size-1048576/math/rand-8 1341 860809 ns/op 6255 B/op 0 allocs/op BenchmarkRand/Read/size-1048576/crypto/rand-8 838 1349225 ns/op 10016 B/op 0 allocs/op BenchmarkRand/Read/size-1048576/randbp-8 5330 238657 ns/op 1582 B/op 0 allocs/op PASS ok github.com/reddit/baseplate.go/randbp 29.982s
Regardless performance, it's never suitable for security purpose, and you should always use crypto/rand for that instead.