Created
June 28, 2021 16:26
-
-
Save chris124567/afc7c198a2fc1b995bd816556022ed80 to your computer and use it in GitHub Desktop.
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 ( | |
"crypto/sha256" | |
"fmt" | |
"hash" | |
"math/rand" | |
"os" | |
"runtime/pprof" | |
"strconv" | |
"sync" | |
"testing" | |
"unsafe" | |
) | |
var bufPool = sync.Pool{ | |
New: func() interface{} { | |
// length of a sha256 hash | |
b := make([]byte, 256) | |
return &b | |
}, | |
} | |
var hashPool = sync.Pool{ | |
New: func() interface{} { | |
return sha256.New() | |
}, | |
} | |
func foo(n int) string { | |
// get buffer from pool | |
bufptr := bufPool.Get().(*[]byte) | |
defer bufPool.Put(bufptr) | |
buf := *bufptr | |
// reset buf | |
buf = buf[:0] | |
// what you suggested: | |
// var ba [256]byte | |
// buf := ba[:0] | |
// get hash object from pool | |
h := hashPool.Get().(hash.Hash) | |
defer hashPool.Put(h) | |
h.Reset() | |
x := strconv.AppendInt(buf, int64(n), 10) | |
for i := 0; i < 100000; i++ { | |
h.Write(x) | |
} | |
// reset whatever strconv.AppendInt put in the buf | |
buf = buf[:0] | |
sum := h.Sum(buf) | |
// this may seem like it "should" allocate, but it does not | |
// 256 bytes fits in the stack. if you experiment with other values | |
// like 99999, you will find it will allocate because the stack space | |
// isnt that large | |
b := make([]byte, 0, 256) | |
for i := 0; i < int(sum[0]); i++ { | |
x := sum[(i*7+1)%len(sum)] ^ sum[(i*5+3)%len(sum)] | |
c := "abcdefghijklmnopqrstuvwxyz"[x%26] | |
b = append(b, c) | |
} | |
sum = sum[:0] // reset | |
sum = append(sum, b...) | |
return *(*string)(unsafe.Pointer(&sum)) | |
} | |
func main() { | |
cpufile, err := os.Create("cpu.pprof") | |
if err != nil { | |
panic(err) | |
} | |
err = pprof.StartCPUProfile(cpufile) | |
if err != nil { | |
panic(err) | |
} | |
defer cpufile.Close() | |
defer pprof.StopCPUProfile() | |
// ensure function output is accurate | |
if foo(12345) == "aajmtxaattdzsxnukawxwhmfotnm" { | |
fmt.Println("Test PASS") | |
} else { | |
fmt.Println("Test FAIL") | |
} | |
fmt.Println("Allocs:", int(testing.AllocsPerRun(100, func() { | |
foo(rand.Int()) | |
}))) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment