pprof Profiling
Node.js profiling vs Go pprof
หัวข้อที่มีชื่อว่า “Node.js profiling vs Go pprof”ใน Node.js คุณมี node --prof (V8 CPU profiler), node --inspect (Chrome DevTools) และเครื่องมืออย่าง clinic.js (clinic doctor, clinic flame) สำหรับวิเคราะห์ heap และ event loop ทั้งหมดทำงานแบบ out-of-process หรือไม่ก็ต้อง wrap คำสั่ง start
Go มาพร้อม runtime/pprof ใน standard library และ net/http/pprof สำหรับ profiling ผ่าน HTTP แบบ live — เก็บ profile ได้โดยไม่ต้องพึ่งเครื่องมือภายนอก และคำสั่ง go tool pprof ก็จัดการการวิเคราะห์ให้
หมายเหตุเรื่อง Playground: pprof ต้องเขียนไฟล์ profile ลง disk แล้วรัน
go tool pprofบล็อกโค้ดด้านล่างคือไฟล์จริง — รันบนเครื่องคุณ
สองวิธีในการเก็บ profile
หัวข้อที่มีชื่อว่า “สองวิธีในการเก็บ profile”1. File-based (สำหรับ script หรือ benchmark)
หัวข้อที่มีชื่อว่า “1. File-based (สำหรับ script หรือ benchmark)”package main
import ( "os" "runtime/pprof" "log")
func main() { // --- CPU profile --- cpuFile, err := os.Create("cpu.out") if err != nil { log.Fatal(err) } defer cpuFile.Close()
if err := pprof.StartCPUProfile(cpuFile); err != nil { log.Fatal(err) } defer pprof.StopCPUProfile()
// ... โค้ดที่ต้องการทดสอบ ... doWork()
// --- Heap profile (เขียนตอนท้าย) --- heapFile, err := os.Create("mem.out") if err != nil { log.Fatal(err) } defer heapFile.Close()
pprof.WriteHeapProfile(heapFile)}2. HTTP endpoint (สำหรับ server ที่รันยาว ๆ)
หัวข้อที่มีชื่อว่า “2. HTTP endpoint (สำหรับ server ที่รันยาว ๆ)”package main
import ( "net/http" _ "net/http/pprof" // blank import register routes /debug/pprof/ "log")
func main() { // Application server ของคุณ go func() { log.Println(http.ListenAndServe(":6060", nil)) }()
// ... rest of app ...}endpoint ที่มีให้:
http://localhost:6060/debug/pprof/— indexhttp://localhost:6060/debug/pprof/profile?seconds=30— CPU profile 30 วินาทีhttp://localhost:6060/debug/pprof/heap— heap snapshothttp://localhost:6060/debug/pprof/goroutine— stack ของทุก goroutinehttp://localhost:6060/debug/pprof/trace?seconds=5— execution trace
// Node.js — เครื่องมือหลายอย่าง ทั้งหมดภายนอก// Option 1: built-in V8 profilernode --prof server.jsnode --prof-process isolate-*.log > report.txt
// Option 2: clinic.js (npm install -g clinic)clinic doctor -- node server.jsclinic flame -- node server.js
// Option 3: Chrome DevToolsnode --inspect server.js // open chrome://inspect// Go — เครื่องมือเดียว มาพร้อม toolchain// Collect CPU profile 30 วินาที จาก live server:go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
// Collect จากไฟล์ที่เขียนโดย runtime/pprof:go tool pprof cpu.out
// เปิด interactive web UI (ต้องการ Graphviz):go tool pprof -http=:8080 cpu.outอ่าน CPU profile
หัวข้อที่มีชื่อว่า “อ่าน CPU profile”# เริ่ม interactive pprof shellgo tool pprof cpu.out
# ภายใน shell:(pprof) top10 # top 10 functions ตาม CPU time(pprof) list myFunc # annotated source สำหรับ myFunc(pprof) web # เปิด SVG flame graph ใน browser(pprof) pdf # save เป็น PDF
# หรือเปิด web UI โดยตรง (flame graphs สวยกว่า)go tool pprof -http=:8080 cpu.outตัวอย่าง output จาก top10:
Showing nodes accounting for 2.40s, 96.77% of 2.48s total flat flat% sum% cum cum% 1.20s 48.39% 48.39% 1.20s 48.39% runtime.mallocgc 0.60s 24.19% 72.58% 0.60s 24.19% strings.(*Builder).WriteString 0.30s 12.10% 84.68% 0.30s 12.10% main.processItem| คอลัมน์ | ความหมาย |
|---|---|
flat | เวลาที่ใช้ ใน ฟังก์ชันนี้ (ไม่รวม callees) |
flat% | เปอร์เซ็นต์ของ total profile time |
cum | เวลา cumulative (ฟังก์ชันนี้ + ฟังก์ชันทั้งหมดที่ฟังก์ชันนี้เรียกต่อ) |
cum% | เปอร์เซ็นต์ cumulative |
Heap profile
หัวข้อที่มีชื่อว่า “Heap profile”go tool pprof mem.out
(pprof) top10 -cum # top allocators ตาม cumulative bytes(pprof) list myFunc # line-level allocation countsheap profile แสดง:
- alloc_objects / alloc_space — allocation รวมทั้งหมดตั้งแต่โปรแกรมเริ่มรัน
- inuse_objects / inuse_space — object/byte ที่ยังถูกใช้อยู่ (หลัง GC)
Benchmarks + pprof ด้วยกัน
หัวข้อที่มีชื่อว่า “Benchmarks + pprof ด้วยกัน”# เขียน CPU + memory profiles ระหว่าง benchmark rungo test -bench=BenchmarkFoo -cpuprofile=cpu.out -memprofile=mem.out ./...
# แล้ว analysego tool pprof cpu.outgo tool pprof mem.outGoroutine และ trace profiles
หัวข้อที่มีชื่อว่า “Goroutine และ trace profiles”# ตรวจสอบ goroutine leaks (ควร flat ตลอดเวลา)go tool pprof http://localhost:6060/debug/pprof/goroutine
# Execution trace — แสดง scheduling, GC, goroutine lifecyclecurl -s "http://localhost:6060/debug/pprof/trace?seconds=5" > trace.outgo tool trace trace.outexecution trace คือมุมมองที่ละเอียดที่สุด: แสดงทุกครั้งที่ goroutine start/stop, ทุก GC pause, ทุกครั้งที่ block รอ network และ system call — คล้ายกับที่ clinic doctor ทำให้ event loop ของ Node