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
41
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
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
710
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
610
これって Effect でできたのでは? / TSKaigi Mashup Kansai #2
susisu
0
240
Detecting Compromised CI with eBPF and Cilium Tetragon
lizrice
0
200
リアルな遅延を測る仕様
kota_yata
1
110
Japan Community Day at Kubecon + CloudNativeCon Japan 2026: Learning Container Privilege Control by Building My Own Low-Level Container Runtime
ternbusty
1
160
S3 を使うアプリケーションをローカル完結で動かすことに全力を注いでみた / Running S3 Apps Offline
contour_gara
0
510
GDG Korea Android: 2026 I/O Extended ~ What's new in Android development tools
pluu
0
230
テーブルをDELETEした
yuzneri
0
140
仕様駆動開発の消費期限
watany
20
8.5k
変わらないものが、変わるものを決める — 意図駆動開発 × イベントソーシング × イミュータブル | What Doesn't Change Decides What Can — IDD × Event Sourcing × Immutability
tomohisa
0
1.8k
【QA Test Talk Vol.8】AI-DLC による Whole Team Approach の加速
pkshadeck
PRO
0
190
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
174
15k
Mobile First: as difficult as doing things right
swwweet
225
10k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
430
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
710
Code Reviewing Like a Champion
maltzj
528
40k
Balancing Empowerment & Direction
lara
6
1.2k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
The Spectacular Lies of Maps
axbom
PRO
1
910
30 Presentation Tips
portentint
PRO
1
370
SEO for Brand Visibility & Recognition
aleyda
0
4.7k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.9k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.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が壊れたことがきっかけで普段、意識していない領域に触れられた 今後さらに知⾒を深めることで業務に活かしたい