SlideShare a Scribd company logo
1 of 60
Looking Inside a
Race Detector
InfoQ.com: News & Community Site
• Over 1,000,000 software developers, architects and CTOs read the site world-
wide every month
• 250,000 senior developers subscribe to our weekly newsletter
• Published in 4 languages (English, Chinese, Japanese and Brazilian
Portuguese)
• Post content from our QCon conferences
• 2 dedicated podcast channels: The InfoQ Podcast, with a focus on
Architecture and The Engineering Culture Podcast, with a focus on building
• 96 deep dives on innovative topics packed as downloadable emags and
minibooks
• Over 40 new content items per week
Watch the video with slide
synchronization on InfoQ.com!
https://www.infoq.com/presentations/
go-race-detector
Purpose of QCon
- to empower software development by facilitating the spread of
knowledge and innovation
Strategy
- practitioner-driven conference designed for YOU: influencers of
change and innovation in your teams
- speakers and topics driving the evolution and innovation
- connecting and catalyzing the influencers and innovators
Highlights
- attended by more than 12,000 delegates since 2007
- held in 9 cities worldwide
Presented at QCon San Francisco
www.qconsf.com
kavya
@kavya719
data race detection
data races
“when two+ threads concurrently access a shared memory
location, at least one access is a write.”
R R R
W R R
R W W
!W W W
count = 1 count = 2 count = 2
!concurrent concurrent concurrent
// Shared variable
var count = 0
func incrementCount() {
if count == 0 {
count ++
}
}
func main() {
// Spawn two “threads”
go incrementCount()
go incrementCount()
}
data race
“g2”
“g1”
data races
“when two+ threads concurrently access a shared memory
location, at least one access is a write.”
Thread 1 Thread 2
lock(l) lock(l)
count=1 count=2
unlock(l) unlock(l)
!data race
// Shared variable
var count = 0
func incrementCount() {
if count == 0 {
count ++
}
}
func main() {
// Spawn two “threads”
go incrementCount()
go incrementCount()
}
data race
• relevant
• elusive
• have undefined consequences
• easy to introduce in languages 

like Go
Panic messages from
unexpected program
crashes are often reported
on the Go issue tracker.
An overwhelming number of
these panics
are caused by data races,
and an
overwhelming number of
those reports
centre around Go’s built in
map type.
— Dave Cheney
given we want to write multithreaded programs,
how may we protect our systems from the
unknown consequences of the
difficult-to-track-down data race bugs…
in a manner that is reliable and scalable?
read by goroutine 7
at incrementCount()
created at main()
race detectors
…but how?
• Go v1.1 (2013)

• Integrated with the Go tool chain —
> go run -race counter.go

• Based on C/ C++ ThreadSanitizer

dynamic race detection library
• As of August 2015,
1200+ races in Google’s codebase,
~100 in the Go stdlib,

100+ in Chromium,

+ LLVM, GCC, OpenSSL, WebRTC, Firefox
go race detector
core concepts
internals
evaluation
wrap-up
core concepts
concurrency in go
The unit of concurrent execution : goroutines
user-space threads

use as you would threads 

> go handle_request(r)
Go memory model specied in terms of goroutines
within a goroutine: reads + writes are ordered
with multiple goroutines: shared data must be
synchronized…else data races!
channels

> ch <- value

mutexes, conditional vars, …

> import “sync” 

> mu.Lock()

atomics

> import “sync/ atomic"

> atomic.AddUint64(&myInt, 1)
The synchronization primitives:
“…goroutines concurrently access a shared memory
location, at least one access is a write.”
?
concurrency
var count = 0
func incrementCount() {
if count == 0 {
count ++
}
}
func main() {
go incrementCount()
go incrementCount()
}
“g2”
“g1”
R R R
W R R
R W W
W W W
count = 1 count = 2 count = 2
!concurrent concurrent concurrent
how can we determine
“concurrent”
memory accesses?
var count = 0
func incrementCount() {
if count == 0 {
count++
}
}
func main() {
incrementCount()
incrementCount()
}
not concurrent — same goroutine
not concurrent — 

lock draws a “dependency edge”
var count = 0
func incrementCount() {
mu.Lock()
if count == 0 {
count ++
}
mu.Unlock()
}
func main() {
go incrementCount()
go incrementCount()
}
happens-before
memory accesses 

i.e. reads, writes
a := b
synchronization 

via locks or lock-free sync
mu.Unlock()
ch <— a
X ≺ Y IF one of:
— same goroutine
— are a synchronization-pair
— X ≺ E ≺ Y
across goroutines
IF X not ≺ Y and Y not ≺ X ,
concurrent!
orders events
A
B
C
D
L
U
L
U
R
W
R
g1 g2
A ≺ B
same goroutine
B ≺ C
lock-unlock on same object
A ≺ D
transitivity
concurrent ?
var count = 0
func incrementCount() {
if count == 0 {
count ++
}
}
func main() {
go incrementCount()
go incrementCount()
}
A ≺ B and C ≺ D
same goroutine
but A ? C and C ? A
concurrent
A
B D
CR
W W
R
g1 g2
how can we implement
happens-before?
vector clocks
means to establish happens-before edges
0 1
lock(mu)
4 1
t1 = max(4, 0)
t2 = max(0,1)
g1 g2
0 0
g1 g2
0 0
g1 g2
1 0
read(count)
2 0
3 0
4 0
unlock(mu)
(0, 0) (0, 0)
(1, 0)
(3, 0)
(4, 0)
(4, 1) C
(4, 2) D
A ≺ D ?
(3, 0) < (4, 2) ?
so yes.
L
U
R
WA
B
L
R
U
g1 g2
CR
W W
R
g1 g2
(1, 0)A
(2, 0)B
(0, 1)
(0, 2) D
B ≺ C ?
(2, 0) < (0, 1) ?
no.
C ≺ B ?
no.
so, concurrent
pure happens-before detection
Determines if the accesses to a memory location can be
ordered by happens-before, using vector clocks.
This is what the Go Race Detector does!
internals
go run -race
to implement happens-before detection, need to:
create vector clocks for goroutines

…at goroutine creation

update vector clocks based on memory access,

synchronization events

…when these events occur

compare vector clocks to detect happens-before 

relations.

…when a memory access occurs
program
spawn
lock
read
race
race detector
state
race detector state machine
do we have to modify
our programs then,
to generate the events?
memory accesses
synchronizations
goroutine creation
nope.
var count = 0
func incrementCount() {
if count == 0 {
count ++
}
}
func main() {
go incrementCount()
go incrementCount()
}
-race
var count = 0
func incrementCount() {
raceread()
if count == 0 {

racewrite()
count ++
}

racefuncexit()
}
func main() {
go incrementCount()
go incrementCount()
the gc compiler instruments memory accesses
adds an instrumentation pass over the IR.
go tool compile -race
func compile(fn *Node)
{
...
order(fn)
walk(fn)
if instrumenting {
instrument(Curfn)
}
...
}
This is awesome.
We don’t have to modify our programs to track memory accesses.
package sync
import “internal/race"
func (m *Mutex) Lock() {
if race.Enabled {
race.Acquire(…)
}
...
}
raceacquire(addr)
mutex.go
package runtime
func newproc1() {
if race.Enabled {
newg.racectx =
racegostart(…)
}
...
}
proc.go
What about synchronization events, and goroutine creation?
runtime.raceread()
ThreadSanitizer (TSan) library
C++ race-detection library 

(.asm file because it’s calling into C++)
program
TSan
TSan implements the happens-before race detection:

creates, updates vector clocks for goroutines -> ThreadState

keeps track of memory access, synchronization events ->
Shadow State, Meta Map

compares vector clocks to detect data races.
threadsanitizer
go incrementCount()
struct ThreadState {
ThreadClock clock;
}
contains a xed-size vector clock
(size == max(# threads))
func newproc1() {
if race.Enabled {
newg.racectx =
racegostart(…)
}
...
}
proc.go
count == 0
raceread(…)
by compiler instrumentation
1. data race with a previous access?
2. store information about this access 

for future detections
stores information about memory accesses.
8-byte shadow word for an access:
TID clock pos wr
TID: accessor goroutine ID

clock: scalar clock of accessor ,
optimized vector clock
pos: offset, size in 8-byte word
wr: IsWrite bit
shadow state
directly-mapped:
0x7fffffffffff
0x7f0000000000
0x1fffffffffff
0x180000000000
application
shadow
N shadow cells per application word (8-bytes)
gx read
When shadow words are lled, evict one at random.
Optimization 1
clock_1 0:2 0gx
gy write
clock_2 4:8 1gy
Optimization 2
TID clock pos wr
scalar clock, not full vector clock.
gx gy
3 23
gx access:
g1: count == 0
raceread(…)
by compiler instrumentation
g1: count++
racewrite(…)
g2: count == 0
raceread(…)
and check for race
g1 0 0:8 0
0 0
g1 1 0:8 1
1 0
g2 0 0:8 0
0 0
race detection
compare:
<accessor’s vector clock,
new shadow word>
g2 0 0:8 0
0 0
“…when two+ threads concurrently access a shared
memory location, at least one access is a write.”
g1 1 0:8 1
with: each existing shadow word
race detection
compare:
<accessor’s vector clock,
new shadow word>
do the access locations overlap?
are any of the accesses a write?
are the TIDS different?
are they concurrent (no happens-before)?
g2’s vector clock: (0, 0)
existing shadow word’s clock: (1, ?)
g1 1 0:8 1g2 0 0:8 0
0 0
✓
✓
✓
✓
with: each existing shadow word
do the access locations overlap?
are any of the accesses a write?
are the TIDS different?
are they concurrent (no happens-before)?
race detection
g1 1 0:8 1g2 0 0:8 0
compare (accessor’s threadState, new shadow word) with
each existing shadow word:
0 0
RACE!
✓
✓
✓
✓
g1 g2
0 0
g1 g2
0 0
g1 g2
1 0
2 0
3 0
unlock(mu)
3 1
lock(mu)
g1 = max(3, 0)
g2 = max(0,1)
TSan must track synchronization events
synchronization events
sync vars
mu := sync.Mutex{} struct SyncVar {
}
stored in the meta map region.
struct SyncVar {
SyncClock clock;
}
contains a vector clock
SyncClock
mu.Unlock()
3 0
g1 g2
mu.Lock() max(
SyncClock)
0 1
TSan tracks le descriptors, memory allocations etc. too
TSan can track your custom sync primitives too, via dynamic
annotations!
a note (or two)…
evaluation
evaluation
“is it reliable?” “is it scalable?”
program slowdown = 5x-15x
memory usage = 5x-10x
no false positives
(only reports “real races”,
but can be benign)
can miss races!
depends on execution trace


As of August 2015,
1200+ races in Google’s codebase,
~100 in the Go stdlib,

100+ in Chromium,

+ LLVM, GCC, OpenSSL, WebRTC, Firefox
with
go run -race =
gc compiler instrumentation +
TSan runtime library for
data race detection
happens-before using
vector clocks
@kavya719
alternatives
I. Static detectors
analyze the program’s source code.

• typically have to augment the source with race annotations (-)
• single detection pass sufficient to determine all possible 

races (+)
• too many false positives to be practical (-)

II. Lockset-based dynamic detectors
uses an algorithm based on locks held

• more performant than pure happens-before (+)
• may not recognize synchronization via non-locks,

like channels (would report as races) (-)
III. Hybrid dynamic detectors
combines happens-before + locksets.

(TSan v1, but it was hella unscalable)

• “best of both worlds” (+)
• false positives (-)
• complicated to implement (-)





requirements
I. Go specics
v1.1+
gc compiler
gccgo does not support as per:
https://gcc.gnu.org/ml/gcc-patches/2014-12/msg01828.html
x86_64 required
Linux, OSX, Windows
II. TSan specics
LLVM Clang 3.2, gcc 4.8
x86_64
requires ASLR, so compile/ ld with -fPIE, -pie
maps (using mmap but does not reserve) virtual address space;
tools like top/ ulimit may not work as expected.
fun facts
TSan
maps (by mmap but does not reserve) tons of virtual address
space; tools like top/ ulimit may not work as expected.
need: gdb -ex 'set disable-randomization off' --args ./a.out

due to ASLR requirement.



Deadlock detection?
Kernel TSan?
goroutine 1
obj.UpdateMe()
mu.Lock()
flag = true
mu.Unlock()
goroutine 2
mu.Lock()
var f bool = flag
mu.Unlock ()
if (f) {
obj.UpdateMe()
}
{ {
a fun concurrency example
Watch the video with slide
synchronization on InfoQ.com!
https://www.infoq.com/presentations/
go-race-detector

More Related Content

Viewers also liked

Questionnaire analysis
Questionnaire analysisQuestionnaire analysis
Questionnaire analysisemiliabowles
 
Obv Newsletter Volume 10 Vietnamese
Obv Newsletter Volume 10 VietnameseObv Newsletter Volume 10 Vietnamese
Obv Newsletter Volume 10 VietnameseOneBodyVillage
 
Obv Newsletter Volume 10 English
Obv Newsletter Volume 10 English Obv Newsletter Volume 10 English
Obv Newsletter Volume 10 English OneBodyVillage
 
Santo Espirito Gezi Monteiro
Santo Espirito Gezi MonteiroSanto Espirito Gezi Monteiro
Santo Espirito Gezi MonteiroDanilo Angelo
 
Arterioesclerosis
ArterioesclerosisArterioesclerosis
ArterioesclerosisAngie Estrada
 
Planificación anual para 5 ° grado de primaria según el curriculo nacional
Planificación anual para  5 ° grado de primaria según el curriculo nacionalPlanificación anual para  5 ° grado de primaria según el curriculo nacional
Planificación anual para 5 ° grado de primaria según el curriculo nacionalMonica Mery Carmona Ruiz
 
HistĂłria- 8Âşano
HistĂłria- 8ÂşanoHistĂłria- 8Âşano
HistĂłria- 8ÂşanoZĂŠ MĂĄrio
 
Being a strong transformative leader
Being a strong transformative leaderBeing a strong transformative leader
Being a strong transformative leaderGrowthwise
 
Actividad ciudadano digital
Actividad ciudadano digitalActividad ciudadano digital
Actividad ciudadano digitalJhader Cano
 
Actividad 1.1 grupos de alimentos
Actividad 1.1 grupos de alimentosActividad 1.1 grupos de alimentos
Actividad 1.1 grupos de alimentosAndrea Higuera
 
Scoliosis
ScoliosisScoliosis
Scoliosisaliciadiez
 
Inclusive Design: Thinking Beyond Accessibility | NERDSummit 2017
Inclusive Design: Thinking Beyond Accessibility | NERDSummit 2017Inclusive Design: Thinking Beyond Accessibility | NERDSummit 2017
Inclusive Design: Thinking Beyond Accessibility | NERDSummit 2017Michael Miles
 
3Com 385640-001
3Com 385640-0013Com 385640-001
3Com 385640-001savomir
 
3Com 10002993
3Com 100029933Com 10002993
3Com 10002993savomir
 

Viewers also liked (16)

Questionnaire analysis
Questionnaire analysisQuestionnaire analysis
Questionnaire analysis
 
Obv Newsletter Volume 10 Vietnamese
Obv Newsletter Volume 10 VietnameseObv Newsletter Volume 10 Vietnamese
Obv Newsletter Volume 10 Vietnamese
 
Obv Newsletter Volume 10 English
Obv Newsletter Volume 10 English Obv Newsletter Volume 10 English
Obv Newsletter Volume 10 English
 
Santo Espirito Gezi Monteiro
Santo Espirito Gezi MonteiroSanto Espirito Gezi Monteiro
Santo Espirito Gezi Monteiro
 
Arterioesclerosis
ArterioesclerosisArterioesclerosis
Arterioesclerosis
 
Planificación anual para 5 ° grado de primaria según el curriculo nacional
Planificación anual para  5 ° grado de primaria según el curriculo nacionalPlanificación anual para  5 ° grado de primaria según el curriculo nacional
Planificación anual para 5 ° grado de primaria según el curriculo nacional
 
News SA 11 2017
News SA 11 2017News SA 11 2017
News SA 11 2017
 
HistĂłria- 8Âşano
HistĂłria- 8ÂşanoHistĂłria- 8Âşano
HistĂłria- 8Âşano
 
BĂşsqueda en pubmed
BĂşsqueda en pubmed BĂşsqueda en pubmed
BĂşsqueda en pubmed
 
Being a strong transformative leader
Being a strong transformative leaderBeing a strong transformative leader
Being a strong transformative leader
 
Actividad ciudadano digital
Actividad ciudadano digitalActividad ciudadano digital
Actividad ciudadano digital
 
Actividad 1.1 grupos de alimentos
Actividad 1.1 grupos de alimentosActividad 1.1 grupos de alimentos
Actividad 1.1 grupos de alimentos
 
Scoliosis
ScoliosisScoliosis
Scoliosis
 
Inclusive Design: Thinking Beyond Accessibility | NERDSummit 2017
Inclusive Design: Thinking Beyond Accessibility | NERDSummit 2017Inclusive Design: Thinking Beyond Accessibility | NERDSummit 2017
Inclusive Design: Thinking Beyond Accessibility | NERDSummit 2017
 
3Com 385640-001
3Com 385640-0013Com 385640-001
3Com 385640-001
 
3Com 10002993
3Com 100029933Com 10002993
3Com 10002993
 

More from C4Media

Streaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoStreaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoC4Media
 
Next Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileNext Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileC4Media
 
Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020C4Media
 
Understand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsUnderstand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsC4Media
 
Kafka Needs No Keeper
Kafka Needs No KeeperKafka Needs No Keeper
Kafka Needs No KeeperC4Media
 
High Performing Teams Act Like Owners
High Performing Teams Act Like OwnersHigh Performing Teams Act Like Owners
High Performing Teams Act Like OwnersC4Media
 
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaDoes Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaC4Media
 
Service Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideService Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideC4Media
 
Shifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDShifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDC4Media
 
CI/CD for Machine Learning
CI/CD for Machine LearningCI/CD for Machine Learning
CI/CD for Machine LearningC4Media
 
Fault Tolerance at Speed
Fault Tolerance at SpeedFault Tolerance at Speed
Fault Tolerance at SpeedC4Media
 
Architectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsArchitectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsC4Media
 
ML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsC4Media
 
Build Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerBuild Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerC4Media
 
User & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleUser & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleC4Media
 
Scaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeScaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeC4Media
 
Make Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereMake Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereC4Media
 
The Talk You've Been Await-ing For
The Talk You've Been Await-ing ForThe Talk You've Been Await-ing For
The Talk You've Been Await-ing ForC4Media
 
Future of Data Engineering
Future of Data EngineeringFuture of Data Engineering
Future of Data EngineeringC4Media
 
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreAutomated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreC4Media
 

More from C4Media (20)

Streaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoStreaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live Video
 
Next Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileNext Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy Mobile
 
Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020
 
Understand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsUnderstand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java Applications
 
Kafka Needs No Keeper
Kafka Needs No KeeperKafka Needs No Keeper
Kafka Needs No Keeper
 
High Performing Teams Act Like Owners
High Performing Teams Act Like OwnersHigh Performing Teams Act Like Owners
High Performing Teams Act Like Owners
 
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaDoes Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
 
Service Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideService Meshes- The Ultimate Guide
Service Meshes- The Ultimate Guide
 
Shifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDShifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CD
 
CI/CD for Machine Learning
CI/CD for Machine LearningCI/CD for Machine Learning
CI/CD for Machine Learning
 
Fault Tolerance at Speed
Fault Tolerance at SpeedFault Tolerance at Speed
Fault Tolerance at Speed
 
Architectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsArchitectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep Systems
 
ML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.js
 
Build Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerBuild Your Own WebAssembly Compiler
Build Your Own WebAssembly Compiler
 
User & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleUser & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix Scale
 
Scaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeScaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's Edge
 
Make Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereMake Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home Everywhere
 
The Talk You've Been Await-ing For
The Talk You've Been Await-ing ForThe Talk You've Been Await-ing For
The Talk You've Been Await-ing For
 
Future of Data Engineering
Future of Data EngineeringFuture of Data Engineering
Future of Data Engineering
 
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreAutomated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
 

Recently uploaded

Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel AraĂşjo
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 

Recently uploaded (20)

Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 

Looking Inside a Race Detector

  • 2. InfoQ.com: News & Community Site • Over 1,000,000 software developers, architects and CTOs read the site world- wide every month • 250,000 senior developers subscribe to our weekly newsletter • Published in 4 languages (English, Chinese, Japanese and Brazilian Portuguese) • Post content from our QCon conferences • 2 dedicated podcast channels: The InfoQ Podcast, with a focus on Architecture and The Engineering Culture Podcast, with a focus on building • 96 deep dives on innovative topics packed as downloadable emags and minibooks • Over 40 new content items per week Watch the video with slide synchronization on InfoQ.com! https://www.infoq.com/presentations/ go-race-detector
  • 3. Purpose of QCon - to empower software development by facilitating the spread of knowledge and innovation Strategy - practitioner-driven conference designed for YOU: influencers of change and innovation in your teams - speakers and topics driving the evolution and innovation - connecting and catalyzing the influencers and innovators Highlights - attended by more than 12,000 delegates since 2007 - held in 9 cities worldwide Presented at QCon San Francisco www.qconsf.com
  • 6. data races “when two+ threads concurrently access a shared memory location, at least one access is a write.” R R R W R R R W W !W W W count = 1 count = 2 count = 2 !concurrent concurrent concurrent // Shared variable var count = 0 func incrementCount() { if count == 0 { count ++ } } func main() { // Spawn two “threads” go incrementCount() go incrementCount() } data race “g2” “g1”
  • 7. data races “when two+ threads concurrently access a shared memory location, at least one access is a write.” Thread 1 Thread 2 lock(l) lock(l) count=1 count=2 unlock(l) unlock(l) !data race // Shared variable var count = 0 func incrementCount() { if count == 0 { count ++ } } func main() { // Spawn two “threads” go incrementCount() go incrementCount() } data race
  • 8. • relevant • elusive • have undened consequences • easy to introduce in languages 
 like Go Panic messages from unexpected program crashes are often reported on the Go issue tracker. An overwhelming number of these panics are caused by data races, and an overwhelming number of those reports centre around Go’s built in map type. — Dave Cheney
  • 9. given we want to write multithreaded programs, how may we protect our systems from the unknown consequences of the difcult-to-track-down data race bugs… in a manner that is reliable and scalable?
  • 10. read by goroutine 7 at incrementCount() created at main() race detectors
  • 12. • Go v1.1 (2013)
 • Integrated with the Go tool chain — > go run -race counter.go
 • Based on C/ C++ ThreadSanitizer
 dynamic race detection library • As of August 2015, 1200+ races in Google’s codebase, ~100 in the Go stdlib,
 100+ in Chromium,
 + LLVM, GCC, OpenSSL, WebRTC, Firefox go race detector
  • 15. concurrency in go The unit of concurrent execution : goroutines user-space threads
 use as you would threads 
 > go handle_request(r) Go memory model specied in terms of goroutines within a goroutine: reads + writes are ordered with multiple goroutines: shared data must be synchronized…else data races!
  • 16. channels
 > ch <- value
 mutexes, conditional vars, …
 > import “sync” 
 > mu.Lock()
 atomics
 > import “sync/ atomic"
 > atomic.AddUint64(&myInt, 1) The synchronization primitives:
  • 17. “…goroutines concurrently access a shared memory location, at least one access is a write.” ? concurrency var count = 0 func incrementCount() { if count == 0 { count ++ } } func main() { go incrementCount() go incrementCount() } “g2” “g1” R R R W R R R W W W W W count = 1 count = 2 count = 2 !concurrent concurrent concurrent
  • 18. how can we determine “concurrent” memory accesses?
  • 19. var count = 0 func incrementCount() { if count == 0 { count++ } } func main() { incrementCount() incrementCount() } not concurrent — same goroutine
  • 20. not concurrent — 
 lock draws a “dependency edge” var count = 0 func incrementCount() { mu.Lock() if count == 0 { count ++ } mu.Unlock() } func main() { go incrementCount() go incrementCount() }
  • 21. happens-before memory accesses 
 i.e. reads, writes a := b synchronization 
 via locks or lock-free sync mu.Unlock() ch <— a X ≺ Y IF one of: — same goroutine — are a synchronization-pair — X ≺ E ≺ Y across goroutines IF X not ≺ Y and Y not ≺ X , concurrent! orders events
  • 22. A B C D L U L U R W R g1 g2 A ≺ B same goroutine B ≺ C lock-unlock on same object A ≺ D transitivity
  • 23. concurrent ? var count = 0 func incrementCount() { if count == 0 { count ++ } } func main() { go incrementCount() go incrementCount() }
  • 24. A ≺ B and C ≺ D same goroutine but A ? C and C ? A concurrent A B D CR W W R g1 g2
  • 25. how can we implement happens-before?
  • 26. vector clocks means to establish happens-before edges 0 1 lock(mu) 4 1 t1 = max(4, 0) t2 = max(0,1) g1 g2 0 0 g1 g2 0 0 g1 g2 1 0 read(count) 2 0 3 0 4 0 unlock(mu)
  • 27. (0, 0) (0, 0) (1, 0) (3, 0) (4, 0) (4, 1) C (4, 2) D A ≺ D ? (3, 0) < (4, 2) ? so yes. L U R WA B L R U g1 g2
  • 28. CR W W R g1 g2 (1, 0)A (2, 0)B (0, 1) (0, 2) D B ≺ C ? (2, 0) < (0, 1) ? no. C ≺ B ? no. so, concurrent
  • 29. pure happens-before detection Determines if the accesses to a memory location can be ordered by happens-before, using vector clocks. This is what the Go Race Detector does!
  • 31. go run -race to implement happens-before detection, need to: create vector clocks for goroutines
 …at goroutine creation
 update vector clocks based on memory access,
 synchronization events
 …when these events occur
 compare vector clocks to detect happens-before 
 relations.
 …when a memory access occurs
  • 33. do we have to modify our programs then, to generate the events? memory accesses synchronizations goroutine creation nope.
  • 34. var count = 0 func incrementCount() { if count == 0 { count ++ } } func main() { go incrementCount() go incrementCount() }
  • 35. -race var count = 0 func incrementCount() { raceread() if count == 0 {
 racewrite() count ++ }
 racefuncexit() } func main() { go incrementCount() go incrementCount()
  • 36. the gc compiler instruments memory accesses adds an instrumentation pass over the IR. go tool compile -race func compile(fn *Node) { ... order(fn) walk(fn) if instrumenting { instrument(Curfn) } ... }
  • 37. This is awesome. We don’t have to modify our programs to track memory accesses. package sync import “internal/race" func (m *Mutex) Lock() { if race.Enabled { race.Acquire(…) } ... } raceacquire(addr) mutex.go package runtime func newproc1() { if race.Enabled { newg.racectx = racegostart(…) } ... } proc.go What about synchronization events, and goroutine creation?
  • 38. runtime.raceread() ThreadSanitizer (TSan) library C++ race-detection library 
 (.asm le because it’s calling into C++) program TSan
  • 39. TSan implements the happens-before race detection:
 creates, updates vector clocks for goroutines -> ThreadState
 keeps track of memory access, synchronization events -> Shadow State, Meta Map
 compares vector clocks to detect data races. threadsanitizer
  • 40. go incrementCount() struct ThreadState { ThreadClock clock; } contains a xed-size vector clock (size == max(# threads)) func newproc1() { if race.Enabled { newg.racectx = racegostart(…) } ... } proc.go count == 0 raceread(…) by compiler instrumentation 1. data race with a previous access? 2. store information about this access 
 for future detections
  • 41. stores information about memory accesses. 8-byte shadow word for an access: TID clock pos wr TID: accessor goroutine ID
 clock: scalar clock of accessor , optimized vector clock pos: offset, size in 8-byte word wr: IsWrite bit shadow state directly-mapped: 0x7fffffffffff 0x7f0000000000 0x1fffffffffff 0x180000000000 application shadow
  • 42. N shadow cells per application word (8-bytes) gx read When shadow words are lled, evict one at random. Optimization 1 clock_1 0:2 0gx gy write clock_2 4:8 1gy
  • 43. Optimization 2 TID clock pos wr scalar clock, not full vector clock. gx gy 3 23 gx access:
  • 44. g1: count == 0 raceread(…) by compiler instrumentation g1: count++ racewrite(…) g2: count == 0 raceread(…) and check for race g1 0 0:8 0 0 0 g1 1 0:8 1 1 0 g2 0 0:8 0 0 0
  • 45. race detection compare: <accessor’s vector clock, new shadow word> g2 0 0:8 0 0 0 “…when two+ threads concurrently access a shared memory location, at least one access is a write.” g1 1 0:8 1 with: each existing shadow word
  • 46. race detection compare: <accessor’s vector clock, new shadow word> do the access locations overlap? are any of the accesses a write? are the TIDS different? are they concurrent (no happens-before)? g2’s vector clock: (0, 0) existing shadow word’s clock: (1, ?) g1 1 0:8 1g2 0 0:8 0 0 0 ✓ ✓ ✓ ✓ with: each existing shadow word
  • 47. do the access locations overlap? are any of the accesses a write? are the TIDS different? are they concurrent (no happens-before)? race detection g1 1 0:8 1g2 0 0:8 0 compare (accessor’s threadState, new shadow word) with each existing shadow word: 0 0 RACE! ✓ ✓ ✓ ✓
  • 48. g1 g2 0 0 g1 g2 0 0 g1 g2 1 0 2 0 3 0 unlock(mu) 3 1 lock(mu) g1 = max(3, 0) g2 = max(0,1) TSan must track synchronization events synchronization events
  • 49. sync vars mu := sync.Mutex{} struct SyncVar { } stored in the meta map region. struct SyncVar { SyncClock clock; } contains a vector clock SyncClock mu.Unlock() 3 0 g1 g2 mu.Lock() max( SyncClock) 0 1
  • 50. TSan tracks le descriptors, memory allocations etc. too TSan can track your custom sync primitives too, via dynamic annotations! a note (or two)…
  • 52. evaluation “is it reliable?” “is it scalable?” program slowdown = 5x-15x memory usage = 5x-10x no false positives (only reports “real races”, but can be benign) can miss races! depends on execution trace 
 As of August 2015, 1200+ races in Google’s codebase, ~100 in the Go stdlib,
 100+ in Chromium,
 + LLVM, GCC, OpenSSL, WebRTC, Firefox
  • 53. with go run -race = gc compiler instrumentation + TSan runtime library for data race detection happens-before using vector clocks
  • 55. alternatives I. Static detectors analyze the program’s source code.
 • typically have to augment the source with race annotations (-) • single detection pass sufcient to determine all possible 
 races (+) • too many false positives to be practical (-)
 II. Lockset-based dynamic detectors uses an algorithm based on locks held
 • more performant than pure happens-before (+) • may not recognize synchronization via non-locks,
 like channels (would report as races) (-)
  • 56. III. Hybrid dynamic detectors combines happens-before + locksets.
 (TSan v1, but it was hella unscalable)
 • “best of both worlds” (+) • false positives (-) • complicated to implement (-)
 
 

  • 57. requirements I. Go specics v1.1+ gc compiler gccgo does not support as per: https://gcc.gnu.org/ml/gcc-patches/2014-12/msg01828.html x86_64 required Linux, OSX, Windows II. TSan specics LLVM Clang 3.2, gcc 4.8 x86_64 requires ASLR, so compile/ ld with -fPIE, -pie maps (using mmap but does not reserve) virtual address space; tools like top/ ulimit may not work as expected.
  • 58. fun facts TSan maps (by mmap but does not reserve) tons of virtual address space; tools like top/ ulimit may not work as expected. need: gdb -ex 'set disable-randomization off' --args ./a.out
 due to ASLR requirement.
 
 Deadlock detection? Kernel TSan?
  • 59. goroutine 1 obj.UpdateMe() mu.Lock() flag = true mu.Unlock() goroutine 2 mu.Lock() var f bool = flag mu.Unlock () if (f) { obj.UpdateMe() } { { a fun concurrency example
  • 60. Watch the video with slide synchronization on InfoQ.com! https://www.infoq.com/presentations/ go-race-detector