Created
June 18, 2017 21:02
-
-
Save gobwas/1d5e4ccb24ee9bfc56eca8ac5ad8efd7 to your computer and use it in GitHub Desktop.
Stack growth test
This file contains hidden or 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 ( | |
"encoding/binary" | |
"flag" | |
"fmt" | |
"log" | |
"os" | |
"reflect" | |
"runtime" | |
"runtime/pprof" | |
"unsafe" | |
) | |
var ( | |
memprofile = flag.String("memprofile", "", "write memory profile to `file`") | |
memprofilerate = flag.Int("memprofilerate", 0, "memory profile rate") | |
cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") | |
) | |
//go:linkname runtimeMoreStack runtime.morestack | |
func runtimeMoreStack() | |
func main() { | |
flag.Parse() | |
if *memprofilerate != 0 { | |
runtime.MemProfileRate = *memprofilerate | |
} | |
if *cpuprofile != "" { | |
f, err := os.Create(*cpuprofile) | |
if err != nil { | |
log.Fatal("could not create CPU profile: ", err) | |
} | |
if err := pprof.StartCPUProfile(f); err != nil { | |
log.Fatal("could not start CPU profile: ", err) | |
} | |
defer pprof.StopCPUProfile() | |
} | |
done := make(chan struct{}) | |
runGrower(done) | |
<-done | |
if *memprofile != "" { | |
f, err := os.Create(*memprofile) | |
if err != nil { | |
log.Fatal("could not create memory profile: ", err) | |
} | |
runtime.GC() // get up-to-date statistics | |
if err := pprof.WriteHeapProfile(f); err != nil { | |
log.Fatal("could not write memory profile: ", err) | |
} | |
f.Close() | |
} | |
} | |
//func unsafer(done chan struct{}) { | |
// defer close(done) | |
// var arr [8]byte | |
// ptr := uintptr(unsafe.Pointer(&arr)) | |
// hdr := reflect.SliceHeader{Data: ptr, Len: len(arr), Cap: len(arr)} | |
// bts := *(*[]byte)(unsafe.Pointer(&hdr)) | |
// fmt.Println(bts) | |
//} | |
func runGrower(done chan struct{}) { | |
defer close(done) | |
for i := 0; i < 4; i++ { | |
g := grower{} | |
g.growSlice() | |
fmt.Println("grow after", g.stackSize) | |
} | |
} | |
type grower struct { | |
sp uintptr | |
stackSize int64 | |
} | |
func (g *grower) checkStackGrowth(p uintptr) (diff int64) { | |
if g.sp != 0 { | |
diff = int64(g.sp) - int64(p) | |
if diff > 0 { | |
g.stackSize += diff | |
} | |
} | |
g.sp = p | |
return | |
} | |
func (g *grower) growSlice() uintptr { | |
var arr [128]byte | |
ptr := uintptr(unsafe.Pointer(&arr)) | |
hdr := &reflect.SliceHeader{Data: ptr, Len: len(arr), Cap: len(arr)} | |
bts := *(*[]byte)(unsafe.Pointer(hdr)) | |
nuevo := g.doGrowSlice(bts, ptr) | |
acthdr := *(*reflect.SliceHeader)(unsafe.Pointer(&bts)) | |
fmt.Println("after", acthdr.Data, ptr) | |
return nuevo | |
} | |
func (g *grower) doGrowSlice(p []byte, original uintptr) uintptr { | |
var bts [512]byte | |
_ = len(bts) | |
// Check stack growth according to orig arg (the highest arg on stack | |
// frame). | |
g.checkStackGrowth(uintptr(unsafe.Pointer(&original))) | |
hdr := *(*reflect.SliceHeader)(unsafe.Pointer(&p)) | |
if actual := hdr.Data; actual != original { | |
return actual | |
} | |
Counter(p).Inc() | |
return g.doGrowSlice(p, original) | |
} | |
func (g *grower) growUint64() uintptr { | |
var v uint64 | |
return g.doGrowUint64(&v, uintptr(unsafe.Pointer(&v))) | |
} | |
func (g *grower) doGrowUint64(v *uint64, original uintptr) uintptr { | |
var bts [512]byte | |
_ = len(bts) | |
// Check stack growth according to orig arg (the highest arg on stack | |
// frame). | |
g.checkStackGrowth(uintptr(unsafe.Pointer(&original))) | |
if actual := uintptr(unsafe.Pointer(v)); actual != original { | |
return actual | |
} | |
*v++ | |
return g.doGrowUint64(v, original) | |
} | |
type Counter []byte | |
func (c Counter) Inc() { | |
c.Set(c.Val() + 1) | |
} | |
func (c Counter) Val() uint64 { | |
return binary.LittleEndian.Uint64([]byte(c)[:8]) | |
} | |
func (c Counter) Set(v uint64) { | |
binary.LittleEndian.PutUint64([]byte(c)[:8], v) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment