Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Data Race Detection In Go From Beginners Eye

Data Race Detection In Go From Beginners Eye

Do you know what is Data Race in concurrent programming and what is inside it's hood ?

- Background

Recently, I faced a problem in my code a data race issue that caused our service to crash after we mistakenly deployed it without checking for race conditions . I didn't know how to fix and prevent the data race issue at first , so I searched online to learn more about data races and the Go Race Detector. Curiosity led me to explore how to prevent Data Races, and I'm excited to share my story of understanding the inner workings of the Go Data Race Detector.

In the realm of concurrent programming, the occurrence of Data Race conditions can be frequent and challenging to manage. If I put it in simple words , when two or more goroutines access shared memory data concurrently and one goroutine is a write , Data Race conditions may arise, leading to unpredictable failures which we can not detect long after the code has been deployed to production. This session focuses on exploring the Go Race Detector, which is built upon the C/C++ ThreadSanitizer runtime library. Originally designed to identify errors in Google's internal codebase and Chromium, The Race Detector is a powerful and proven tool for detecting data race bugs.

Given that we wanted to write multithreaded programs, how can we protect our systems from the unknown consequences of difficult to track down data race bugs in a manner that is reliable and scalable .

Go Race Detector follows " Pure Happens Before Race Detection" using Vector Clocks so let's understand the concepts.

- Expected effect on audience

This session aims to provide attendees, especially beginners, with a comprehensive understanding of Data Races in concurrent programming. Participants will gain insights into detecting and addressing these issues effectively using the Go Race Detector and also the attendies will learn about the backend technology behind Data Race Detector .

Avatar for Vaibhav Gupta

Vaibhav Gupta

August 08, 2024
Tweet

More Decks by Vaibhav Gupta

Other Decks in Programming

Transcript

  1. Vaibhav Gupta @97vaibhav • Indian 󰏝 • Software engineer •

    A Two-year-old Gopher • Anime,Culture And Travel
  2. What is a Data Race ? “When two or more

    goroutines access shared memory data concurrently and one goroutine is a write ” "2つ以上のGo routineが同時に共有メモリ・データにアク セスし、1つのゴルーチンが書き込み"
  3. What is a Data Race ? “When two or more

    goroutines access shared memory data concurrently and one goroutine is a write ” "2つ以上のGo routineが同時に共有メモリ・データにアク セスし、1つのゴルーチンが書き込み" Let’s Look at an example 例を見てみましょう
  4. G1

  5. G1 G2 G1R G1R G1R G1W G2R G2R G2R G1W

    G2W G2W G2W G1W ✅ ❌ ❌ counter =2 🤔
  6. If we want to find Data Race in our CodeBase

    how can we do that in a manner which is reliable ?? CodeBaseのデータ・レース状態を追跡したい場合、どのようにすれ ば信頼できるのでしょうか??
  7. Go Race Detector • Go v1.1 • Integrated with the

    Go tool chain go run -race main.go
  8. Go Race Detector • Go v1.1 • Integrated with the

    Go tool chain go run -race main.go • It is Based on C/ C++ ThreadSanitizer https://go.dev/blog/race-detector
  9. Go Memory Model Go memory model states that • in

    a goroutine reads and writes are ordered • when multiple goroutines are present shared data must be synchronized Goのメモリ・モデルでは、次のようになる。 • ゴルーチンでは、読み書きの順序が決まっている。 • 複数のゴルーチンが存在する場合、共有データは同期さ れなければならない
  10. Go Memory Model Go memory model states that • in

    a goroutine reads and writes are ordered • when multiple goroutines are present shared data must be synchronized Goのメモリ・モデルでは、次のようになる。 • ゴルーチンでは、読み書きの順序が決まっている。 • 複数のゴルーチンが存在する場合、共有データは同期さ れなければならない Ref. https://go.dev/ref/mem#introduction
  11. Go Memory Model Go memory model states that • in

    a goroutine reads and writes are ordered • when multiple goroutines are present shared data must be synchronized Goのメモリ・モデルでは、次のようになる。 • ゴルーチンでは、読み書きの順序が決まっている。 • 複数のゴルーチンが存在する場合、共有データは同期さ れなければならない Ref. https://go.dev/ref/mem#introduction Data Race 😭
  12. The synchronization Types Channels Mychannel <- element Mutex • Lock()

    • Unlock() https://go.dev/tour/concurrency/9 Atomics https://pkg.go.dev/sync/atomic
  13. Happens Before When two events lets say a and b

    are present , only one of the following three scenarios is possible • a happens before b a < b • b happens before a b < a • If Neither of the above is true ◦ In this case, we say a and b are concurrent
  14. Example L R W U L R W U G1

    G2 A C B D L M N O
  15. Example L R W U L R W U G1

    G2 A C B D L M N O B<C
  16. Example L R W U L R W U G1

    G2 A C B D L M N O B<C ✅
  17. Example L R W U L R W U G1

    G2 A C B D L M N O B<C ✅ D<L
  18. Example L R W U L R W U G1

    G2 A C B D L M N O B<C ✅ D<L ✅
  19. Example L R W U L R W U G1

    G2 A C B D L M N O B<C ✅ D<L ✅ C<M ?
  20. Example L R W U L R W U G1

    G2 A C B D L M N O B<C ✅ D<L ✅ C<M ✅
  21. R W R W G1 G2 A B L M

    A<B L<M ✅
  22. R W R W G1 G2 A B L M

    A<B L<M ✅ ✅
  23. R W R W G1 G2 A B L M

    A<B L<M ✅ ✅ A<L? 
  24. R W R W G1 G2 A B L M

    A<B L<M ✅ ✅ A<L?  B<M ?
  25. R W R W G1 G2 A B L M

    A<B L<M ✅ ✅ A<L?  B<M ? わからない🥲
  26. Vector Clocks • Each process starts with a vector clock

    initialized to zero. • Every time an event occurs at a process, it increments its own entry in the vector clock by 1. • When a process sends a message, it includes its current vector clock in the message. • Upon receiving a message, a process updates its own vector clock by taking the maximum of each entry in its vector clock and the corresponding entry in the received vector clock, then increments its own entry for its own process by 1. • 各プロセスは、ゼロで初期化されたベクトルクロックを持って開始します。 • プロセスでイベントが発生するたびに、そのプロセスのベクトルクロックのエントリを 1つ増やします。 • プロセスがメッセージを送信するときは、現在のベクトルクロックをメッセージに含めます。 • メッセージを受信すると、プロセスは、自分のベクトルクロックの各エントリと受信したベクトルクロッ クの対応するエントリの最大値を取り、それぞれのプロセスのエントリを 1つ増やします。
  27. Vector Clocks L R W G1 G2 A C B

    (1,0) (2,0) (3,0) (0,0) (0,0)
  28. Vector Clocks L R W U G1 G2 A C

    B D (1,0) (2,0) (3,0) (4,0) (0,0) (0,0)
  29. Vector Clocks L R W U L G1 G2 A

    C B D L (1,0) (2,0) (3,0) (4,0) (0,1) (0,0) (0,0) (4,0)
  30. Vector Clocks L R W U L G1 G2 A

    C B D L (1,0) (2,0) (3,0) (4,0) (0,1) (0,0) (0,0) a1=(4,0) a2=(0,1) Max (4,1) (4,0)
  31. Vector Clocks L R W U L G1 G2 A

    C B D L (1,0) (2,0) (3,0) (4,0) (4,1) (0,0) (0,0)
  32. Vector Clocks L R W U L R G1 G2

    A C B D L M (1,0) (2,0) (3,0) (4,0) (4,1) (4,2) (0,0) (0,0)
  33. Vector Clocks L R W U L R W G1

    G2 A C B D L M N (1,0) (2,0) (3,0) (4,0) (4,1) (4,2) (4,3) (0,0) (0,0)
  34. Vector Clocks L R W U L R W U

    G1 G2 A C B D L M N O (1,0) (2,0) (3,0) (4,0) (4,1) (4,2) (4,3) (4,4) (0,0) (0,0)
  35. Vector Clocks L R W U L R W U

    G1 G2 A C B D L M N O (1,0) (2,0) (3,0) (4,0) (4,1) (4,2) (4,3) (4,4) (0,0) (0,0) C<M
  36. Vector Clocks L R W U L R W U

    G1 G2 A C B D L M N O (1,0) (2,0) (3,0) (4,0) (4,1) (4,2) (4,3) (4,4) (0,0) (0,0) C<M (3,0)< (4,2)
  37. Vector Clocks L R W U L R W U

    G1 G2 A C B D L M N O (1,0) (2,0) (3,0) (4,0) (4,1) (4,2) (4,3) (4,4) (0,0) (0,0) C<M (3,0)< (4,2) ✅
  38. R W R W G1 G2 A B L M

    (1,0) (2,0) (0,1) (0,2)
  39. R W R W G1 G2 A B L M

    (1,0) (2,0) (0,1) (0,2) A<B (1,0)<(2,0)
  40. R W R W G1 G2 A B L M

    ✅ (1,0) (2,0) (0,1) (0,2) A<B (1,0)<(2,0)
  41. R W R W G1 G2 A B L M

    (1,0) (2,0) (0,1) (0,2) ✅ A<B (1,0)<(2,0) L<M (0,1)<(0,2)
  42. R W R W G1 G2 A B L M

    (1,0) (2,0) (0,1) (0,2) ✅ A<B (1,0)<(2,0) L<M (0,1)<(0,2) ✅
  43. R W R W G1 G2 A B L M

    (1,0) (2,0) (0,1) (0,2) A<M (1,0)<(0,2)  
  44. R W R W G1 G2 A B L M

    A<M (1,0)<(0,2) ❌  (1,0) (2,0) (0,1) (0,2)
  45. R W R W G1 G2 A B L M

    (1,0) (2,0) (0,1) (0,2) M<B (0,2)<(2,0) A<M (1,0)<(0,2) ❌ 
  46. R W R W G1 G2 A B L M

    (1,0) (2,0) (0,1) (0,2) M<B (0,2)<(2,0) ❌ A<M (1,0)<(0,2) ❌ 
  47. R W R W G1 G2 A B L M

    (1,0) (2,0) (0,1) (0,2) M<B (0,2)<(2,0) ❌ A<M (1,0)<(0,2) ❌  Concurrent ☹
  48. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0)
  49. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0) (0,1,0) H I G3 (0,0,0)
  50. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0) (0,1,0) H I G3 (0,0,0) (4,0,0)
  51. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0) (4,2,0) (4,3,0) (4,1,0) H I G3 (0,0,0)
  52. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0) (4,2,0) (4,3,0) (4,1,0) H I G3 (0,0,0) (0,0,1) (0,0,2)
  53. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0) (4,2,0) (4,3,0) (4,1,0) H I G3 (0,0,0) (0,0,1) (0,0,2) (2,0,0)
  54. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0) (4,2,0) (4,3,0) (4,1,0) H I G3 (0,0,0) (0,0,1) (2,0,2)
  55. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0) (4,2,0) (4,3,0) (4,1,0) H I G3 (0,0,0) (0,0,1) (2,0,2) G<I
  56. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0) (4,2,0) (4,3,0) (4,1,0) H I G3 (0,0,0) (0,0,1) (2,0,2) G<I (4,3,0) < (2,0,2)
  57. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0) (4,2,0) (4,3,0) (4,1,0) H I G3 (0,0,0) (0,0,1) (2,0,2) G<I (4,3,0) < (2,0,2) ❌
  58. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0) (4,2,0) (4,3,0) (4,1,0) H I G3 (0,0,0) (0,0,1) (2,0,2) G<I (4,3,0) < (2,0,2) ❌ I<G (2,0,2) < (4,3,0)
  59. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0) (4,2,0) (4,3,0) (4,1,0) H I G3 (0,0,0) (0,0,1) (2,0,2) G<F (4,3,0) < (2,0,2) ❌ I<G (2,0,2) < (4,3,0) ❌
  60. Vector Clocks G1 A C B D (0,0,0) (1,0,0) (2,0,0)

    (3,0,0) (4,0,0) E F G G2 (0,0,0) (4,2,0) (4,3,0) (4,1,0) H I G3 (0,0,0) (0,0,1) (2,0,2) G<F (4,3,0) < (2,0,2) ❌ I<G (2,0,2) < (4,3,0) ❌ Concurrent
  61. Go Race Detector follows pure happens-before Approach Goレースディテクタはpure happens-beforeアプローチに従う Go

    Race Detector Determines if the accesses to a memory location can be ordered by happens-before, using vector clocks. Goレースディテクタは、ベクトルクロックを使用して、メモリ位置へ のアクセスがhappens-beforeによって順序付けられるかどうかを判 断する。
  62. go run -race main.go • Memory Access • Creating Vector

    clocks For goroutines • Updating vector clocks on synchronization events • It compares Vector clocks to detect happens-before relation
  63. ThreadSanitizer(Tsan) • Go race detector is built on Tsan •

    TSan implements happens-before race detection . • Tsan creates, updates vector clocks for goroutines - ThreadState • Tsan keeps track of memory access, synchronization events such as lock, unlock - Shadow State • Tsan compares vector clocks to detect data races in our code .
  64. Shadow State Stores information about memory accesses. 8-byte shadow word

    for an access TID epoch addr rd/wr Struct Shadow { tid // thread id epoch // thread’s clock time addr // memory access address write // read/write }
  65. Shadow State Do the accesses overlap? Is one of them

    a write? Are the thread IDs different? Are they unordered by happens-before?
  66. Shadow State Do the accesses overlap ✅ Is one of

    them a write ✅ Are the thread IDs different ✅ Are they unordered by happens-before ✅
  67. Shadow State Do the accesses overlap ✅ Is one of

    them a write ✅ Are the thread IDs different ✅ Are they unordered by happens-before ✅ If these conditions are met, TSan detects and reports a data race.
  68. 1. Use Synchronization Primitives 2. Avoid Unprotected Access 3. Practice

    Goroutine Communication 4. Test Concurrency 5. Monitor and Profile
  69. Lets Evaluate Race Detector Reliable • Won’t give you unnecessary

    results • The Race detector does not give false positives • Can miss races condition https://medium.com/@val_delepl ace/does-the-race-detector-catch- all-data-races-1afed51d57fb Scalable • Execution time = 2x-20x • memory usage = 5x-10x https://go.dev/doc/articles/race_detector
  70. References : • https://speakerdeck.com/kkc/go-race-detector-under-the-hood?sli de=11 • https://go.dev/doc/articles/race_detector • https://medium.com/@val_deleplace/does-the-race-detector-catch -all-data-races-1afed51d57fb

    • https://go.dev/doc/articles/race_detector#Typical_Data_Races • https://tarides.com/blog/2023-10-18-off-to-the-races-using-threads anitizer-in-ocaml/ • https://www.youtube.com/watch?v=4wq-YlaI_vk&t=1312s • https://www.infoq.com/presentations/go-race-detector/
  71. Q/A