0Pricing
Go Academy · บทเรียน

สแตกกับฮีปและการวิเคราะห์การหลุดพ้น

ทำความเข้าใจว่า 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. สแตกกับฮีปและการวิเคราะห์การหลุดพ้น
  2. โมเดลหน่วยความจำของ Go และ Happens-Before
  3. ภายในตัวเก็บขยะ
  4. ลดการจัดสรร: sync.Pool และ Arena
← กลับไปที่ Go Academy