Skip to content

Commit

Permalink
article: move assets to bench-time folder
Browse files Browse the repository at this point in the history
  • Loading branch information
changkun committed Nov 8, 2020
1 parent 77a03a0 commit a9be9a8
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 3 deletions.
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"files.associations": {
"*.go2": "go",
"chrono": "cpp"
}
}
6 changes: 3 additions & 3 deletions bench-time.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ go test -v -run=none -bench=WithTimer -benchtime=100000x -count=5 -cpuprofile cp

Sadly, the graph shows a chunk of useless information where most of the costs shows as `runtime.ReadMemStats`:

![pprof](./assets/bench-time-pprof1.png)
![pprof](./bench-time/pprof1.png)

This is because of the `StopTimer/StartTimer` implementation in the testing package calls `runtime.ReadMemStats`:

Expand Down Expand Up @@ -203,7 +203,7 @@ func (b *B) StopTimer() {

And re-run the test again, then we have:

![pprof](./assets/bench-time-pprof2.png)
![pprof](./bench-time/pprof2.png)

Have you noticed where the problem is? Yes, there is a heavy cost in calling `time.Now()` in a tight loop (not really surprising because it is a system call).

Expand Down Expand Up @@ -282,7 +282,7 @@ Thus, in terms of benchmarking, the actual measured time of a target code equals
to the execution time of target code plus the overhead of calling `now()`:

<p align="center">
<img src="./assets/bench-time.png">
<img src="./bench-time/flow.png">
</p>

Assume the target code consumes in `T` ns, and the overhead of `now()` is `t` ns.
Expand Down
60 changes: 60 additions & 0 deletions bench-time/bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package time_test

import (
"fmt"
"sync/atomic"
"testing"
"time"
)

func BenchmarkAtomic(b *testing.B) {
var v int32
var n = 1000000
for k := 1; k < n; k *= 10 {
b.Run(fmt.Sprintf("n-%d", k), func(b *testing.B) {
atomic.StoreInt32(&v, 0)
b.Run("with-timer", func(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
b.StartTimer()
for j := 0; j < k; j++ {
atomic.AddInt32(&v, 1)
}
}
})
atomic.StoreInt32(&v, 0)
b.Run("w/o-timer", func(b *testing.B) {
for i := 0; i < b.N; i++ {
for j := 0; j < k; j++ {
atomic.AddInt32(&v, 1)
}
}
})
})
}
}

func TestSolution(t *testing.T) {
var v int32
atomic.StoreInt32(&v, 0)
r := testing.Benchmark(func(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
// ... do extra stuff ...
b.StartTimer()
atomic.AddInt32(&v, 1)
}
})

// do calibration that removes the overhead of calling time.Now().
calibrate := func(d time.Duration, n int) time.Duration {
since := time.Duration(0)
for i := 0; i < n; i++ {
start := time.Now()
since += time.Since(start)
}
return (d - since) / time.Duration(n)
}

fmt.Printf("%v ns/op\n", calibrate(r.T, r.N))
}
17 changes: 17 additions & 0 deletions bench-time/cpp/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <iostream>
#include <chrono>

void empty() {}

int main() {
int n = 1000000;
for (int j = 0; j < 10; j++) {
std::chrono::nanoseconds since(0);
for (int i = 0; i < n; i++) {
auto start = std::chrono::steady_clock::now();
empty();
since += std::chrono::steady_clock::now() - start;
}
std::cout << "avg since: " << since.count() / n << "ns \n";
}
}
22 changes: 22 additions & 0 deletions bench-time/cpp/solution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <iostream>
#include <chrono>

void target() {}

int main() {
int n = 1000000;
for (int j = 0; j < 10; j++) {
std::chrono::nanoseconds since(0);
for (int i = 0; i < n; i++) {
auto start = std::chrono::steady_clock::now();
target();
since += std::chrono::steady_clock::now() - start;
}

auto overhead = -(std::chrono::steady_clock::now() -
std::chrono::steady_clock::now());
since -= overhead * n;

std::cout << "avg since: " << since.count() / n << "ns \n";
}
}
File renamed without changes
3 changes: 3 additions & 0 deletions bench-time/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module benchtime

go 1.16
File renamed without changes
File renamed without changes
File renamed without changes.

0 comments on commit a9be9a8

Please sign in to comment.