จากงาน Golang meetup ครั้งที่ 1 ของกลุ่ม
Golang Thailand
มีการพูดถึงเรื่องการทำ profiling ทั้ง CPU และ Memory
ทำการวิเคราะห์และหา code ที่ใช้ทรัพยากรมากเกินไป
เพื่อทำการปรับปรุงประสิทธิภาพการทำงานของ code ให้ดีขึ้น
ดังนั้นลองมาฝึกกันหน่อยสิ
เริ่มด้วย code ที่เขียนเอาไว้ แน่นอนว่าต้องมีชุดการทดสอบด้วย
เป็น code ของระบบ web application ว่าด้วยการบวกเลข !!
มันจะง่ายไปไหม ? แต่ไม่เป็นไร !!
โดยใน code นั้นมีการทำงานดังนี้
- รับจากจาก query string มีสองตัวคือ operand1 และ operand2
- ทำการแปลงข้อมูลจาก String เป็น Int
- ทำการบวกเลข
- ผลลัพธ์แสดงออกมาด้วย template
code เริ่มต้นเป็นดังนี้
[gist id="d689193018b4d75612045ab0c40c557a" file="original_add.go"]
มีชุดการทดสอบดังนี้
[gist id="d689193018b4d75612045ab0c40c557a" file="add_test.go"]
ก่อนจะทำอะไรต่อไปต้องทดสอบให้ผ่านก่อน !!
[code]
$go test
[/code]
จากนั้นมาเริ่มทำ CPU profiling กันเลย
ด้วยคำสั่ง
[code]
$go test -run none -bench . -benchtime 3s -benchmem -cpuprofile cpu.out
[/code]
ได้ผลการทำงานดังนี้
[gist id="d689193018b4d75612045ab0c40c557a" file="1.txt"]
ทำการวิเคราะห์ CPU profile ด้วย pprof
[code]
$go tool pprof profiling.test cpu.out
[/code]
จากนั้นจะเข้าสู่ interactive mode (สำหรับมือใหม่จะงงมาก ๆ ว่าต้องพิมพ์อะไรต่อไป)
สามารถอ่านเพิ่มเติมได้ที่
Golang :: Blog :: Profiling go program
[code]
Entering interactive mode (type "help" for commands)
(pprof)
[/code]
ต้องการดูว่ามี function ไหนบ้างใช้งาน CPU เยอะ ๆ ด้วย top20
[gist id="d689193018b4d75612045ab0c40c557a" file="top20.txt"]
ต้องการดู function ที่ใช้งานเยอะ ๆ แบบชัด ๆ
[gist id="d689193018b4d75612045ab0c40c557a" file="top_cum.txt"]
function handleAdd() ใช้ CPU เยอะเลยนะ
ไปดูใน function นี้กันหน่อยสิ
[gist id="d689193018b4d75612045ab0c40c557a" file="handleAdd_list.txt"]
ยังไม่พอ มาดูในรูปแบบกราฟกันหน่อย
ด้วยการใส่คำสั่ง web list handleAdd
แสดงผลดังนี้
มาถึงต้องนี้ทำให้เราเห็นว่า
บรรทัดที่ 24 เข้าใช้งาน CPU ถึง 4.92 วินาที !!
น่าจะเป็นจัดที่น่าสนใจ เพื่อทำงาน optimize code ต่อไปนะ
สิ่งที่ใช้เวลาการทำงานเยอะ ๆ คือ
การเปิดไฟล์ template ขึ้นทำงานนั่นเอง
นั่นคือ function template.parseFile() !!
จาก code จะเห็นว่าทำการ parseFile() ทุก request
ซึ่งเป็นวิธีการที่แย่มาก ๆ
ดังนั้นมาทำการแก้ไข code ดีกว่า
ด้วยการ parseFile() ครั้งเดียวพอ
[gist id="d689193018b4d75612045ab0c40c557a" file="new_add.go"]
จากนั้นทำการทดสอบใหม่อีกรอบ
[gist id="d689193018b4d75612045ab0c40c557a" file="new_bench.txt"]
สังเกตุไหมว่า performance ดีขึ้นเยอะมาก ๆ
ลองดูกราฟสิ
อีกสักนิดลองทำการเปรียบเทียบผลการทดสอบด้วย
benchcmp นิดหน่อย
[gist id="d689193018b4d75612045ab0c40c557a" file="compare.txt"]
มาถึงตรงนี้เราทำเพียง CPU profiling นะ
ยังเหลือ
Memory profiling อีกนะ แต่เอาไว้ก่อนดีกว่า !!
โดย code ที่ใช้งานอยู่ที่
Github :: Web Add Number
ขอให้สนุกกับการ coding ครับ
Reference Websites
https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go
https://medium.com/@hackintoshrao/analyzing-benchmarks-with-ease-using-benchcmp-and-benchviz-golang-add607fc46d6