Go Benchmark how does it work - go

I've got my Go benchmark working with my API calls but I'm not exactly sure what it means below:
$ go test intapi -bench=. -benchmem -cover -v -cpuprofile=cpu.out
=== RUN TestAuthenticate
--- PASS: TestAuthenticate (0.00 seconds)
PASS
BenchmarkAuthenticate 20000 105010 ns/op 3199 B/op 49 allocs/op
coverage: 0.0% of statements
ok intapi 4.349s
How does it know how many calls it should make? I do have a loop with b.N as size of the loop but how does Golang know how many to run?
Also I now have cpu profile file. How can I use this to view it?

From TFM:
The benchmark function must run the target code b.N times. The benchmark package will vary b.N until the benchmark function lasts long enough to be timed reliably.

Related

How to print gc traces by embedding gctrace env with go binary?

I have a simple program that prints hello world. To emit gc trace information am using following command by directly running the main.go file
$ GODEBUG=gctrace=1 go run main.go
gc 1 #0.011s 1%: 0.020+1.3+0.056 ms clock, 0.24+0.62/0.38/1.6+0.67 ms cpu, 4->4->0 MB, 5 MB goal, 12 P
Hello Playground
gc 2 #0.021s 0%: 0.004+0.55+0.006 ms clock, 0.052+0.12/0.36/0.49+0.079 ms cpu, 4->4->0 MB, 5 MB goal, 12 P
Question
Is there a way to build the binary and yet print the gctraces while running the binary directly and without explicitly passing the GODEBUG=gctrace=1 to the binary?
(OR)
How to build binary with GODEBUG=gctrace=1 without explicitly mentioning at runtime ?
$ go build -O main // (builds binary main)
$ ./main // doesn't print gc trace information
Hello Playground
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, playground")
}

Go Coverage over multiple package and Gitlab Coverage Badge

I'm trying to display an accurate coverage badge for my gitlab project.
Thing is I have several packages, in gitlab-ci.yml, I run
go test $(go list ./... | grep -v /vendor/) -v -coverprofile .testCoverage.txt
and my output is something like that:
$ go test -coverprofile=coverage.txt -covermode=atomic ./...
ok gitlab.com/[MASKED]/pam 10.333s coverage: 17.2% of statements
ok gitlab.com/[MASKED]/pam/acquisition 0.004s coverage: 57.7% of statements
ok gitlab.com/[MASKED]/pam/acquisition/api 0.005s coverage: 72.1% of statements
ok gitlab.com/[MASKED]/pam/acquisition/ftp 24.936s coverage: 73.1% of statements
ok gitlab.com/[MASKED]/pam/repartition 0.004s coverage: 90.1% of statements
And my Test coverage parsing regex in Gitlab is:
^coverage:\s(\d+(?:\.\d+)?%)
If I check the .testCoverage, I get a lot of lines like that:
gitlab.com/[MASKED]/pam/repartition/repartition.go:54.33,56.5 1 1
So, it gives me a result of 90.1% when it is only the coverage of the last package.
How should I do it ?
According to this answer,
I just needed another command:
go tool cover -func profile.cov
That will give you the result:
✗ go tool cover -func profile.cov
gitlab.com/[MASKED]/pam/acquisition/acquisition.go:17: FetchAll 0.0%
gitlab.com/[MASKED]/pam/acquisition/acquisition.go:32: TransformData 100.0%
gitlab.com/[MASKED]/pam/acquisition/acquisition_mocks.go:13: FetchMeters 0.0%
gitlab.com/[MASKED]/pam/repartition/repartition.go:102: GroupMetersByOperation 100.0%
gitlab.com/[MASKED]/pam/repartition/repartition.go:111: SetProrataRedistributed 71.4%
total: (statements) 68.7%
In gitlab, you can change the regex:
^coverage:\s(\d+(?:\.\d+)?%)
By
\(statements\)(?:\s+)?(\d+(?:\.\d+)?%)
Now, if you have mocks, coverage will include them, so you must remove them following this answer:
go test . -coverprofile profile.cov.tmp
cat profile.cov.tmp | grep -v "_mocks.go" > cover.out
tool cover -func profile.cov
Off course, all your mocks should be in files with suffix : _mocks.go
And it should work.
Hope it helps others!

No function names when using gperftools/pprof

I've been trying to get gperftools CPU profiling working on my program.
I'm running into an issue where all the function names in my program are pointer addresses when reported by pprof. Annoyingly, most of the function names from libraries I've linked are readable, but none from my program files are. Example below.
s979258ca% pprof --text ./hmiss hmiss.prof
Using local file ./hmiss.
Using local file hmiss.prof.
Total: 469 samples
152 32.4% 32.4% 152 32.4% 0x000000010ba6dd45
47 10.0% 42.4% 47 10.0% 0x000000010ba6d365
46 9.8% 52.2% 46 9.8% 0x000000010ba6d371
34 7.2% 59.5% 34 7.2% 0x000000010ba8a04a
32 6.8% 66.3% 32 6.8% 0x000000010ba6d35a
10 2.1% 68.4% 10 2.1% 0x000000010ba8873c
9 1.9% 70.4% 9 1.9% 0x00007fff63f409da
6 1.3% 71.6% 6 1.3% 0x000000010ba7feca
6 1.3% 72.9% 6 1.3% 0x00007fff63f40116
6 1.3% 74.2% 6 1.3% 0x00007fff63f409f2
5 1.1% 75.3% 5 1.1% 0x000000010ba6dd4c
...
What do I need to do to get my functions names included in the pprof output?
Here's what the process to get to the above point looks like for me, if it helps.
I build my program with the options below
clang++
"-std=c++17",
"-g",
"-O2",
"...cpp files..."
"-o",
"~/cpp/hmiss/hmiss",
"/usr/local/Cellar/gperftools/2.7/lib/libprofiler.dylib",
I enable CPU profiling with gprof by running
DYLD_FALLBACK_LIBRARY_PATH=/opt/local/lib CPUPROFILE=hmiss.prof ./hmiss
I then run pprof --text ./hmiss hmiss.prof
From an answer to a similar question I thought possibly including debugging symbols might get the names in there, but just building my program with -g didn't seem to help. Also, removing the -O2 flag did not help either.
Use google's pprof instead of brew's pprof https://github.com/google/pprof
I had a similar issue that pprof was only showing the binaries, not the function name and line. Also it was taking ages to produce the traces.
I found you can't call it as go tool pprof instead you must call ~/go/bin/pprof or have it on your path directly.

Remove half second delay when minitest starts?

Consider this output when I use the bash time utility to benchmark a trivial minitest run:
$time ruby spec/trivial_spec.rb
Run options: --seed 4156
# Running:
.
Finished in 0.001077s, 928.9209 runs/s, 928.9209 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
real 0m0.443s
user 0m0.341s
sys 0m0.083s
As you can see, the test itself runs almost instantly (0.001s), but actually permorming that test takes nearly half a second, presumably because of the load time of minitest itself.
Is there any way to remove this delay? Either through minitest config options or perhaps using another tool that preloads it?

does anybody have a simple pprof use on a go-executable?

I have looked at the article about profiling go programs, and I simple do not understand it. Do someone have a simple code example were the performance of code snippet is logged in text file by a profile-"object"?
Here are the commands I use for a simple CPU and memory profiling to get you started.
Let's say you made a benchmark function like this :
File something_test.go :
func BenchmarkProfileMe(b *testing.B) {
// execute the significant portion of the code you want to profile b.N times
}
In a shell script:
# -test XXX is a trick so you don't trigger other tests by asking a non existent specific test called literally XXX
# you can adapt the benchtime depending on the type of code you want to profile.
go test -v -bench ProfileMe -test.run XXX -cpuprofile cpu.pprof -memprofile mem.pprof -benchtime 10s
go tool pprof --text ./something.test cpu.pprof ## To get a CPU profile per function
go tool pprof --text ./something.test cpu.pprof --lines ## To get a CPU profile per line
go tool pprof --text ./something.test mem.pprof ## To get the memory profile
It will present you the hottests spots in each cases on the console.

Resources