randbp

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 20, 2020 License: BSD-3-Clause Imports: 5 Imported by: 3

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

View Source
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

View Source
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

func GenerateRandomString(r *rand.Rand, maxLength int, runes []rune) string

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

func ShouldSampleWithRate(rate float64) bool

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

type Rand struct {
	*rand.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 New

func New(seed int64) Rand

New initializes a thread-safe, properly seeded Rand.

func (Rand) Read

func (r Rand) Read(p []byte) (int, error)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL