[Go profiling snippets] Bits of code useful for profiling purposes #tags: golang, go, profiling, performance, measurement
package main
import (
"bufio"
"fmt"
"io"
"log"
"math/rand"
"os"
"os/signal"
"syscall"
"time"
)
const WhereTo = "/storage/p01/dummy/data.bin"
const RandomSeed = 987123
const BufSize = 1 << 20
const FileSizeLimit = 1 << 30
func AppendByte(slice []byte, data ...byte) []byte {
m := len(slice)
n := m + len(data)
if n > cap(slice) { // if necessary, reallocate
// allocate double what's needed, for future growth.
newSlice := make([]byte, (n+1)*2)
copy(newSlice, slice)
slice = newSlice
}
slice = slice[0:n]
copy(slice[m:n], data)
return slice
}
type RandomInteger struct {
rand.Source
}
// New creates a new random reader with a time source.
func New() io.Reader {
return NewFrom(rand.NewSource(time.Now().UnixNano()))
}
// NewFrom creates a new reader from your own rand.Source
func NewFrom(src rand.Source) io.Reader {
return &RandomInteger{src}
}
// Read satisfies io.Reader
func (r *RandomInteger) Read(p []byte) (n int, err error) {
todo := len(p)
offset := 0
for {
val := int64(r.Int63())
for i := 0; i < 8; i++ {
p[offset] = byte(val)
todo--
if todo == 0 {
return len(p), nil
}
offset++
val >>= 8
}
}
}
func main() {
var b []byte
var output string = WhereTo
var bytecount int
var writer *bufio.Writer
var randbytes = make([]byte, 1024)
if len(os.Args) > 1 {
if os.Args[1] != "" {
output = os.Args[1]
}
}
// Cleanup on CTRL-C
sig := make(chan os.Signal, 2)
signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
go func() {
<-sig
fmt.Fprintf(os.Stdout,
"Wrote %d bytes to %s\n", bytecount, WhereTo)
os.Exit(0)
}()
source := rand.NewSource(RandomSeed)
r := NewFrom(source)
f, err := os.OpenFile(output, os.O_RDWR|os.O_CREATE, 0755)
f.Truncate(0) // Start out with empty file in all cases
writer = bufio.NewWriterSize(f, BufSize) // Writes out to file (f)
if err != nil {
fmt.Printf("%v\n", err)
}
for { // Loop over the bytes and keep appending until we reach limit
if bytecount >= FileSizeLimit {
break
}
b = make([]byte, 0)
for i := 0; i < 1024; i++ {
r.Read(randbytes)
b = AppendByte(b, randbytes...)
}
if n, err := writer.Write(b); err != nil {
log.Printf("%v\n", err)
} else {
bytecount += n
writer.Flush() // flush after every 1MB
}
fmt.Printf("\r%dKB", bytecount>>10) // Update count of KB in place
}
fmt.Printf("\n")
}
package main
import (
"fmt"
"time"
)
// SleepyTime - how long to sleep?
const SleepyTime = 100
// GoRoutines - how many lightweight threads do we want?
const GoRoutines = 100
func main() {
var ch chan struct{}
for i := 0; i < GoRoutines; i++ {
go func() {
for {
fmt.Printf("Sleeping for %d\n", SleepyTime)
time.Sleep(time.Microsecond * SleepyTime)
}
}()
}
// Block forever, otherwise main exits before go-routines
// have a chance to do anything substantial.
<-ch
}