mirror of
https://github.com/golang/go
synced 2024-11-25 08:57:58 -07:00
add simple garbage collector benchmarks to dashboard
R=agl1 CC=golang-dev https://golang.org/cl/207043
This commit is contained in:
parent
96476b4c3e
commit
d3be2e3e0a
@ -16,7 +16,7 @@ rm -rf "$GOROOT"/pkg/${GOOS}_$GOARCH
|
|||||||
rm -f "$GOROOT"/lib/*.a
|
rm -f "$GOROOT"/lib/*.a
|
||||||
for i in lib9 libbio libcgo libmach cmd pkg \
|
for i in lib9 libbio libcgo libmach cmd pkg \
|
||||||
../misc/cgo/gmp ../misc/cgo/stdio \
|
../misc/cgo/gmp ../misc/cgo/stdio \
|
||||||
../test/bench
|
../test/bench ../test/garbage
|
||||||
do(
|
do(
|
||||||
cd "$GOROOT"/src/$i || exit 1
|
cd "$GOROOT"/src/$i || exit 1
|
||||||
if test -f clean.bash; then
|
if test -f clean.bash; then
|
||||||
|
@ -169,7 +169,7 @@ install: install.dirs
|
|||||||
|
|
||||||
test: test.dirs
|
test: test.dirs
|
||||||
|
|
||||||
bench: bench.dirs
|
bench: bench.dirs ../../test/garbage.bench
|
||||||
|
|
||||||
nuke: nuke.dirs
|
nuke: nuke.dirs
|
||||||
rm -rf "$(GOROOT)"/pkg/*
|
rm -rf "$(GOROOT)"/pkg/*
|
||||||
|
27
test/garbage/Makefile
Normal file
27
test/garbage/Makefile
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
include ../../src/Make.$(GOARCH)
|
||||||
|
|
||||||
|
ALL=\
|
||||||
|
parser\
|
||||||
|
peano\
|
||||||
|
tree\
|
||||||
|
|
||||||
|
all: $(ALL)
|
||||||
|
|
||||||
|
%.$O: %.go
|
||||||
|
$(GC) $*.go
|
||||||
|
|
||||||
|
%: %.$O
|
||||||
|
$(LD) -o $@ $*.$O
|
||||||
|
|
||||||
|
%.bench: %
|
||||||
|
./$*
|
||||||
|
|
||||||
|
bench: $(addsuffix .bench, $(ALL))
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.[$(OS)] $(ALL)
|
||||||
|
|
@ -15,6 +15,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isGoFile(dir *os.Dir) bool {
|
func isGoFile(dir *os.Dir) bool {
|
||||||
@ -66,26 +67,31 @@ func parseDir(dirpath string) map[string]*ast.Package {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
st := &runtime.MemStats
|
st := &runtime.MemStats
|
||||||
n := flag.Int("n", 10, "iterations")
|
n := flag.Int("n", 4, "iterations")
|
||||||
p := flag.Int("p", len(packages), "# of packages to keep in memory")
|
p := flag.Int("p", len(packages), "# of packages to keep in memory")
|
||||||
flag.BoolVar(&st.DebugGC, "d", st.DebugGC, "print GC debugging info (pause times)")
|
flag.BoolVar(&st.DebugGC, "d", st.DebugGC, "print GC debugging info (pause times)")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
var t0 int64
|
||||||
pkgroot := os.Getenv("GOROOT") + "/src/pkg/"
|
pkgroot := os.Getenv("GOROOT") + "/src/pkg/"
|
||||||
for i := -1; i < *n; i++ {
|
for pass := 0; pass < 2; pass++ {
|
||||||
parsed := make([]map[string]*ast.Package, *p)
|
// Once the heap is grown to full size, reset counters.
|
||||||
for j := range parsed {
|
// This hides the start-up pauses, which are much smaller
|
||||||
parsed[j] = parseDir(pkgroot + packages[j%len(packages)])
|
// than the normal pauses and would otherwise make
|
||||||
}
|
// the average look much better than it actually is.
|
||||||
if i == -1 {
|
st.NumGC = 0
|
||||||
// Now that heap is grown to full size, reset counters.
|
st.PauseNs = 0
|
||||||
// This hides the start-up pauses, which are much smaller
|
t0 = time.Nanoseconds()
|
||||||
// than the normal pauses and would otherwise make
|
|
||||||
// the average look much better than it actually is.
|
for i := 0; i < *n; i++ {
|
||||||
st.NumGC = 0
|
parsed := make([]map[string]*ast.Package, *p)
|
||||||
st.PauseNs = 0
|
for j := range parsed {
|
||||||
|
parsed[j] = parseDir(pkgroot + packages[j%len(packages)])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
runtime.GC()
|
||||||
}
|
}
|
||||||
|
t1 := time.Nanoseconds()
|
||||||
|
|
||||||
fmt.Printf("Alloc=%d/%d Heap=%d/%d Mallocs=%d PauseTime=%.3f/%d = %.3f\n",
|
fmt.Printf("Alloc=%d/%d Heap=%d/%d Mallocs=%d PauseTime=%.3f/%d = %.3f\n",
|
||||||
st.Alloc, st.TotalAlloc,
|
st.Alloc, st.TotalAlloc,
|
||||||
@ -97,6 +103,10 @@ func main() {
|
|||||||
for _, s := range st.BySize {
|
for _, s := range st.BySize {
|
||||||
fmt.Printf("%10d %10d %10d\n", s.Size, s.Mallocs, s.Frees)
|
fmt.Printf("%10d %10d %10d\n", s.Size, s.Mallocs, s.Frees)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Standard gotest benchmark output, collected by build dashboard.
|
||||||
|
fmt.Printf("garbage.BenchmarkParser %d %d ns/op\n", *n, (t1-t0)/int64(*n))
|
||||||
|
fmt.Printf("garbage.BenchmarkParserPause %d %d ns/op\n", st.NumGC, int64(st.PauseNs)/int64(st.NumGC))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
137
test/garbage/peano.go
Normal file
137
test/garbage/peano.go
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// $G $F.go && $L $F.$A && ./$A.out
|
||||||
|
|
||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type Number struct {
|
||||||
|
next *Number
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------
|
||||||
|
// Peano primitives
|
||||||
|
|
||||||
|
func zero() *Number { return nil }
|
||||||
|
|
||||||
|
|
||||||
|
func is_zero(x *Number) bool { return x == nil }
|
||||||
|
|
||||||
|
|
||||||
|
func add1(x *Number) *Number {
|
||||||
|
e := new(Number)
|
||||||
|
e.next = x
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func sub1(x *Number) *Number { return x.next }
|
||||||
|
|
||||||
|
|
||||||
|
func add(x, y *Number) *Number {
|
||||||
|
if is_zero(y) {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
return add(add1(x), sub1(y))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func mul(x, y *Number) *Number {
|
||||||
|
if is_zero(x) || is_zero(y) {
|
||||||
|
return zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
return add(mul(x, sub1(y)), x)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func fact(n *Number) *Number {
|
||||||
|
if is_zero(n) {
|
||||||
|
return add1(zero())
|
||||||
|
}
|
||||||
|
|
||||||
|
return mul(fact(sub1(n)), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------
|
||||||
|
// Helpers to generate/count Peano integers
|
||||||
|
|
||||||
|
func gen(n int) *Number {
|
||||||
|
if n > 0 {
|
||||||
|
return add1(gen(n - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
return zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func count(x *Number) int {
|
||||||
|
if is_zero(x) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return count(sub1(x)) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func check(x *Number, expected int) {
|
||||||
|
var c = count(x)
|
||||||
|
if c != expected {
|
||||||
|
panic("error: found ", c, "; expected ", expected, "\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------
|
||||||
|
// Test basic functionality
|
||||||
|
|
||||||
|
func verify() {
|
||||||
|
check(zero(), 0)
|
||||||
|
check(add1(zero()), 1)
|
||||||
|
check(gen(10), 10)
|
||||||
|
|
||||||
|
check(add(gen(3), zero()), 3)
|
||||||
|
check(add(zero(), gen(4)), 4)
|
||||||
|
check(add(gen(3), gen(4)), 7)
|
||||||
|
|
||||||
|
check(mul(zero(), zero()), 0)
|
||||||
|
check(mul(gen(3), zero()), 0)
|
||||||
|
check(mul(zero(), gen(4)), 0)
|
||||||
|
check(mul(gen(3), add1(zero())), 3)
|
||||||
|
check(mul(add1(zero()), gen(4)), 4)
|
||||||
|
check(mul(gen(3), gen(4)), 12)
|
||||||
|
|
||||||
|
check(fact(zero()), 1)
|
||||||
|
check(fact(add1(zero())), 1)
|
||||||
|
check(fact(gen(5)), 120)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------
|
||||||
|
// Factorial
|
||||||
|
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
st := &runtime.MemStats
|
||||||
|
t0 := time.Nanoseconds()
|
||||||
|
verify()
|
||||||
|
for i := 0; i <= 9; i++ {
|
||||||
|
print(i, "! = ", count(fact(gen(i))), "\n")
|
||||||
|
}
|
||||||
|
runtime.GC()
|
||||||
|
t1 := time.Nanoseconds()
|
||||||
|
|
||||||
|
fmt.Printf("garbage.BenchmarkPeano 1 %d ns/op\n", t1-t0)
|
||||||
|
fmt.Printf("garbage.BenchmarkPeanoPause %d %d ns/op\n", st.NumGC, int64(st.PauseNs)/int64(st.NumGC))
|
||||||
|
}
|
104
test/garbage/tree.go
Normal file
104
test/garbage/tree.go
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of "The Computer Language Benchmarks Game" nor the
|
||||||
|
name of "The Computer Language Shootout Benchmarks" nor the names of
|
||||||
|
its contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The Computer Language Benchmarks Game
|
||||||
|
* http://shootout.alioth.debian.org/
|
||||||
|
*
|
||||||
|
* contributed by The Go Authors.
|
||||||
|
* based on C program by Kevin Carson
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var n = flag.Int("n", 16, "depth")
|
||||||
|
|
||||||
|
type Node struct {
|
||||||
|
item int
|
||||||
|
left, right *Node
|
||||||
|
}
|
||||||
|
|
||||||
|
func bottomUpTree(item, depth int) *Node {
|
||||||
|
if depth <= 0 {
|
||||||
|
return &Node{item: item}
|
||||||
|
}
|
||||||
|
return &Node{item, bottomUpTree(2*item-1, depth-1), bottomUpTree(2*item, depth-1)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) itemCheck() int {
|
||||||
|
if n.left == nil {
|
||||||
|
return n.item
|
||||||
|
}
|
||||||
|
return n.item + n.left.itemCheck() - n.right.itemCheck()
|
||||||
|
}
|
||||||
|
|
||||||
|
const minDepth = 4
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
t0 := time.Nanoseconds()
|
||||||
|
|
||||||
|
maxDepth := *n
|
||||||
|
if minDepth+2 > *n {
|
||||||
|
maxDepth = minDepth + 2
|
||||||
|
}
|
||||||
|
stretchDepth := maxDepth + 1
|
||||||
|
|
||||||
|
check := bottomUpTree(0, stretchDepth).itemCheck()
|
||||||
|
fmt.Printf("stretch tree of depth %d\t check: %d\n", stretchDepth, check)
|
||||||
|
|
||||||
|
longLivedTree := bottomUpTree(0, maxDepth)
|
||||||
|
|
||||||
|
for depth := minDepth; depth <= maxDepth; depth += 2 {
|
||||||
|
iterations := 1 << uint(maxDepth-depth+minDepth)
|
||||||
|
check = 0
|
||||||
|
|
||||||
|
for i := 1; i <= iterations; i++ {
|
||||||
|
check += bottomUpTree(i, depth).itemCheck()
|
||||||
|
check += bottomUpTree(-i, depth).itemCheck()
|
||||||
|
}
|
||||||
|
fmt.Printf("%d\t trees of depth %d\t check: %d\n", iterations*2, depth, check)
|
||||||
|
}
|
||||||
|
fmt.Printf("long lived tree of depth %d\t check: %d\n", maxDepth, longLivedTree.itemCheck())
|
||||||
|
|
||||||
|
t1 := time.Nanoseconds()
|
||||||
|
st := &runtime.MemStats
|
||||||
|
|
||||||
|
// Standard gotest benchmark output, collected by build dashboard.
|
||||||
|
fmt.Printf("garbage.BenchmarkTree %d %d ns/op\n", *n, (t1-t0)/int64(*n))
|
||||||
|
fmt.Printf("garbage.BenchmarkTreePause %d %d ns/op\n", st.NumGC, int64(st.PauseNs)/int64(st.NumGC))
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user