มันจะมีประสิทธิภาพมากขึ้นสำหรับระบบโดยทั่วไปที่จะทำอะไรกับ Stacks และเพียงแค่ใช้ Heap สำหรับการจัดการหน่วยความจำ


14

ฉันคิดว่าทุกอย่างที่สามารถทำได้ด้วย stack สามารถทำได้ด้วย heap แต่ไม่ใช่ทุกสิ่งที่สามารถทำได้ด้วย heap ที่สามารถทำได้ด้วย stack ถูกต้องหรือไม่ แล้วเพื่อความเรียบง่ายและแม้ว่าเราจะสูญเสียประสิทธิภาพเล็กน้อยไปกับปริมาณงานบางอย่างมันจะดีกว่าไหมที่จะไปกับมาตรฐานเดียว (เช่นกอง)?

คิดถึงการแลกเปลี่ยนระหว่างโมดุลและประสิทธิภาพ ฉันรู้ว่าไม่ใช่วิธีที่ดีที่สุดในการอธิบายสถานการณ์นี้ แต่โดยทั่วไปดูเหมือนว่าความเข้าใจและการออกแบบที่เรียบง่ายอาจเป็นตัวเลือกที่ดีกว่าแม้ว่าจะมีศักยภาพสำหรับประสิทธิภาพที่ดีขึ้น


1
ใน C และ C ++ คุณต้องจัดสรรหน่วยความจำอย่างชัดเจนที่จัดสรรไว้ในฮีป นั่นไม่ใช่เรื่องง่าย
user16764

ฉันใช้การใช้งาน C # โดยการทำโปรไฟล์เปิดเผยว่าวัตถุสแต็คได้รับการจัดสรรในพื้นที่ที่คล้ายกับกองขยะที่น่ากลัว ทางออกของฉัน? ย้ายทุกอย่างที่เป็นไปได้ (เช่นตัวแปรลูปตัวแปรชั่วคราว ฯลฯ ) ไปยังหน่วยความจำฮีปแบบถาวร ทำให้โปรแกรมกิน 10x RAM และทำงานที่ความเร็ว 10x
imallett

@IanMallett: ฉันไม่เข้าใจคำอธิบายปัญหาและวิธีแก้ปัญหาของคุณ คุณมีลิงค์พร้อมข้อมูลเพิ่มเติมที่ไหนสักแห่งหรือไม่? โดยทั่วไปฉันพบว่าการจัดสรรแบบกองซ้อนจะเร็วกว่า
Frank Hileman

@ FrankHileman ปัญหาพื้นฐานคือ: การใช้งาน C # ฉันใช้มีความเร็วในการเก็บขยะต่ำมาก "การแก้ปัญหา" คือการทำให้ตัวแปรทั้งหมดคงอยู่เพื่อให้ที่รันไทม์ไม่มีการดำเนินการของหน่วยความจำเกิดขึ้น ฉันเขียนความเห็นเมื่อไม่นานมานี้เกี่ยวกับการพัฒนา C # / XNA โดยทั่วไปซึ่งกล่าวถึงบริบทบางอย่าง
imallett

@IanMallett: ขอบคุณ ในฐานะนักพัฒนา C / C ++ ซึ่งส่วนใหญ่ใช้ C # ในปัจจุบันประสบการณ์ของฉันแตกต่างกันมาก ฉันพบว่าห้องสมุดเป็นปัญหาที่ใหญ่ที่สุด ดูเหมือนว่าแพลตฟอร์ม XBox360 นั้นได้รับการพัฒนาสำหรับผู้พัฒนา. net โดยปกติเมื่อฉันมีปัญหา GC ฉันเปลี่ยนไปใช้การรวมกำไร มันช่วยได้
Frank Hileman

คำตอบ:


30

การกองข้อมูลไม่ดีในการจัดสรรหน่วยความจำที่รวดเร็วและการจัดสรรคืน ถ้าคุณต้องการที่จะคว้าหน่วยความจำจำนวนเล็กน้อยในระยะเวลาที่ จำกัด ฮีปไม่ใช่ตัวเลือกที่ดีที่สุดของคุณ สแต็กที่มีอัลกอริธึมการจัดสรร / การจัดสรรคืนแบบ super-simple นั้นยอดเยี่ยมอย่างเป็นธรรมชาติ (ยิ่งกว่านั้นหากสร้างไว้ในฮาร์ดแวร์) ซึ่งเป็นสาเหตุที่ผู้คนใช้สิ่งต่าง ๆ เช่นการส่งอาร์กิวเมนต์ไปยังฟังก์ชั่น ข้อเสียที่สำคัญคือมันมีพื้นที่ จำกัด และการเก็บรักษาวัตถุขนาดใหญ่ไว้ในนั้นหรือพยายามที่จะใช้มันสำหรับวัตถุที่มีอายุยาวนานเป็นทั้งความคิดที่ไม่ดี

การกำจัดสแต็คอย่างสมบูรณ์เพื่อลดความซับซ้อนของภาษาการเขียนโปรแกรมเป็นวิธีที่ผิด IMO - วิธีที่ดีกว่าคือการแยกความแตกต่างออกไปให้คอมไพเลอร์คิดว่าควรใช้หน่วยความจำประเภทใดในขณะที่โปรแกรมเมอร์ ระดับการสร้างที่ใกล้เคียงกับที่มนุษย์คิด - และในความเป็นจริงภาษาระดับสูงเช่น C #, Java, Python และอื่น ๆ ทำสิ่งนี้อย่างแน่นอน พวกเขามีไวยากรณ์ที่เหมือนกันเกือบจะสำหรับวัตถุที่ได้รับการจัดสรรฮีปและแบบดั้งเดิมที่จัดสรรสแต็ก ('ประเภทการอ้างอิง' กับ 'ประเภทค่า' ใน. NET lingo) ทั้งโปร่งใสหรือมีความแตกต่างการทำงานเล็กน้อยซึ่งคุณต้องเข้าใจในการใช้ภาษา ถูกต้อง (แต่คุณไม่จำเป็นต้องรู้ว่า stack และ heap ทำงานอย่างไรภายใน)


2
นี่เป็นสิ่งที่ดี :) รัดกุมและให้ข้อมูลกับผู้เริ่มต้นจริงๆ!
Dark Templar

1
ใน CPUs จำนวนมากสแต็กจะถูกจัดการในฮาร์ดแวร์ซึ่งเป็นปัญหานอกภาษา แต่มันเล่นเป็นส่วนใหญ่ในเวลาทำงาน
Patrick Hughes

@ แพทริกฮิวจ์: ใช่ แต่ฮีปยังอยู่ในฮาร์ดแวร์ด้วยใช่ไหม?
Dark Templar

@Dark สิ่งที่ Patrick ต้องการจะพูดก็คือสถาปัตยกรรมเช่น x86 มีรีจิสเตอร์พิเศษเพื่อจัดการกับสแต็กและคำแนะนำพิเศษในการวางหรือลบบางอย่างใน / จากสแต็ก ทำให้มันค่อนข้างเร็ว
FUZxxl

3
@ Donal Fellows: จริงทั้งหมด แต่ประเด็นก็คือสแต็คและกองทั้งคู่มีจุดแข็งและจุดอ่อนของตนและการใช้งานตามลำดับจะทำให้ได้รหัสที่มีประสิทธิภาพที่สุด
tdammers

8

พูดง่ายๆคือสแต็กไม่ใช่ประสิทธิภาพเล็กน้อย มันเร็วกว่ากองหลายร้อยหรือหลายพันเท่า นอกจากนี้เครื่องจักรที่ทันสมัยส่วนใหญ่มีการสนับสนุนฮาร์ดแวร์สำหรับสแต็ก (เช่น x86) และฟังก์ชันการทำงานของฮาร์ดแวร์สำหรับเช่นสแตกการโทรไม่สามารถลบได้


คุณหมายถึงอะไรเมื่อคุณพูดว่าเครื่องจักรที่ทันสมัยมีฮาร์ดแวร์รองรับสแต็ก สแต็กเองนั้นมีอยู่ในฮาร์ดแวร์ใช่ไหม
Dark Templar

1
x86 มีการลงทะเบียนพิเศษและคำแนะนำสำหรับการจัดการกับกองซ้อน x86 ไม่รองรับฮีป - สิ่งเหล่านี้สร้างขึ้นโดยระบบปฏิบัติการ
Pubby

8

ไม่

พื้นที่สแต็คใน C ++ นั้นเทียบได้รวดเร็วอย่างไม่น่าเชื่อ ฉันร่วมไม่มีนักพัฒนา C ++ ที่มีประสบการณ์จะเปิดให้ปิดการใช้งานฟังก์ชั่นนั้น

ด้วย C ++ คุณมีทางเลือกและคุณสามารถควบคุมได้ นักออกแบบไม่ได้มีความโน้มเอียงที่จะแนะนำคุณสมบัติที่เพิ่มเวลาหรือพื้นที่ในการทำงานที่สำคัญ

การออกกำลังกายทางเลือกนั้น

หากคุณต้องการสร้างห้องสมุดหรือโปรแกรมที่ต้องการให้ทุกวัตถุได้รับการจัดสรรแบบไดนามิกคุณสามารถทำได้ด้วย C ++ มันจะดำเนินการค่อนข้างช้า แต่คุณสามารถมี 'โมดุล' สำหรับส่วนที่เหลือของเรา modularity เป็นตัวเลือกเสมอแนะนำตามความจำเป็นเพราะทั้งสองมีความจำเป็นสำหรับการใช้งานที่ดี / รวดเร็ว

ทางเลือก

มีภาษาอื่น ๆ ที่ต้องการที่เก็บข้อมูลสำหรับแต่ละวัตถุที่สร้างขึ้นบนฮีป มันค่อนข้างช้าเช่นที่มันประนีประนอมการออกแบบ (โปรแกรมโลกแห่งความจริง) ในทางที่เลวร้ายยิ่งกว่าต้องเรียนรู้ทั้งสอง (IMO)

ทั้งสองมีความสำคัญและ C ++ ช่วยให้คุณใช้พลังงานได้อย่างมีประสิทธิภาพสำหรับแต่ละสถานการณ์ ต้องบอกว่าภาษา C ++ อาจไม่เหมาะกับการออกแบบของคุณหากปัจจัยเหล่านี้ใน OP ของคุณมีความสำคัญต่อคุณ (ตัวอย่างเช่นอ่านในภาษาระดับสูงกว่า)


ฮีปนั้นมีความเร็วเท่ากันกับสแต็ก แต่ไม่มีการสนับสนุนฮาร์ดแวร์พิเศษสำหรับการจัดสรร ในอีกทางหนึ่งมีวิธีที่จะเร่งกองมาก (ขึ้นอยู่กับเงื่อนไขหลายประการที่ทำให้พวกเขามีเทคนิคเฉพาะผู้เชี่ยวชาญ)
Donal Fellows

@DonalFellows: การสนับสนุนฮาร์ดแวร์สำหรับสแต็กไม่เกี่ยวข้อง สิ่งสำคัญคือการรู้ว่าเมื่อใดก็ตามที่มีการเผยแพร่สิ่งหนึ่งอาจปล่อยสิ่งใดก็ตามที่ได้รับการจัดสรรหลังจากนั้น ภาษาการเขียนโปรแกรมบางภาษาไม่มีฮีปที่สามารถเพิ่มออบเจ็กต์ได้อย่างอิสระ แต่มีวิธี "ฟรีทุกอย่างที่จัดสรรหลังจาก"
supercat

6

แล้วเพื่อความเรียบง่ายและแม้ว่าเราจะสูญเสียประสิทธิภาพเล็กน้อยไปกับปริมาณงานบางอย่างมันจะดีกว่าไหมที่จะไปกับมาตรฐานเดียว (เช่นกอง)?

ที่จริงแล้วประสิทธิภาพการทำงานน่าจะมีมาก!

ตามที่คนอื่น ๆ ได้ชี้ให้เห็นว่าสแต็คเป็นโครงสร้างที่มีประสิทธิภาพอย่างมากสำหรับการจัดการข้อมูลที่เป็นไปตามกฎ LIFO (เข้าก่อนออกก่อน) การจัดสรร / การเพิ่มหน่วยความจำบนสแต็คมักจะเป็นเพียงการเปลี่ยนแปลงการลงทะเบียนบน CPU การเปลี่ยนรีจิสเตอร์นั้นเป็นหนึ่งในการดำเนินการที่เร็วที่สุดที่โปรเซสเซอร์สามารถทำได้

ฮีปมักเป็นโครงสร้างข้อมูลที่ค่อนข้างซับซ้อนและการจัดสรร / การเพิ่มหน่วยความจำจะมีคำแนะนำมากมายในการทำบัญชีที่เกี่ยวข้องทั้งหมด ยิ่งไปกว่านั้นในการใช้งานทั่วไปการเรียกทุกครั้งเพื่อทำงานกับฮีปจะต้องส่งผลให้เกิดการเรียกไปยังระบบปฏิบัติการ การเรียกระบบปฏิบัติการใช้เวลานานมาก! โดยทั่วไปแล้วโปรแกรมจะต้องเปลี่ยนจากโหมดผู้ใช้เป็นโหมดเคอร์เนลและเมื่อใดก็ตามที่สิ่งนี้เกิดขึ้นระบบปฏิบัติการอาจตัดสินใจว่าโปรแกรมอื่นมีความต้องการเร่งด่วนมากกว่าและโปรแกรมของคุณจะต้องรอ


5

Simula ใช้กองเพื่อทุกสิ่ง วางทุกอย่างบนกองเสมอเจือจางอีกหนึ่งระดับของความร้ายสำหรับตัวแปรท้องถิ่นและมันทำให้ความดันเพิ่มเติมเกี่ยวกับขยะสะสม (คุณต้องคำนึงว่านักสะสมขยะจริงๆดูดกลับมาแล้ว) ส่วนหนึ่งเป็นสาเหตุที่ Bjarne คิดค้น C ++


ดังนั้นโดยทั่วไป C ++ จะใช้ heap เท่านั้นเช่นกัน?
Dark Templar

2
@Dark: อะไรนะ? ไม่การขาดกองซ้อนใน Simula เป็นแรงบันดาลใจให้ทำได้ดีกว่า
fredoverflow

อาฉันเห็นสิ่งที่คุณหมายถึงตอนนี้! ขอบคุณ +1 :)
Templar มืด

3

สแต็คมีประสิทธิภาพอย่างมากสำหรับข้อมูล LIFO เช่น meta-data ที่เกี่ยวข้องกับการเรียกใช้ฟังก์ชันเป็นต้น สแต็กยังใช้ประโยชน์จากคุณสมบัติการออกแบบโดยธรรมชาติของ CPU เนื่องจากประสิทธิภาพในระดับนี้เป็นพื้นฐานของทุกสิ่งทุกอย่างในกระบวนการการที่ "น้อย" ในระดับนั้นจะเผยแพร่อย่างกว้างขวาง นอกจากนี้หน่วยความจำฮีปสามารถเคลื่อนย้ายได้โดยระบบปฏิบัติการซึ่งจะเป็นอันตรายต่อสแต็ก ในขณะที่สแต็กสามารถนำไปใช้ในฮีปได้ แต่ก็ต้องมีค่าใช้จ่ายที่จะส่งผลกระทบต่อกระบวนการทุกชิ้นในระดับที่ละเอียดที่สุด


2

"มีประสิทธิภาพ" ในแง่ของการเขียนโค้ดอาจ แต่ไม่ใช่ในแง่ของประสิทธิภาพซอฟต์แวร์ของคุณ การจัดสรรสแต็กนั้นฟรี (ใช้เพียงไม่กี่คำสั่งเครื่องในการย้ายสแต็คพอยเตอร์และจองพื้นที่บนสแต็กสำหรับตัวแปรในเครื่อง)

เนื่องจากการจัดสรรสแต็กนั้นแทบจะไม่มีเวลาเลยการจัดสรรแม้ในฮีปที่มีประสิทธิภาพมากจะเป็น 100k (หากไม่ใช่ 1M +) ของเวลาที่ช้ากว่า

ตอนนี้ลองนึกภาพว่ามีตัวแปรท้องถิ่นและโครงสร้างข้อมูลอื่น ๆ ที่แอปพลิเคชันทั่วไปใช้อยู่ ทุกๆ "i" ตัวน้อยที่คุณใช้เป็นตัวนับลูปจะถูกจัดสรรช้ากว่าล้านครั้ง

แน่นอนว่าถ้าฮาร์ดแวร์เร็วพอคุณสามารถเขียนแอปพลิเคชันที่ใช้เฉพาะฮีป แต่ตอนนี้คุณสามารถเขียนแอปพลิเคชันประเภทใดถ้าคุณใช้ประโยชน์จากฮีปและใช้ฮาร์ดแวร์เดียวกัน


เมื่อคุณพูดว่า "ลองนึกภาพว่าตัวแปรโลคัลจำนวนเท่าใดและโครงสร้างข้อมูลอื่น ๆ ที่แอปพลิเคชันทั่วไปใช้" โครงสร้างข้อมูลอื่นใดที่คุณอ้างถึงโดยเฉพาะ?
Dark Templar

1
ค่า "100k" และ "1M +" เป็นวิทยาศาสตร์หรือไม่? หรือเป็นเพียงวิธีที่จะพูดว่า "มาก"?
Bruno Reis

@Bruno - IMHO ตัวเลข 100K และ 1M ที่ฉันใช้คือการประมาณการแบบอนุรักษ์นิยมเพื่อพิสูจน์จุด หากคุณคุ้นเคยกับ VS และ C ++ ให้เขียนโปรแกรมที่จัดสรร 100 ไบต์บนสแต็กและเขียนหนึ่งรายการที่จัดสรร 100 ไบต์บนฮีป จากนั้นสลับไปที่มุมมองถอดแยกชิ้นส่วนและเพียงนับจำนวนคำแนะนำการประกอบแต่ละครั้งใช้การจัดสรร การดำเนินการฮีปมักจะมีการเรียกใช้ฟังก์ชันหลายอย่างใน windows DLL มีที่เก็บข้อมูลและรายการที่เชื่อมโยงจากนั้นก็รวมตัวกันและอัลกอริทึมอื่น ๆ ด้วยสแต็คมันสามารถต้มลงไปหนึ่งคำสั่งการชุมนุม "เพิ่ม esp, 100" ...
DXM

2
"100k (หากไม่ใช่ 1M +) ของเวลาจะช้าลง"? มันพูดเกินจริงไปหน่อย ปล่อยให้มันเป็นสองคำสั่งของขนาดช้ากว่าอาจจะสาม แต่นั่นมัน อย่างน้อยลีนุกซ์ของฉันสามารถทำการจัดสรรฮีป 100M (+ คำแนะนำโดยรอบ) ในเวลาน้อยกว่า 6 วินาทีในคอร์ i5 ที่ไม่สามารถมากกว่าสองร้อยคำสั่งต่อการจัดสรร - จริง ๆ แล้วมันเกือบจะแน่นอน ถ้าหกคำสั่งของขนาดที่ช้ากว่าสแต็กจะมีบางอย่างผิดปกติกับการใช้ฮีปของระบบปฏิบัติการ แน่ใจว่ามีข้อผิดพลาดมากมายกับ Windows แต่นั่น ...
ซ้าย

1
ผู้ดูแลอาจจะฆ่าเธรดความคิดเห็นทั้งหมดนี้ ดังนั้นนี่คือข้อตกลงฉันยอมรับว่าตัวเลขจริงถูกดึงออกมาจาก .... ของฉัน แต่ขอยอมรับว่าปัจจัยนั้นใหญ่จริง ๆ และไม่ได้ให้ความเห็นเพิ่มเติม :)
DXM

2

คุณอาจสนใจ "การรวบรวมขยะเร็ว แต่สแต็คเร็วกว่า"

http://dspace.mit.edu/bitstream/handle/1721.1/6622/AIM-1462.ps.Z

ถ้าฉันอ่านอย่างถูกต้องพวกเหล่านี้แก้ไขคอมไพเลอร์ C เพื่อจัดสรร "สแต็กเฟรม" บนฮีปจากนั้นใช้การรวบรวมขยะเพื่อยกเลิกการจัดสรรเฟรมแทนการแตกสแต็ก

สแต็ก "สแต็กเฟรม" ที่จัดสรรได้ดีกว่า "สแต็กเฟรม" ที่จัดสรรโดยฮีปอย่างเด็ดขาด


1

กองการโทรจะทำงานกับฮีปได้อย่างไร โดยพื้นฐานแล้วคุณจะต้องจัดสรรสแต็คบนฮีปในทุกโปรแกรมดังนั้นทำไมไม่มี OS + ฮาร์ดแวร์ทำเช่นนั้นสำหรับคุณ

หากคุณต้องการให้สิ่งต่าง ๆ เรียบง่ายและมีประสิทธิภาพเพียงให้หน่วยความจำกับผู้ใช้และให้พวกเขาจัดการกับมัน แน่นอนไม่มีใครต้องการที่จะใช้ทุกอย่างด้วยตนเองและนั่นคือเหตุผลที่เรามีกองและกอง


การพูดอย่างเคร่งครัด "call stack" ไม่ใช่คุณสมบัติที่จำเป็นของสภาพแวดล้อมรันไทม์ภาษาโปรแกรม เช่นการใช้งานตรงไปตรงมาของภาษาหน้าที่ประเมินอย่างขี้เกียจโดยการลดกราฟ (ซึ่งฉันเขียนไว้) ไม่มี call stack แต่ call call เป็นเทคนิคที่มีประโยชน์และใช้กันอย่างแพร่หลายโดยเฉพาะอย่างยิ่งโปรเซสเซอร์ที่ทันสมัยถือว่าคุณใช้และได้รับการปรับให้เหมาะสมสำหรับการใช้งาน
Ben

@Ben - ในขณะที่มันเป็นความจริง (และสิ่งที่ดี) กับสิ่งที่เป็นนามธรรมเช่นการจัดสรรหน่วยความจำจากภาษานี้จะไม่เปลี่ยนสถาปัตยกรรมคอมพิวเตอร์ที่แพร่หลายในขณะนี้ ดังนั้นรหัสการลดกราฟของคุณจะยังคงใช้สแต็กเมื่อทำงานเหมือนหรือไม่
Ingo

@Ingo ไม่ได้มีความหมายใด ๆ แน่นอนว่าระบบปฏิบัติการจะเริ่มต้นส่วนของหน่วยความจำแบบดั้งเดิมที่เรียกว่า "สแต็ก" และจะมีการลงทะเบียนชี้ไปที่มัน แต่ฟังก์ชั่นในภาษาต้นฉบับไม่ได้แสดงให้เห็นว่าเป็นสแต็กเฟรมในลำดับการโทร การดำเนินการของฟังก์ชั่นนั้นแสดงโดยการจัดการโครงสร้างข้อมูลในฮีป แม้ว่าจะไม่มีการใช้การเพิ่มประสิทธิภาพการโทรครั้งล่าสุดก็ตาม แต่ก็ไม่สามารถ "ล้นสแต็ค" ได้ นั่นคือสิ่งที่ฉันหมายถึงเมื่อฉันบอกว่าไม่มีอะไรพื้นฐานเกี่ยวกับ "โทรสแต็ค"
Ben

ฉันไม่ได้พูดถึงฟังก์ชั่นของภาษาต้นฉบับ แต่ฟังก์ชั่นในล่าม (หรืออะไรก็ตาม) ที่จริงลดกราฟ พวกนั้นจะต้องสแต็ค สิ่งนี้เห็นได้ชัดเนื่องจากฮาร์ดแวร์ร่วมสมัยไม่ลดกราฟ ดังนั้นอัลกอริธึมการลดกราฟของคุณจะถูกแมปกับเครื่องในที่สุดและฉันคิดว่ามีการเรียกรูทีนย่อยระหว่างพวกเขา QED
Ingo

1

ต้องใช้ทั้งสแต็กและฮีป พวกเขาจะใช้ในสถานการณ์ที่แตกต่างกันเช่น:

  1. การจัดสรรฮีปมีข้อ จำกัด ที่ sizeof (a [0]) == sizeof (a [1])
  2. การจัดสรรสแต็กมีข้อ จำกัด ที่ sizeof (a) เป็นค่าคงที่เวลารวบรวม
  3. การจัดสรรฮีปสามารถทำลูปกราฟและโครงสร้างข้อมูลที่ซับซ้อนได้
  4. การจัดสรรสแต็กสามารถทำแผนผังขนาดเวลารวบรวม
  5. กองต้องติดตามความเป็นเจ้าของ
  6. การจัดสรรสแต็กและการจัดสรรคืนอัตโนมัติ
  7. หน่วยความจำฮีปสามารถส่งผ่านจากขอบเขตหนึ่งไปอีกขอบเขตหนึ่งได้อย่างง่ายดายผ่านตัวชี้
  8. หน่วยความจำสแต็คนั้นมีอยู่ในแต่ละฟังก์ชันและวัตถุจะต้องถูกย้ายไปยังขอบเขตด้านบนเพื่อยืดอายุการใช้งาน (หรือเก็บไว้ในวัตถุแทนที่จะเป็นฟังก์ชันสมาชิกภายใน)
  9. ฮีปไม่ดีต่อประสิทธิภาพ
  10. สแต็คค่อนข้างเร็ว
  11. อ็อบเจ็กต์ฮีปถูกส่งคืนจากฟังก์ชันผ่านตัวชี้ที่เป็นเจ้าของ หรือ shared_ptrs
  12. วัตถุสแต็กจะถูกส่งคืนจากฟังก์ชั่นผ่านการอ้างอิงที่ไม่ได้เป็นเจ้าของ
  13. Heap ต้องการการจับคู่ใหม่ทุกประเภทด้วยการลบหรือลบที่ถูกต้อง []
  14. วัตถุสแต็คใช้ RAII และรายการเริ่มต้นของตัวสร้าง
  15. วัตถุฮีปสามารถเริ่มต้นได้ทุกจุดภายในฟังก์ชั่นและไม่สามารถใช้พารามิเตอร์คอนสตรัคเตอร์ได้
  16. วัตถุสแต็กใช้พารามิเตอร์ตัวสร้างสำหรับการเริ่มต้น
  17. ฮีปใช้อาร์เรย์และขนาดอาร์เรย์สามารถเปลี่ยนแปลงได้ในรันไทม์
  18. สแต็คสำหรับวัตถุเดี่ยวและขนาดได้รับการแก้ไขในเวลารวบรวม

โดยทั่วไปกลไกไม่สามารถเปรียบเทียบได้เลยเพราะรายละเอียดมากมายแตกต่างกัน สิ่งเดียวที่พบได้ทั่วไปกับพวกเขาก็คือพวกเขาทั้งสองจัดการกับหน่วยความจำอย่างใด


1

คอมพิวเตอร์สมัยใหม่มีหน่วยความจำแคชหลายชั้นนอกเหนือจากระบบหน่วยความจำหลักขนาดใหญ่ แต่ช้า หนึ่งสามารถเข้าถึงหน่วยความจำแคชที่เร็วที่สุดในเวลาที่จำเป็นในการอ่านหรือเขียนหนึ่งไบต์จากระบบหน่วยความจำหลัก ดังนั้นการเข้าถึงที่ตั้งหนึ่งพันครั้งจึงเร็วกว่าการเข้าถึงสถานที่อิสระ 1,000 แห่ง (หรือ 100 แห่ง) แต่ละแห่ง เนื่องจากแอปพลิเคชั่นส่วนใหญ่จัดสรรและยกเลิกการจัดสรรหน่วยความจำขนาดเล็กจำนวนมากใกล้กับด้านบนสุดของสแต็คตำแหน่งที่อยู่ด้านบนสุดของสแต็กจะถูกใช้งานและใช้ซ้ำจำนวนมหาศาลเช่นส่วนใหญ่ (99% + ในแอปพลิเคชันทั่วไป) ของการเข้าถึงสแต็กสามารถจัดการได้โดยใช้หน่วยความจำแคช

ในทางตรงกันข้ามหากแอปพลิเคชันต้องสร้างและละทิ้งวัตถุฮีปซ้ำ ๆ เพื่อเก็บข้อมูลความต่อเนื่องทุกรุ่นของทุกวัตถุสแต็กที่เคยสร้างขึ้นจะต้องถูกเขียนลงในหน่วยความจำหลัก แม้ว่าวัตถุดังกล่าวส่วนใหญ่จะไร้ประโยชน์อย่างสมบูรณ์ในเวลาที่ CPU ต้องการรีไซเคิลหน้าแคชที่เริ่มต้นมา แต่ CPU จะไม่มีทางรู้ได้ ดังนั้น CPU จะต้องเสียเวลามากในการเขียนหน่วยความจำช้าของข้อมูลที่ไร้ประโยชน์ ไม่ใช่สูตรสำหรับความเร็ว

สิ่งที่ต้องพิจารณาอีกประการหนึ่งคือในหลายกรณีการรู้ว่าการอ้างอิงวัตถุที่ส่งผ่านไปยังรูทีนนั้นจะไม่มีประโยชน์เมื่อออกจากรูทีน หากพารามิเตอร์และตัวแปรท้องถิ่นถูกส่งผ่านผ่านสแต็กและหากการตรวจสอบรหัสของชุดคำสั่งแสดงให้เห็นว่ามันไม่ได้เก็บสำเนาของการอ้างอิงแบบพาส - อินรหัสที่เรียกรูทีนนั้นสามารถมั่นใจได้ว่าหากไม่มีการอ้างอิงจากภายนอก วัตถุมีอยู่ก่อนการโทรไม่มีจะมีอยู่หลังจากนั้น ในทางตรงกันข้ามถ้าพารามิเตอร์ถูกส่งผ่านวัตถุฮีปแนวคิดเช่น "หลังจากส่งคืนรูทีน" จะค่อนข้างคลุมเครือมากขึ้นเพราะถ้ารหัสเก็บสำเนาของความต่อเนื่องมันจะเป็นไปได้สำหรับรูทีนที่จะ "ส่งคืน" มากกว่าหนึ่งครั้ง สายเดียว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.