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
gocon_after_party_osaki.pdf
Search
zaiho
November 22, 2025
Programming
39
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
gocon_after_party_osaki.pdf
zaiho
November 22, 2025
Other Decks in Programming
See All in Programming
才能?センス?知らん、 続けたもん勝ちだ。-- 結婚・出産・癌を越えてなお、私がプロダクトを創り続ける理由
16bitidol
2
910
ソフトウェア設計に溶けるインフラ ― AWS CDK のインフラ認識論
konokenj
3
650
Android CLI
fornewid
0
180
php-fpmのプロセスが枯渇した日-調査・対処・そして本当にやるべきだったこと-
shibuchaaaan
0
140
AI時代の仕事技芸論〜ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ(スクフェス仙台 2026バージョン)
kuranuki
0
720
AI時代、エンジニアはどう育つのか -未経験エンジニアの成長を間近で見て考えたこと-
thasu0123
0
150
【やさしく解説 設計編 #1】「ドメイン駆動」と「実装駆動」ってなに? 〜設計の考え方を、たとえ話で学ぼう〜
panda728
PRO
1
130
壊れたパーサから始める関数型設計と構成的なパーサ #fp_matsuri
raiga0310
2
400
関数型プログラミングのメリットって何だろう?
wanko_it
0
190
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
shogogg
0
370
初めてのKubernetes 本番運用でハマった話
oku053
0
130
GDG Korea Android: 2026 I/O Extended ~ What's new in Android development tools
pluu
0
170
Featured
See All Featured
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
640
Test your architecture with Archunit
thirion
1
2.3k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.3k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
230
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
510
Marketing to machines
jonoalderson
1
5.6k
New Earth Scene 8
popppiees
3
2.4k
The Limits of Empathy - UXLibs8
cassininazir
1
540
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.2k
Code Reviewing Like a Champion
maltzj
528
40k
Leo the Paperboy
mayatellez
8
1.9k
How to build a perfect <img>
jonoalderson
1
5.8k
Transcript
愛⽤PCの不具合から始まった、 Goで体感するメモリの世界 Go Night Talks ‒ After Conference
SPEAKER 株式会社ヤプリ サーバーサイドエンジニア ⼤﨑 敬太 • 24新卒として⼊社 • Yappli CRMの開発に従事
• 最近はPHP多め • 好きな⽔は「財宝」
ゲームを起動しただけなのに • ゲームを起動してプレイするたびにブルースクリーン(Windowsが破壊)
1. パーツの不具合を切り分け a. ❌メモリを交換 b. ❌マザボを交換 c. ❌SSDを交換 d. ❌グラボを交換
2. 操作の切り分け a. ✅ブラウジング b. ✅ベンチマークツール c. ❌ゲーム 原因の切り分け ベンチマークツールも ブラウジングもできるし、 CPUは怪しくなさそうやな ⾃分
1. パーツの不具合を切り分け a. ❌メモリを交換 b. ❌マザボを交換 c. ❌SSDを交換 d. ❌グラボを交換
2. 操作の切り分け a. ✅ブラウジング b. ベンチマークツール c. ❌某FPSゲーム 原因の切り分け ゲームってCPUキャッシュ めっちゃ使うからそれが怪 しいじゃない? 友⼈ ...なるほど?
「CPUキャッシュ」に アクセスしやすいコードを書けば、 CPUが原因であることがわかるのでは...?
ネタバレです 実は「原因」は 不明のままPCは死亡しました😇 (CPU変えたら動作したのでCPUのどっかが悪かったです) そのため、仮説検証のために私が⾏ったことを追っていきたいと思います!
そもそもCPUとかメモリの 仕組みをよくわかってない( ̄▽ ̄;)
CPUとメモリ メイン メモリ 左であればあるほどアクセスは⾼速 L3 コアN L1 L2 コアN L1
L2 CPU
CPUとメモリ • キャッシュライン ◦ 固定の⼤きさの連続した64バイトのメモリセグメント ◦ 1つの変数ではなく、まとまった単位でメインメモリからフェッチ • データアライメント ◦
メモリアクセス⾼速化のための、データの割り当て s := make([]int64, 64) for i := range s { s[i] = int64(i + 1) } fmt.Printf("s0: %p (%d)\n", &s[0], uintptr(unsafe.Pointer(&s[0]))) fmt.Printf("s1: %p (%d)\n", &s[1], uintptr(unsafe.Pointer(&s[1]))) fmt.Printf("s2: %p (%d)\n", &s[2], uintptr(unsafe.Pointer(&s[2]))) fmt.Printf("s3: %p (%d)\n", &s[3], uintptr(unsafe.Pointer(&s[3]))) // s0: 0x1400011a000 (1374390689792) // s1: 0x1400011a008 (1374390689800) // s2: 0x1400011a010 (1374390689808) // s3: 0x1400011a018 (1374390689816) s[0] s[1] s[2] s[3]
CPUとメモリ - 寄り道 - • データアライメント ◦ 型によってはパディングが発⽣する type Book
struct { id int32 enable bool title string author string sealed bool publisher string } // Size: 64 実は末尾に 余裕がある type Book struct { title string author string publisher string id int32 enable bool sealed bool } // Size: 56 type Book struct { title string author string publisher string id int32 enable bool sealed bool bool1 bool bool2 bool } // Size: 56 最適化
検証⽅針 • 隙間なくキャッシュラインに格納できるスライスを⽤意! ◦ パディングを発⽣させない • 無限ループで参照しまくるように! • いざ参らん!!! package
main import ( "fmt" "runtime" "sync/atomic" "time" "unsafe" ) type CacheLineData struct { val0 int64 val1 int64 val2 int64 val3 int64 val4 int64 val5 int64 val6 int64 val7 int64 } func printMemStats(label string) { var m runtime.MemStats runtime.ReadMemStats(&m) fmt.Printf("\n=== %s ===\n", label) fmt.Printf("Alloc = %v MiB", m.Alloc/1024/1024) fmt.Printf("\tTotalAlloc = %v MiB", m.TotalAlloc/1024/1024) fmt.Printf("\tSys = %v MiB", m.Sys/1024/1024) fmt.Printf("\tNumGC = %v\n", m.NumGC) } func main() { fmt.Printf("CacheLineData size: %d bytes\n", unsafe.Sizeof(CacheLineData{})) const sliceSize = 512 data := make([]CacheLineData, sliceSize) printMemStats("スライス確保後") // 初期化 for i := range data { data[i].val0 = int64(i) data[i].val1 = int64(i * 2) data[i].val2 = int64(i * 3) data[i].val3 = int64(i * 4) data[i].val4 = int64(i * 5) data[i].val5 = int64(i * 6) data[i].val6 = int64(i * 7) data[i].val7 = int64(i * 8) } printMemStats("初期化後") var iterations atomic.Uint64 ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() fmt.Println("\nL1キャッシュアクセスループ開始 (Ctrl+Cで停止)") go func() { for { <-ticker.C count := iterations.Swap(0) fmt.Printf("Iterations: %d million (avg: %d M/sec)\n", count/1_000_000, count/1_000_000) printMemStats("実行中") } }() var sum int64 for { for i := range data { sum += data[i].val0 sum += data[i].val1 sum += data[i].val2 sum += data[i].val3 sum += data[i].val4 sum += data[i].val5 sum += data[i].val6 sum += data[i].val7 } iterations.Add(1) fmt.Println(sum) } }
• WindowsのインストールUSBをbootに コードをぶん回すゾォ!
まとめ • 学び ◦ メモリの仕組み ▪ まだまだCPUやメモリは不思議がたくさん ◦ メモリを意識したGo ▪
データアライメント ◦ 計測ツール ▪ pprof ▪ -bench, -gcflags PCが壊れたことがきっかけで普段、意識していない領域に触れられた 今後さらに知⾒を深めることで業務に活かしたい