ไบต์ส่วนตัว, ไบต์เสมือน, ชุดการทำงานคืออะไร


490

ฉันพยายามใช้ยูทิลิตี perfmon windows เพื่อดีบักการรั่วไหลของหน่วยความจำในกระบวนการ

นี่คือวิธีที่ perfmon อธิบายข้อกำหนด:

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

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

Private Bytesเป็นขนาดหน่วยความจำปัจจุบันของหน่วยความจำที่กระบวนการนี้จัดสรรไว้ซึ่งไม่สามารถแชร์กับกระบวนการอื่นได้

นี่คือคำถามที่ฉันมี:

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

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

มีความสัมพันธ์ระหว่างไบต์ส่วนตัว, ชุดการทำงานและไบต์เสมือนหรือไม่?

มีเครื่องมืออื่นใดที่ให้แนวคิดที่ดีกว่าเกี่ยวกับการใช้หน่วยความจำหรือไม่?


3
เครื่องมือที่ดีกว่าจะ valgrind / helgrind แต่ไม่โชคร้ายภายใต้ Windows :(
คอร์เนลคิซีลวิซ ซ์

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

@SergeiKurenkov สิ่งหนึ่งที่เราสามารถพูดได้คือมันไม่เคยเกิดจาก "การกระจายตัวของหน่วยความจำ"
เจมี่ Hanrahan

คำตอบ:


517

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

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

Working Setหมายถึงหน่วยความจำกายภาพทั้งหมด(RAM) ที่ใช้โดยกระบวนการ อย่างไรก็ตามไม่เหมือนกับไบต์ส่วนตัวซึ่งรวมถึงไฟล์ที่แม็พหน่วยความจำและแหล่งข้อมูลอื่น ๆ ดังนั้นจึงเป็นการวัดที่แม่นยำน้อยกว่าไบต์ส่วนตัว นี่เป็นค่าเดียวกับที่ได้รับรายงานใน "การใช้งาน Mem" ของ Task Manager และเป็นที่มาของความสับสนไม่รู้จบในไม่กี่ปีที่ผ่านมา หน่วยความจำในชุดการทำงานคือ "กายภาพ" ในแง่ที่ว่าสามารถแก้ไขได้โดยไม่มีข้อผิดพลาดของหน้า อย่างไรก็ตามรายการหน้าสแตนด์บายยังคงอยู่ในหน่วยความจำ แต่ไม่ได้รายงานในชุดการทำงานและนี่คือสาเหตุที่คุณอาจเห็น "การใช้ Mem" ลดลงอย่างกระทันหันเมื่อคุณย่อแอปพลิเคชันให้เล็กที่สุด

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

ดังนั้นความสัมพันธ์คือ:

  • ไบต์ส่วนตัวคือสิ่งที่แอปของคุณจัดสรรจริง แต่รวมถึงการใช้ไฟล์เพจ
  • Working Set เป็น Private Bytes ที่ไม่มีการทำเพจรวมทั้งไฟล์ที่แม็พหน่วยความจำ
  • ไบต์เสมือนเป็นชุดการทำงานพร้อมกับเพจส่วนตัวไบต์และรายการสแตนด์บาย

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

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

หนึ่งในเครื่องมือที่มีประสิทธิภาพที่สุดสำหรับการตรวจจับ / แก้ไขการรั่วไหลของหน่วยความจำใน Windows คือVisual Studio (ลิงค์ไปที่หน้าเกี่ยวกับการใช้ VS สำหรับการรั่วไหลของหน่วยความจำไม่ใช่หน้าผลิตภัณฑ์) Rational Purifyเป็นไปได้อีกอย่างหนึ่ง Microsoft ยังมีเอกสารแนวปฏิบัติที่ดีที่สุดทั่วไปเพิ่มเติมในเรื่องนี้ มีเครื่องมืออื่น ๆ ที่ระบุไว้ในนี้คำถามก่อนหน้านี้

ฉันหวังว่าสิ่งนี้จะล้างสิ่งเล็ก ๆ น้อย ๆ ! การติดตามการรั่วไหลของหน่วยความจำเป็นหนึ่งในสิ่งที่ยากที่สุดในการแก้ไขข้อบกพร่อง โชคดี.


26
ฉันกลัวว่าคำตอบของคุณจะไม่ถูกต้องนัก ไบต์ส่วนตัวหมายถึงจำนวนหน่วยความจำ (RAM) ที่กระบวนการที่เรียกใช้งานได้ร้องขอ - ไม่เพียง แต่หน่วยความจำกายภาพ ดังนั้นคุณสามารถตรวจสอบกรณีการรั่วไหลของหน่วยความจำส่วนใหญ่ได้อย่างแน่นอนโดยการตรวจสอบไบต์ส่วนตัว ลอง :: VisualAlloc คอมมิตหน่วยความจำขนาดใหญ่ (พูด 1.5G) คุณควรเห็นว่าไบต์ส่วนตัวของคุณใหญ่กว่าชุดการทำงาน ซึ่งพิสูจน์ว่า "ชุดการทำงานของคุณเป็นไบต์ส่วนตัวพร้อมไฟล์ที่แมปหน่วยความจำ" ไม่ถูกต้อง
Jay Zhu

4
ที่จริงฉันเชื่อว่าการเขียนคือ "Working Set เป็นไบต์ส่วนตัวในหน่วยความจำรวมถึงไฟล์ที่แมปหน่วยความจำ" และสามารถสลับไบต์ส่วนตัวได้คุณสามารถเห็นไบต์ส่วนตัวที่ใหญ่กว่าหน่วยความจำกายภาพที่คุณมีในเครื่อง
Jay Zhu

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

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

1
เรียกใช้เต็ม! objsize นี้ควรแสดงวัตถุใด ๆ ที่ตรึงไว้ในกองทันที คุณสามารถยืนยันได้โดยตรวจสอบ eeheap -gc สิ่งนี้จะแสดงให้คุณทราบว่าระดับเสียงติดอยู่ที่ใด โดยปกติหากไม่มีคำใบ้ใด ๆ พร้อมใช้งานกับคำสั่งทั้งหมดข้างต้นไบต์ส่วนตัวของคุณจะถูกใช้โดยวัตถุที่ไม่ได้รับการจัดเก็บใน GC ตอนนี้ย้ายไปที่ gchandles หรือ gcleaks คำสั่งเหล่านี้ควรบอกคุณว่าไม่สามารถแม็พที่อยู่ประเภท / วัตถุ ตัวชี้ยังคงอยู่ที่นั่น แต่วัตถุหายไป นี่เป็นปัญหาเชิงหมวดหมู่สำหรับตัวจัดการเหตุการณ์ที่ยังไม่เผยแพร่
G33kKahuna

10

คุณไม่ควรพยายามใช้ perfmon, task manager หรือเครื่องมือใด ๆ เช่นนั้นเพื่อกำหนดหน่วยความจำรั่ว พวกเขาดีสำหรับการระบุแนวโน้ม แต่ไม่มาก ตัวเลขที่รายงานในแง่สมบูรณ์นั้นคลุมเครือเกินไปและรวมกันว่ามีประโยชน์สำหรับงานเฉพาะเช่นการตรวจจับการรั่วไหลของหน่วยความจำ

คำตอบก่อนหน้าสำหรับคำถามนี้ได้ให้คำอธิบายที่ดีเกี่ยวกับประเภทต่างๆ

คุณถามเกี่ยวกับการแนะนำเครื่องมือ: ฉันแนะนำ Memory Validator ความสามารถในการตรวจสอบแอพพลิเคชั่นที่ทำการจัดสรรหน่วยความจำหลายพันล้าน

http://www.softwareverify.com/cpp/memory/index.html

ข้อจำกัดความรับผิดชอบ: ฉันออกแบบตัวตรวจสอบความจำ


1
ฉันไม่สามารถเรียกใช้ไฟล์คลาสอย่างง่าย (ใน Java) ได้หรือไม่ สิ่งที่ช่วยให้?
jn1kk

ฉันสงสัยว่าสตีเฟ่นและซาตานมีความสัมพันธ์กันหรือแม้แต่โคลน ... : D;)
Robert Koritnik

@StephenKellett มีรุ่นทดลองหรือไม่
Pacerier

@Pacerier หากคุณไปที่ลิงค์นี้จะมีทั้งรุ่น x86 และ x64 เหนือตัวเลือกซื้อทางด้านซ้ายของหน้า
Bradley A. Tetreault

10

คำจำกัดความของเคาน์เตอร์ perfmon นั้นใช้งานไม่ได้ตั้งแต่ต้นและด้วยเหตุผลบางอย่างดูเหมือนจะยากเกินกว่าจะแก้ไขได้

ภาพรวมที่ดีของการจัดการหน่วยความจำ Windows มีอยู่ในวิดีโอ " Mysteries of Memory Management Revealed " บน MSDN: ครอบคลุมหัวข้อมากกว่าที่จำเป็นในการติดตามการรั่วไหลของหน่วยความจำ (เช่นการจัดการชุดการทำงาน) แต่ให้รายละเอียดเพียงพอในหัวข้อที่เกี่ยวข้อง


เพื่อให้คำแนะนำปัญหาเกี่ยวกับคำอธิบายตัวนับ perfmon ต่อไปนี้เป็นเรื่องราวภายในเกี่ยวกับไบต์ส่วนตัวจาก " Private Bytes Performance Counter - ระวัง! " ใน MSDN:

ถาม: เมื่อไหร่ที่ Private Byte ไม่ใช่ Private Byte

ตอบ: เมื่อไม่มีผู้อยู่อาศัย

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


จาก " การวางแผนประสิทธิภาพ " บน MSDN:

3.3 ไบต์ส่วนตัว

3.3.1 คำอธิบาย

หน่วยความจำส่วนตัวหมายถึงหน่วยความจำที่จัดสรรสำหรับกระบวนการที่ไม่สามารถใช้ร่วมกันโดยกระบวนการอื่น หน่วยความจำนี้มีราคาแพงกว่าหน่วยความจำที่ใช้ร่วมกันเมื่อกระบวนการหลายอย่างดำเนินการบนเครื่อง หน่วยความจำส่วนตัวใน dlls ที่ไม่มีการจัดการ (ดั้งเดิม) มักจะประกอบด้วยสถิติของ C ++ และอยู่ในลำดับ 5% ของชุดการทำงานทั้งหมดของ dll


1
โหวตขึ้นเพราะตัวอย่างที่ดีเมามันเกี่ยวกับว่ามันพังได้อย่างไร!
Bruno Brant

คำพูดแรกเข้าใจผิด การจัดสรร "Private bytes" ไม่จำเป็นต้องมีสิ่งใด "จัดสรรในไฟล์ swap" (ซึ่งเรียกว่า pagefile จริง ๆ ) คุณไม่จำเป็นต้องมี pagefile สำหรับ "private bytes" ในการจัดสรร ในความเป็นจริงการจัดสรรไบต์ส่วนตัวไม่ได้ทันทีใช้ใดพื้นที่ใดก็ได้และอาจไม่เคยใช้มากที่สุดเท่าที่ได้รับการจัดสรร
เจมี่ Hanrahan

คำพูดที่สองนั้นไม่ค่อยดีนัก ไบต์ส่วนตัวที่ใช้ในรหัส DLL นั้นไม่จำเป็นว่าส่วนใหญ่จะถูกจัดสรรแบบคงที่ภายใน DLL รหัส DLL สมบูรณ์แบบไม่เสียค่าใช้จ่ายในการโทร VirtualAlloc, HeapAlloc (malloc และใหม่ใน CRTL) และอื่น ๆ นอกจากนี้ยังพยายามอธิบายขนาดหน่วยความจำส่วนตัวเป็นเปอร์เซ็นต์ของขนาดชุดการทำงานซึ่งไร้สาระ ก่อนหน้านี้มีขนาดเสมือน (และจะเหมือนกันสำหรับการใช้งานของรหัสที่มีอินพุตเดียวกันทุกครั้ง) ในขณะที่ตัวหลังเป็นแบบฟิสิคัล (ซึ่งอาจแตกต่างอย่างสิ้นเชิงจากการรันหนึ่งไปยังถัดไปขึ้นอยู่กับหน่วยความจำ หิวโหยเครื่องคือ)
เจมี่ Hanrahan

5

มีการสนทนาที่น่าสนใจที่นี่: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/307d658a-f677-40f2-bdef-e6352b0bfe9e/ ความเข้าใจของฉันเกี่ยวกับการจัดสรรเล็ก ๆ ไม่แสดงในไบต์ส่วนตัวหรือชุดการทำงาน

เรื่องสั้นสั้น:

ถ้าฉันโทร

p=malloc(1000);
free(p);

ไบต์ส่วนตัวจะแสดงเฉพาะการจัดสรรไม่ใช่การจัดสรรคืน

ถ้าฉันโทร

p=malloc(>512k);
free(p);

ไบต์ส่วนตัวจึงสะท้อนการจัดสรรและการจัดสรรคืนอย่างถูกต้อง


7
นี่คือคำอธิบายโดยข้อเท็จจริงที่ว่าฟังก์ชันหน่วยความจำไลบรารีมาตรฐาน C ใช้แบบกำหนดเองหรือ Win32 Heap ซึ่งเป็นกลไกการจัดการหน่วยความจำด้านบนของการจัดการหน่วยความจำระดับกระบวนการระดับต่ำ
Kyberias

@Kyberias แล้วเราจะลงมาด้านล่างได้อย่างไร?
Pacerier

ในขณะที่ (1) ฟรี (malloc (1,000)); // นี่จะทำให้ Private Bytes เพิ่มขึ้นตลอดไปไหม?
franckspike

2
@franckspike: ไม่จะเพิ่มเป็นจุดหนึ่ง (โดยทั่วไปประมาณ 4 kB แต่อาจแตกต่างกัน) แล้วหยุดเนื่องจาก CRT จะใช้หน่วยความจำที่ว่างก่อนหน้านี้แทนการร้องขอหน้าใหม่จากระบบปฏิบัติการ
Miral

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