Skip to content

Commit

Permalink
Add benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
delphinus committed May 21, 2017
1 parent 9b86e7b commit ab1aa63
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Makefile
Expand Up @@ -12,3 +12,6 @@ test: ## Run tests only
test-coverage: ## Run tests and show coverage in browser
go test -v -coverprofile=$(COVERAGE) -covermode=count
go tool cover -html=$(COVERAGE)

benchmark: ## Do benchmarks
go test -bench . -benchmem
15 changes: 15 additions & 0 deletions README.md
Expand Up @@ -21,3 +21,18 @@ func main() {
// simple password: JEVGqkiW
}
```

## Benchmark

```go
go test -bench . -benchmem
BenchmarkRandomString/Runes-8 200000 10915 ns/op 1312 B/op 2 allocs/op
BenchmarkRandomString/Bytes-8 200000 8815 ns/op 512 B/op 2 allocs/op
BenchmarkRandomString/Remainder-8 200000 6466 ns/op 512 B/op 2 allocs/op
BenchmarkRandomString/Mask-8 200000 7421 ns/op 512 B/op 2 allocs/op
BenchmarkRandomString/MaskImproved-8 1000000 1690 ns/op 512 B/op 2 allocs/op
BenchmarkRandomString/MaskSource-8 1000000 1437 ns/op 512 B/op 2 allocs/op
BenchmarkRandomString/Generate-8 1000000 1437 ns/op 512 B/op 2 allocs/op
PASS
ok github.com/delphinus/random-string 11.708s
```
187 changes: 187 additions & 0 deletions benchmark_test.go
@@ -0,0 +1,187 @@
package randomString

// http://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-testLength-in-golang

import (
"math"
"math/rand"
"sync"
"testing"
"time"
)

const testLetterBytes = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"
const testLength = 256

var testLetterRunes = []rune(testLetterBytes)
var testMutex sync.Mutex
var testSrc = rand.NewSource(time.Now().UnixNano())
var testBits = uint(math.Log2(float64(len(testLetterBytes)))) + 1
var testMask = int64(1<<testBits - 1)
var testMax = 63 / testBits

func randStringRunes(n int) string {
by := make([]rune, n)
for i := range by {
by[i] = testLetterRunes[rand.Intn(len(testLetterRunes))]
}
return string(by)
}

func randStringBytes(n int) string {
by := make([]byte, n)
for i := range by {
by[i] = testLetterBytes[rand.Intn(len(testLetterBytes))]
}
return string(by)
}

func randStringRemainder(n int) string {
by := make([]byte, n)
for i := range by {
by[i] = testLetterBytes[rand.Int63()%int64(len(testLetterBytes))]
}
return string(by)
}

func randStringMask(n int) string {
by := make([]byte, n)
for i := 0; i < n; {
if idx := int(rand.Int63() & testMask); idx < len(testLetterBytes) {
by[i] = testLetterBytes[idx]
i++
}
}
return string(by)
}

func randStringMaskImproved(n int) string {
by := make([]byte, n)
for i, cache, remain := n-1, rand.Int63(), testMax; i >= 0; {
if remain == 0 {
cache, remain = rand.Int63(), testMax
}
if idx := int(cache & testMask); idx < len(testLetterBytes) {
by[i] = testLetterBytes[idx]
i--
}
cache >>= testBits
remain--
}
return string(by)
}

func randStringSource(n int) string {
by := make([]byte, n)
testMutex.Lock()
cache := testSrc.Int63()
testMutex.Unlock()
for i, remain := n-1, testMax; i >= 0; {
if remain == 0 {
testMutex.Lock()
cache = testSrc.Int63()
testMutex.Unlock()
remain = testMax
}
if idx := int(cache & testMask); idx < len(testLetterBytes) {
by[i] = testLetterBytes[idx]
i--
}
cache >>= testBits
remain--
}
return string(by)
}

func BenchmarkRandomString(b *testing.B) {
b.Run("Runes", func(b *testing.B) {
/*
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = randStringRunes(testLength)
}
})
*/
for i := 0; i < b.N; i++ {
_ = randStringRunes(testLength)
}
})

b.Run("Bytes", func(b *testing.B) {
/*
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = randStringBytes(testLength)
}
})
*/
for i := 0; i < b.N; i++ {
_ = randStringBytes(testLength)
}
})

b.Run("Remainder", func(b *testing.B) {
/*
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = randStringRemainder(testLength)
}
})
*/
for i := 0; i < b.N; i++ {
_ = randStringRemainder(testLength)
}
})

b.Run("Mask", func(b *testing.B) {
/*
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = randStringMask(testLength)
}
})
*/
for i := 0; i < b.N; i++ {
_ = randStringMask(testLength)
}
})

b.Run("MaskImproved", func(b *testing.B) {
/*
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = randStringMaskImproved(testLength)
}
})
*/
for i := 0; i < b.N; i++ {
_ = randStringMaskImproved(testLength)
}
})

b.Run("MaskSource", func(b *testing.B) {
/*
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = randStringSource(testLength)
}
})
*/
for i := 0; i < b.N; i++ {
_ = randStringSource(testLength)
}
})

b.Run("Generate", func(b *testing.B) {
/*
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = Generate(testLength)
}
})
*/
for i := 0; i < b.N; i++ {
_ = Generate(testLength)
}
})
}

0 comments on commit ab1aa63

Please sign in to comment.