สแตกกับฮีปและการวิเคราะห์การหลุดพ้น
ทำความเข้าใจว่า Go ตัดสินใจจัดสรรหน่วยความจำไว้ที่ใด
สแตกกับฮีปและการวิเคราะห์การหลุดพ้น เป็นบทเรียน Go Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Go Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน
การจัดสรรบนสแตก
ตัวแปรภายในที่ไม่หลุดออกจากฟังก์ชันจะถูกจัดสรรบนสแตกของ goroutine การจัดสรรบนสแตกทำได้รวดเร็ว เพราะเพียงเพิ่มพอยน์เตอร์ และไม่มีต้นทุนในการเก็บคืน เนื่องจากเฟรมสแตกจะถูกนำออกเมื่อส่งคืนค่าจากฟังก์ชัน
การจัดสรรบนฮีป
ตัวแปรที่หลุดไปยังฮีปจะถูกจัดสรรด้วยตัวจัดสรรของ Go และถูกติดตามโดยตัวเก็บขยะ การจัดสรรบนฮีปช้ากว่าและเพิ่มภาระให้ GC
อะไรทำให้เกิดการหลุดออกจากสแตก
สาเหตุทั่วไปที่ทำให้ค่าหลุดออก ได้แก่ การนำที่อยู่ของตัวแปรภายในไปใช้แล้วส่งคืน การเก็บตัวแปรภายในไว้ในอินเทอร์เฟซ หรือการส่งตัวแปรผ่านแชนเนล การวิเคราะห์การหลุดออกของคอมไพเลอร์จะเป็นผู้ตัดสินเรื่องนี้
func newUser() *User { // *User escapes to heap
return &User{Name: "Alice"}
}go build -gcflags=-m
แสดงผลการตัดสินใจจากการวิเคราะห์การหลุดออก:
go build -gcflags="-m" .
// main.go:10:15: &User literal escapes to heap
// main.go:5:14: s does not escapeสแตกของ Goroutine
แต่ละ goroutine จะเริ่มต้นด้วยสแตกขนาดเล็ก (2 KiB ใน Go 1.14 ขึ้นไป) ซึ่งจะขยายแบบไดนามิกตามความจำเป็น สแตกแยกจากฮีป และจะถูกเก็บคืนเมื่อ goroutine สิ้นสุดการทำงาน
การหลีกเลี่ยงการจัดสรร
ส่งค่า ไม่ใช่พอยน์เตอร์ สำหรับโครงสร้างขนาดเล็ก ใช้อาร์เรย์ที่จัดสรรบนสแตกแทนสไลซ์เมื่อทราบขนาดแน่นอน ส่งคืนค่าแทนพอยน์เตอร์เพื่อให้ค่าเหล่านั้นคงอยู่บนสแตก
การบรรจุค่าในอินเทอร์เฟซ
การกำหนดค่าชนิดรูปธรรมให้กับอินเทอร์เฟซจะทำให้ค่าหลุดไปยังฮีป หรือที่เรียกว่าการบรรจุค่า สำหรับเส้นทางที่ทำงานบ่อย ให้รับชนิดรูปธรรม หรือใช้เจเนอริกแทนอินเทอร์เฟซ
sync.Pool
นำออบเจ็กต์ที่จัดสรรบนฮีปกลับมาใช้ใหม่ด้วย sync.Pool เพื่อลดภาระของ GC จากการจัดสรรออบเจ็กต์อายุสั้นบ่อยครั้ง เช่น บัฟเฟอร์และบริบทของคำขอ
var pool = sync.Pool{New: func() any { return make([]byte, 1024) }}
buf := pool.Get().([]byte)
defer pool.Put(buf[:0])การทำโพรไฟล์การจัดสรร
ใช้ go test -benchmem และการทำโพรไฟล์ฮีปด้วย -alloc_space เพื่อค้นหาฟังก์ชันที่จัดสรรหน่วยความจำมากที่สุด
สไลซ์เทียบกับอาร์เรย์
อาร์เรย์ขนาดเล็ก [N]T อาจคงอยู่บนสแตก ส่วนส่วนหัวของสไลซ์ (24 ไบต์) จะถูกจัดสรรบนสแตก แต่อาร์เรย์เบื้องหลังอาจหลุดออกได้ การจัดสรรล่วงหน้าด้วย make ช่วยหลีกเลี่ยงการจัดสรรใหม่ซ้ำ ๆ
การทำให้สตริงใช้พื้นที่ร่วมกัน
ลิเทอรัลสตริงจะไม่ถูกจัดสรรบนฮีป เพราะอยู่ในเซกเมนต์ข้อมูลแบบอ่านอย่างเดียว การแปลง []byte เป็นสตริงจะทำให้เกิดการจัดสรร ให้แคชสตริงที่ใช้บ่อยเพื่อหลีกเลี่ยงการแปลงซ้ำ
ตรวจสอบความเข้าใจ
อะไรทำให้ตัวแปรภายในหลุดจากสแตกไปยังฮีป
สรุป: สแตกเทียบกับฮีป
ประเด็นสำคัญ:
- สแตก: รวดเร็วและไม่มีต้นทุน GC ฮีป: ช้ากว่าและถูกติดตามโดย GC
- go build -gcflags="-m" แสดงการตัดสินใจเกี่ยวกับการหลุดออก
- การบรรจุค่าในอินเทอร์เฟซ การนำที่อยู่ของตัวแปรภายในไปใช้ และการส่งผ่านแชนเนลทำให้ค่าเกิดการหลุดออก
- ใช้ sync.Pool สำหรับออบเจ็กต์ที่จัดสรรและทิ้งบ่อย
คำถามที่พบบ่อย
บทเรียน “สแตกกับฮีปและการวิเคราะห์การหลุดพ้น” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “สแตกกับฮีปและการวิเคราะห์การหลุดพ้น” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Go Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “สแตกกับฮีปและการวิเคราะห์การหลุดพ้น”
ทำความเข้าใจว่า Go ตัดสินใจจัดสรรหน่วยความจำไว้ที่ใด คุณปฏิบัติ Go Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Go Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Go Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “สแตกกับฮีปและการวิเคราะห์การหลุดพ้น” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Go Academy นี้ได้ไหม
ได้ บทเรียน Go Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- สแตกกับฮีปและการวิเคราะห์การหลุดพ้น
- โมเดลหน่วยความจำของ Go และ Happens-Before
- ภายในตัวเก็บขยะ
- ลดการจัดสรร: sync.Pool และ Arena