Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
testing/synctest使ってみた
Search
Pana
March 07, 2025
0
46
testing/synctest使ってみた
Pana
March 07, 2025
Tweet
Share
More Decks by Pana
See All by Pana
Deep dive into log/slog package
k3forx
1
330
Featured
See All Featured
Faster Mobile Websites
deanohume
307
31k
4 Signs Your Business is Dying
shpigford
184
22k
Become a Pro
speakerdeck
PRO
29
5.4k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
6
330
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
7
740
How to train your dragon (web standard)
notwaldorf
96
6.1k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
161
15k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
32
2.4k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.8k
How to Ace a Technical Interview
jacobian
278
23k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Java REST API Framework Comparison - PWX 2021
mraible
31
8.7k
Transcript
2025.03.07 presented by Pana testing/synctest使ってみた 第2回Beerbash
⾃⼰紹介 ‧名前(ニックネーム) ‧Pana (miyaharaさんとよく間違えられるため) ‧名字で呼んでもらっても⼤丈夫です ‧基本情報 ‧1996年⽣まれ、広島出⾝ ‧業務 ‧カナリー、マーケットプレイスチーム ‧趣味
‧コーヒー、つけ麺、美味しいもの⾷べる
Go1.24リリース🎉
Go1.24のリリースサマリ 今回はtesting/synctestパッケージを紹介! ‧型エイリアスがジェネリクスに対応 ‧tools.goで管理していた依存関係がgo.modで管理できるように ‧イテレータ関連のメソッドが追加 ‧mapの実装がSwiss Tableになってパフォーマンスが向上 ‧実験的なパッケージとしてtesting/synctestが導⼊ ‧etc...
testing/synctestの紹介
testing/synctestの概要 ‧実装の背景 ‧concurrentな実装のテストは時間がかかる ‧flakyになりがち ‧注意点 ‧まだ実験的に導⼊されているので挙動が正しくないことがある
testing/synctestの概要 実際に試してみる! ‧公開されている関数は2つ ‧Run ‧Wait ‧実⾏時には GOEXPERIMENT=synctest フラグを渡す必要がある
実験1: 簡単なキャッシュ
実験1: 簡単なキャッシュ(実装コード) ‧SetとGetのみ ‧Setが呼ばれた時に setTime = time.Now() が実⾏される ‧Getが呼ばれた時、TTL経過していたらゼ ロ値、そうでない場合は
c.v が返される
実験1: 簡単なキャッシュ(テストコード) ‧xxx ‧xxx ‧xxx テストの実⾏に5秒以上かかる 😢 実⾏してみる
実験1: 簡単なキャッシュ(テストコード) Run関数でWrapすると、約0.17秒でテストが終わる 🎉 実⾏してみる
synctest.RunのGoDocをみてみる
synctest.RunのGoDocをみてみる(⼀部翻訳) 1. Runは関数fを新しいゴルーチンの中で実⾏する 2. 新しいゴルーチンとそれから間接的に開始されたゴルーチンはbubbleを形 成する 3. Runはbubbleの中のすべてのゴルーチンがexitするまで待つ 4. bubbleの中のゴルーチンはsyntheticな時間実装を使う、初期時間はUTCの
2000-01-01 5. bubbleの中のすべてのゴルーチンがブロックされたら時間が進む 4, 5を検証してみる 💡
実験1: 簡単なキャッシュ(テストコード) time.Sleepによってブロックすると時間が進む! 実⾏してみる
実験1: 簡単なキャッシュ(テストコード) もうちょっとpracticalな例を考えてみる ‧今回の実験で分かったこと ‧Runを使えばテストにかかる時間を短縮できる ‧Runの挙動(⼀部のみ) ‧ここで疑問 🤔 ‧「別にTTLを5秒にしなくても、1マイクロ秒にすればいいやん」 →
その通りです!今回の実装の場合 testing/synctest パッケージは不要 → なぜなら、そもそもの実装が直列で実⾏されるから
実験2: 簡単なキャッシュv2
実験2: 簡単なキャッシュv2(実装コード) ‧Setが呼ばれた時に、別のゴルーチン でexpireさせる (ゼロ値に更新する) ‧「何かの関数を呼んだ際に、別のゴ ルーチンが作られる」という挙動を具 体化した1つの例として考えてみる
実験2: 簡単なキャッシュv2(テストコード) 100回中4回落ちた = flakyなテストになっている 😢 100回実⾏してみる v1と同じテスト!
なぜランダムで落ちるのか? 「Get」と「c.v = zero」のどちらが先 に実⾏されるか不明 = flakyになる原因 (Runの仕様その5) bubbleの中のすべてのゴルーチンがブロック されたら時間が進む
実験2: 簡単なキャッシュv2(テストコード) 落ちなくなった 🎉 直感的には「ゴルーチンの終了を待つ」挙動だが...? 100回実⾏してみる
synctest.WaitのGoDocをみてみる
synctest.WaitのGoDocをみてみる(⼀部翻訳) 1. Waitは、現在のbubble内の現在のゴルーチン以外のすべてのゴルーチンが 持続的にブロック (durably block) されるまでブロックする 2. bubble外のゴルーチンから呼び出された場合や、同じbubble内の2つのゴ ルーチンが同時にWaitを呼び出した場合はパニックする
3. bubble内の他のゴルーチンによってのみブロックを解除できる場合、その ゴルーチンはdurably blockされる 4. time.Sleepやbubble内からのチャネルの送受信などはゴルーチンを durably blockする 「ゴルーチンの終了を待つ」とは書かれていない! 1, 4を元にもう⼀度考えてみる!
synctest.Waitの挙動 1. Waitが呼ばれた時、サブのゴルーチ ンは実⾏中なら2、終了したなら4へ 2. サブのゴルーチンがdurably blockedになるまで待つ 3. durably blockedになることなく、
サブのゴルーチンが終了 4. Waitはサブのゴルーチンを気にする 必要がなくなってunblock 5. メインのゴルーチンの処理が進む (Runの仕様その5) bubbleの中のすべてのゴルーチンがブロックされたら時間が進む
おさらい! Q1. テストでSetだけ呼んだ時、下記で出⼒される時刻はどうなるか? 正解はC A. テストを実⾏した時の時刻 B. 2000-01-01 00:00:00 (UTC)
C. 2000-01-01 00:00:05 (UTC) (Runの仕様その3) Runはbubbleの中のすべてのゴルーチンがexitするまで待つ → サブのゴルーチンのtime.Sleepを待つ
おさらい! Q2. メインのゴルーチンのtime.Sleepを外すとどうなるか? 正解はA A. テストが落ちる B. flakyなテストになる C. テストは落ちない
(Waitの仕様その1) Waitは、現在のbubble内の現在のゴルーチン以外のすべてのゴルー チンが持続的にブロック (durably block) されるまでブロックする → サブのゴルーチンがブロックされたら、メインのゴルーチンの処 理が進む
まとめ
testing/synctestパッケージのまとめ 1. testing/synctestを使うとテストにかかる時間を短縮できる 2. synctest.Runの中のすべてのゴルーチンがブロックされてから、時刻が進む 3. synctest.Waitはゴルーチンの終了を待つわけではない a. durably blockになるのを待つ
4. GoDoc読むの⼤切 a. 直感的なコードの挙動と実際の挙動が違っていた 実際に導⼊されるかは分からないが⾯⽩い機能でした 😆
ありがとうございました