Sunday, August 23, 2020

Exploring Go Race Detector

   

I got to know about Golang Race Detector from a colleague & wanted to give this a try. Here is the sample code on my github  I tested (also, same code on Go playground for quicker testing).

We can use race detector in multiple ways:

1) Using go run -race with the specific go file:
Babus-MacBook-Pro:Race_Tests_inGolang babuneelam$ go run -race main.go
flag:  true
==================
WARNING: DATA RACE
Write at 0x0000012742a1 by goroutine 7:
  main.writer()
      /Users/babuneelam/Projects/GoProjects/Race_Tests_inGolang/main.go:12 +0x55

Previous read at 0x0000012742a1 by main goroutine:
  main.reader()
      /Users/babuneelam/Projects/GoProjects/Race_Tests_inGolang/main.go:19 +0x3e
  main.main()
      /Users/babuneelam/Projects/GoProjects/Race_Tests_inGolang/main.go:27 +0x5e

Goroutine 7 (running) created at:
  main.main()
      /Users/babuneelam/Projects/GoProjects/Race_Tests_inGolang/main.go:26 +0x59
==================
flag:  true
^Csignal: interrupt
Babus-MacBook-Pro:Race_Tests_inGolang babuneelam

 

2) Build the go program with "-race" flag:

Babus-MacBook-Pro:Race_Tests_inGolang babuneelam$ go build -race
Babus-MacBook-Pro:Race_Tests_inGolang babuneelam

Then, run the program:

Babus-MacBook-Pro:Race_Tests_inGolang babuneelam$ ./racetest 
flag:  true
==================
WARNING: DATA RACE
Write at 0x0000012742a1 by goroutine 7:
  main.writer()
      /Users/babuneelam/Projects/GoProjects/Race_Tests_inGolang/main.go:12 +0x55

Previous read at 0x0000012742a1 by main goroutine:
  main.reader()
      /Users/babuneelam/Projects/GoProjects/Race_Tests_inGolang/main.go:19 +0x3e
  main.main()
      /Users/babuneelam/Projects/GoProjects/Race_Tests_inGolang/main.go:27 +0x5e

Goroutine 7 (running) created at:
  main.main()
      /Users/babuneelam/Projects/GoProjects/Race_Tests_inGolang/main.go:26 +0x59
==================
flag:  true
flag:  true
^C
Babus-MacBook-Pro:Race_Tests_inGolang babuneelam

 

3)  go test -race mypkg - TBD

4)  go install -race mypkg - TBD


As we can see the go race detector displayed us two pieces needed:
  1. A race warning  
  2. The two code locations that are causing the race
So, it's quite useful. To find the correct way of writing the above code, please check here.

However, this is not a static analysis tool. So, we need to run the program to detect the races. And only those races that happen during execution are detected. If we use race as part of test cases, then race detector is only as effective as your test coverage !!

In terms of performance, Golang Race Detector says this:

The cost of race detection varies by program, but for a typical program, memory usage may increase by 5-10x and execution time by 2-20x.

The race detector currently allocates an extra 8 bytes per defer and recover statement. Those extra allocations are not recovered until the goroutine exits. This means that if you have a long-running goroutine that is periodically issuing defer and recover calls, the program memory usage may grow without bound. These memory allocations will not show up in the output of runtime.ReadMemStats or runtime/pprof.

So, this is definitely not for production environments.

No comments:

UA-48797665-1