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
range over funcの使い道と非同期N+1リゾルバーの夢 / about a ran...
Search
mackee
December 13, 2024
Programming
0
670
range over funcの使い道と非同期N+1リゾルバーの夢 / about a range over func
kamakura.go #7
mackee
December 13, 2024
Tweet
Share
More Decks by mackee
See All by mackee
ワンバイナリWebサービスのススメ
mackee
10
7.8k
tanukistack ライブコーディング / tanukistack live-coding
mackee
0
110
perl for shell, awk and sed programmers
mackee
2
2.3k
今更GoのWebフレームワークを作ろうとしているワケ / Why am I trying to create a Go web framework now?
mackee
1
630
database/sqlでNullを扱う歴史とsql.Null[T]の登場 / sql.Null[T] history
mackee
0
530
マイクロサービス化を利用した Goへの移行事例
mackee
0
650
PerlでつくるフルスクラッチWebAuthn/パスキー認証 / Demonstration of full-scratch WebAuthn/Passkey Authentication written in Perl
mackee
3
4.6k
SRE定例やその辺の取り組みをアプリケーションエンジニア目線で語る / "Observe" about SRE Meeting by Application Engineer
mackee
0
1.9k
TinyGoで使えるORM sqllaの 紹介とTinyGoで使えるようにするための工夫
mackee
0
1.5k
Other Decks in Programming
See All in Programming
A full stack side project webapp all in Kotlin (KotlinConf 2025)
dankim
0
120
MDN Web Docs に日本語翻訳でコントリビュートしたくなる
ohmori_yusuke
1
120
High-Level Programming Languages in AI Era -Human Thought and Mind-
hayat01sh1da
PRO
0
770
20250628_非エンジニアがバイブコーディングしてみた
ponponmikankan
0
680
Code as Context 〜 1にコードで 2にリンタ 34がなくて 5にルール? 〜
yodakeisuke
0
130
git worktree × Claude Code × MCP ~生成AI時代の並列開発フロー~
hisuzuya
1
570
『自分のデータだけ見せたい!』を叶える──Laravel × Casbin で複雑権限をスッキリ解きほぐす 25 分
akitotsukahara
2
640
地方に住むエンジニアの残酷な現実とキャリア論
ichimichi
5
1.5k
A2A プロトコルを試してみる
azukiazusa1
2
1.4k
10 Costly Database Performance Mistakes (And How To Fix Them)
andyatkinson
0
330
LT 2025-06-30: プロダクトエンジニアの役割
yamamotok
0
760
Python型ヒント完全ガイド 初心者でも分かる、現代的で実践的な使い方
mickey_kubo
1
110
Featured
See All Featured
It's Worth the Effort
3n
185
28k
Making the Leap to Tech Lead
cromwellryan
134
9.4k
Into the Great Unknown - MozCon
thekraken
40
1.9k
The Pragmatic Product Professional
lauravandoore
35
6.7k
Rebuilding a faster, lazier Slack
samanthasiow
82
9.1k
Building Better People: How to give real-time feedback that sticks.
wjessup
367
19k
GitHub's CSS Performance
jonrohan
1031
460k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
10
950
A better future with KSS
kneath
238
17k
Documentation Writing (for coders)
carmenintech
72
4.9k
Transcript
range over funcͷ͍ಓͱ ඇಉظN+1Ϧκϧόʔͷເ @mackee_w
Δਓ • X: @mackee_w • GitHub: @mackee • ໘ന๏ਓΧϠοΫ •
όοΫΤϯυ & SRE • ࠷ۙRAGύΠϓϥΠϯͳͲΛࢼ࡞ ͍ͯ͠·͢
range over func͓͞Β͍ + ͍ಓ
Go 1.23 Release NotesΑΓ
ͬ͘͟Γ range over ** Go language specΑΓ
ͬ͘͟Γrange over func • for range … ͷ … ʹೖΕΒΕΔͭͰɺҙͷڍಈΛ͢Δ͕ͭ࡞ΕΔΑ͏
ʹͳΓ·ͨ͠Α • ݴޠઃܭଆͷҙਤ: ෮ॲཧͷҰൠԽ͞Εͨॲཧύλʔϯɺͭ·ΓΠςϨʔ λʔΛݴޠػೳͱͯ͠ΈࠐΜͩ • *database/sql.Rows *bu fi o.ScannerͳͲΠςϨʔλʔΛಠࣗʹ࣮͠ ͍ͯΔ(ͦͯͦ͠ΕͧΕΠϯλʔϑΣΠε͕ҧ͏) • ͜ΕΒΛେ౷Ұ͢Δҙਤ͕͋ΔͷͰͳ͍͔(ཁग़య)
ͬ͘͟Γ͍ํ
iter.Seqࣗ࡞ͯ͠ྑ͍ • ҙͷྻจࣈྻΛϧʔϓ͝ͱʹ ੜ͠ଓ͚Δ܅࡞ΕΔ • ଞͷrange over **ͱҧ͍ɺແݶʹ Λు͖ग़͢ͷ࡞ΕΔ •
👉ͷྻΛՃ͍ͯͯ͠͠Δ
օ͞Μ͕͙͢ʹ͑Δศརؔ slices.Chunk
iter.Seqผʹfor rangeͰΘͳͯ͘ྑ͍ • iter.Seq slices.Collect ͰεϥΠεʹมͰ͖Δ • ແݶʹΛుͭ͘ऴΘΒͳ͍ͷͰҙ •
εϥΠεͷΑ͏ͳσʔλྻΛදݱ͢ΔσʔλΛ͞ΒʹநԽͨ͠ܕͱݴ͑Δ • github.com/BooleanCat/go-functional/v2/it ʹศརϢʔςΟϦςΟ͕ؔ͋Δ • ͍ΘΏΔ github.com/samber/lo ͷ iter.Seq/iter.Seq2൛ • it.Map/it.Map2, it.Filter/it.Filter2 ͳͲ • x/exp/xiter ύοέʔδʹಉछͷ͕ؔೖΔ͜ͱ͕ٞ͞Ε͍ͯΔ
ࠓ·Ͱͷ + ͬͱதͷ͕ҎԼͷεϥΠυ ʹ͋Δ • Go Conference 2024: ΠςϨʔλʹΑͬͯGoͲ͏มΘΔͷ͔ •
https://gocon.jp/2024/sessions/2/
TIPS: օ͞Μ͕͙͢ʹ͑Δศརؔ slices.Chunk • sliceΛׂͯ͠ෳݸͷsliceΛฦ͢iter.Seq[[]E]Λ࡞Δ • Ͳ͏͍͏໘ʹศར͔ʁ => όϧΫͰॲཧ͍͕ͨ͠ɺҰؾʹΓ͗͢ Δͷྑ͘ͳ͍࣌
• SQLͰIN۟Λ༻͍ͨόϧΫऔಘ • Ұʹ͛ΒΕΔID͕nݸʹ੍ݶ͞Ε͍ͯΔόϧΫऔಘAPI
ඇಉظN+1Ϧκϧόʔͷເ
N+1 • ιγϟήͷྫ: users ςʔϒϧʹ user_weapons(උث) ςʔϒϧ͕ has-many Ͱ ͍͍ͭͯΔɻҰཡͰuserͱඋثΛηοτͰग़͍ͨ͠
• φΠʔϒͳ࣮: SELECT * FROM users WHERE … • ্هͰҾͬு͖ͬͯͨ݁ՌΛߦ͝ͱʹSELECT * FROM user_weapons WHERE user_id = ? • usersͷߦ͝ͱʹSQL͕ൃߦ͞Εͯ͠·͏ͨΊɺRDBMS·Ͱͷ௨৴Φʔόʔϔο υɺSQLύʔείετɺͳͲͳͲ͕ੵΈॏͳΓϨεϙϯελΠϜ͕ྼԽ͢Δ
GraphQLN+1͕ຊ࣭తʹى͜Γ͕ͪ • GraphQLͰɺ͋Δϊʔυʹඥͮ͘ࢠڙͷϊʔυΛऔΔΑ͏ͳΫΤϦΛΫϥΠ Ξϯτ͕ಈతʹΈཱͯͯൃߦ͢Δ͜ͱ͕Ͱ͖Δ • ී௨ʹφΠʔϒʹ࣮͢ΔͱN+1͕ൃੜ͢Δʂ • ͦ͜ͰGraphQLքͰdataloaderͱ͍͏ςΫ͕·͍ͬͯΔ • GoͷdataloaderͰɺϊʔυͷղܾΛඇಉظʹ͢Δ
+ छྨ͝ͱͷϊʔυͷղ ܾϦΫΤετΛόοϑΝϦϯάͯ͠όϧΫͰॲཧ͢Δ • dataloaderʹ͍ͬͯΕ΄ͱΜͲͷN+1͍͍ײ͡ʹղܾ͞ΕΔ
ҰํRESTfulͷN+1ղܾํ๏ • ϨεϙϯεͷΈཱͯํϑϨʔϜϫʔΫͰͳ͘ΞϓϦέʔγϣϯ ίʔυͷ • => dataloaderͷΑ͏ʹఆܕԽͰ͖ͳ͍ • ΄ͱΜͲͷέʔεͰεϥΠεΛฦ͢ͱ͖ʹಉظతʹεϥΠεͷதΛ ॱ൪ʹΈཱͯͯߦ͍ͬͯΔͷͰdataloaderͷద༻Ͱ͖ͳ͍
• => εϥΠεͷղܾΛඇಉظʹ͢Εྑ͍ͷͰʁ
github.com/mackee/iterutils/async.Map • go-functional/v2/it.Mapͷඇಉظ൛ • async.Map2͋ΔΑʂ • ͜ΕͰεϥΠεͷࢠͷϊʔυͷղܾΛdataloaderʹͤΔ͜ͱ͕Ͱ ͖ΔͷͰͳ͍͔
͍ํ
sync.WaitGroupͰࣄΓΔͷͰʁ • ҧ͍ͱͯ͠ɺॏͶ͕͚͕Մೳ • async.MapiterΛड͚ೖΕΔ ͭ·Γit.Mapasync.MapΛෳճ ֻ͚߹ΘͤΔ͜ͱ͕Ͱ͖Δ • ॲཧͷ࣮ߦࣗମɺslices.Collect ͞ΕΔ·ͰԆ͞ΕΔ
• ͪͳΈʹॱ൪ೖΕͨiter.Seqͷॱ൪ʹྻͯ͠ฦ͢Α͏ʹͳͬͯ ͍·͢
async.Map2ͷ͍ํ • errgroup.Groupʹ૬ • iter.Seq2[V, error] Λฦ͢ • it.TryCollectiter.Seq2[V, error]Λ৯ͯͲΕ͔ҰͭͰ
error͕͋Εଧͪͬͯ errorΛฦ͢
github.com/vikstrous/dataloadgen • GoͰdataloaderΛߦ͏ͭ • GenericsΛ͍ͬͯΔͷ Ͱੜ͠ͳͯ͘ศར(ର vektah/dataloaden)
࣮ࡍૣ͘ͳΔ͔ݕূͯ͠ΈΔ • ӈਤͷςʔϒϧΛ༻ҙ • fi xtureΛೖΕͨ users: 10000, items: 10000
user_items: 100000 • ϥϯμϜͰ500݅IDࢦఆͨ͠users ΛऔΓɺ͞Βʹ͍࣋ͬͯΔitemΛ ͱΔૢ࡞ • FkΠϯσοΫεష͍ͬͯͳ͍
N+1͕͋Δঢ়ଶͷίʔυ
Dataloaderʹͨ͠ͱ͖ͷಉ༷ͷίʔυ
Dataloaderʹͨ͠ͱ͖ͷಉ༷ͷίʔυ
ϕϯν݁Ռ 100ഒۙ͘ͷ͕͍ࠩͭͨ
ͦͷଞͷߟ • ࣮ISUCONͷաڈͰͬͯείΞ͕ͦΜͳʹ্͕Βͳ͍ • ਪଌ: CPU/ϝϞϦ੍͕ݶ͞Ε͍ͯͨΓ͢Δ͔Βʁ • ͔ͳΓgoroutineΛىಈ͢ΔͨΊʁ • ͔࣮͠͠ࡍͷݱͰgqlgen/dataloader͕ػೳ͍ͯ͠ΔҎ্ɺ͜ͷ
ख๏༗ޮͦ͏ͱݴ͑Δ • (͕͜͜λΠτϧͷʮເʯཁૉͰ͢)
·ͱΊ • GraphQLͰͳ͍໘ͰdataloaderΛ͏߹ʹɺasync.Map/ async.Map2͕༻Ͱ͖Δ͜ͱΛࣔͨ͠ • ͦͯ͋͠ΔఔޮՌతͰ͋Δ͜ͱ͕Θ͔ͬͨ • async.Map/dataloaderΛ͏ͱطଘͷσʔλΈཱͯͷߏ͔Β͋ ·Γม͑ͳͯ͘ྑ͍ͷͰϦϑΝΫλʹศར •
AΛݺͿͷʹBͷmap͕ඞཁΈ͍ͨͳґଘؔݮΒͤΔ
Ҏ্Ͱ͢ʂ • ͦͷଞ͓Βͤ: gitHub.com/mackee/iterutils ʹطଘͷΠςϨʔλͬ Ά͍interfaceΛiter.Seqʹม͢Δ͕ؔ͋ΔͷͰݟͯ͘Εʂ