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
500
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
tanukistack ライブコーディング / tanukistack live-coding
mackee
0
76
perl for shell, awk and sed programmers
mackee
2
2k
今更GoのWebフレームワークを作ろうとしているワケ / Why am I trying to create a Go web framework now?
mackee
1
430
database/sqlでNullを扱う歴史とsql.Null[T]の登場 / sql.Null[T] history
mackee
0
350
マイクロサービス化を利用した Goへの移行事例
mackee
0
480
PerlでつくるフルスクラッチWebAuthn/パスキー認証 / Demonstration of full-scratch WebAuthn/Passkey Authentication written in Perl
mackee
3
4.1k
SRE定例やその辺の取り組みをアプリケーションエンジニア目線で語る / "Observe" about SRE Meeting by Application Engineer
mackee
0
1.9k
TinyGoで使えるORM sqllaの 紹介とTinyGoで使えるようにするための工夫
mackee
0
1.4k
Go向けORM sqllaの紹介と JOINやUNIONを含んだクエリの扱い方
mackee
0
4.9k
Other Decks in Programming
See All in Programming
Empowering Developers with HTML-Aware ERB Tooling @ RubyKaigi 2025, Matsuyama, Ehime
marcoroth
2
650
Compose Hot Reload is here, stop re-launching your apps! (Android Makers 2025)
zsmb
1
510
AHC045_解説
shun_pi
0
530
API for docs
soutaro
2
1.3k
Agentic Applications with Symfony
el_stoffel
2
300
gen_statem - OTP's Unsung Hero
whatyouhide
1
200
Coding Experience Cpp vs Csharp - meetup app osaka@9
harukasao
0
750
ミリしらMCP勉強会
watany
4
760
Being an ethical software engineer
xgouchet
PRO
0
210
リアルタイムレイトレーシング + ニューラルレンダリング簡単紹介 / Real-Time Ray Tracing & Neural Rendering: A Quick Introduction (2025)
shocker_0x15
1
310
「”誤った使い方をすることが困難”な設計」で良いコードの基礎を固めよう / phpcon-odawara-2025
taniguhey
0
150
Defying Front-End Inertia: Inertia.js on Rails
skryukov
0
480
Featured
See All Featured
Designing Experiences People Love
moore
141
24k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
120k
Producing Creativity
orderedlist
PRO
344
40k
Optimizing for Happiness
mojombo
377
70k
Java REST API Framework Comparison - PWX 2021
mraible
30
8.5k
RailsConf 2023
tenderlove
30
1.1k
Site-Speed That Sticks
csswizardry
5
490
A designer walks into a library…
pauljervisheath
205
24k
Raft: Consensus for Rubyists
vanstee
137
6.9k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
GitHub's CSS Performance
jonrohan
1030
460k
Why Our Code Smells
bkeepers
PRO
336
57k
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ʹม͢Δ͕ؔ͋ΔͷͰݟͯ͘Εʂ