Last active
March 26, 2019 10:43
-
-
Save wrfly/7d6249e6f379bb348663886eb6b5a90c to your computer and use it in GitHub Desktop.
simple sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"math/rand" | |
"sync" | |
"time" | |
"github.com/wrfly/gua" | |
) | |
type c struct { | |
Ratio float32 `default:"0.5" desc:"sample ratio"` | |
Total uint `default:"1000" desc:"total number to test"` | |
} | |
const bucketSize = 100 | |
type sampler struct { | |
ratio float32 | |
m sync.RWMutex | |
i uint8 | |
buckets []bool | |
threshold int32 | |
} | |
func (s *sampler) pass() bool { | |
return rand.Int31n(bucketSize) < s.threshold | |
} | |
func (s *sampler) pass1() bool { | |
s.m.RLock() | |
s.i++ | |
s.i = s.i % bucketSize | |
x := s.i | |
s.m.RUnlock() | |
return s.buckets[x] | |
} | |
func (s *sampler) resetRatio(ratio float32) { | |
if ratio > 1 || ratio < 0 { | |
panic("bad ratio, must in [0,1]") | |
} | |
s.m.Lock() | |
s.ratio = ratio | |
s.threshold = int32(ratio * 100) | |
buckets := make([]bool, bucketSize) | |
for i := 0; i < int(ratio*100); i++ { | |
random := rand.Int31n(bucketSize) | |
if buckets[random] { | |
i-- | |
} else { | |
buckets[random] = true | |
} | |
} | |
s.buckets = buckets | |
s.m.Unlock() | |
} | |
func newSampler(ratio float32) *sampler { | |
s := &sampler{} | |
s.resetRatio(ratio) | |
return s | |
} | |
func main() { | |
config := new(c) | |
gua.Parse(config) | |
var ( | |
passed uint | |
i uint | |
) | |
s := newSampler(config.Ratio) | |
start := time.Now() | |
for ; i < config.Total; i++ { | |
if s.pass1() { | |
passed++ | |
} | |
} | |
printResult(s, passed, config.Total, start) | |
passed, i = 0, 0 | |
start = time.Now() | |
for ; i < config.Total; i++ { | |
if s.pass1() { | |
passed++ | |
} | |
} | |
printResult(s, passed, config.Total, start) | |
passed, i = 0, 0 | |
start = time.Now() | |
for ; i < config.Total; i++ { | |
if s.pass() { | |
passed++ | |
} | |
} | |
printResult(s, passed, config.Total, start) | |
fmt.Println() | |
} | |
func printResult(s *sampler, passed, total uint, start time.Time) { | |
fmt.Printf("ratio=%.2f result=%.2f%% (%d/%d) [%s]\n", | |
s.ratio, | |
float32(passed)/float32(total)*100, | |
passed, total, time.Now().Sub(start)) | |
} |
Author
wrfly
commented
Mar 26, 2019
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment