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
800
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.9k
tanukistack ライブコーディング / tanukistack live-coding
mackee
0
110
perl for shell, awk and sed programmers
mackee
2
2.4k
今更GoのWebフレームワークを作ろうとしているワケ / Why am I trying to create a Go web framework now?
mackee
1
770
database/sqlでNullを扱う歴史とsql.Null[T]の登場 / sql.Null[T] history
mackee
0
650
マイクロサービス化を利用した Goへの移行事例
mackee
0
790
PerlでつくるフルスクラッチWebAuthn/パスキー認証 / Demonstration of full-scratch WebAuthn/Passkey Authentication written in Perl
mackee
3
4.9k
SRE定例やその辺の取り組みをアプリケーションエンジニア目線で語る / "Observe" about SRE Meeting by Application Engineer
mackee
0
2k
TinyGoで使えるORM sqllaの 紹介とTinyGoで使えるようにするための工夫
mackee
0
1.5k
Other Decks in Programming
See All in Programming
TypeScriptでDXを上げろ! Hono編
yusukebe
4
930
テスターからテストエンジニアへ ~新米テストエンジニアが歩んだ9ヶ月振り返り~
non0113
2
250
ソフトウェア設計とAI技術の活用
masuda220
PRO
25
7.3k
AIのメモリー
watany
12
1.2k
Git Sync を超える!OSS で実現する CDK Pull 型デプロイ / Deploying CDK with PipeCD in Pull-style
tkikuc
4
520
Understanding Kotlin Multiplatform
l2hyunwoo
0
250
MySQL9でベクトルカラム登場!PHP×AWSでのAI/類似検索はこう変わる
suguruooki
1
280
リバースエンジニアリング新時代へ! GhidraとClaude DesktopをMCPで繋ぐ/findy202507
tkmru
7
1.7k
リッチエディターを安全に開発・運用するために
unachang113
1
350
11年かかって やっとVibe Codingに 時代が追いつきましたね
yimajo
1
230
なぜ今、Terraformの本を書いたのか? - 著者陣に聞く!『Terraformではじめる実践IaC』登壇資料
fufuhu
3
380
実践 Dev Containers × Claude Code
touyu
1
120
Featured
See All Featured
Reflections from 52 weeks, 52 projects
jeffersonlam
351
21k
Automating Front-end Workflow
addyosmani
1370
200k
KATA
mclloyd
31
14k
Making the Leap to Tech Lead
cromwellryan
134
9.5k
The Cost Of JavaScript in 2023
addyosmani
51
8.7k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
1k
Faster Mobile Websites
deanohume
308
31k
Why Our Code Smells
bkeepers
PRO
337
57k
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.8k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.8k
Building an army of robots
kneath
306
45k
The Invisible Side of Design
smashingmag
301
51k
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ʹม͢Δ͕ؔ͋ΔͷͰݟͯ͘Εʂ