เธรดใช้หน่วยความจำเสมือนหรือหน่วยความจำจริงหรือไม่?


10

ฉันพยายามเพิ่มประสิทธิภาพเซิร์ฟเวอร์ Linux ของฉันเพื่อจัดการ 10,000 เธรดต่อกระบวนการในขณะที่มันเพิ่ง 382 ในขณะนี้ ตามบทความนี้จะใช้สูตรต่อไปนี้เพื่อค้นหาเธรดที่เป็นไปได้ทั้งหมด:

number of threads = total virtual memory / (stack size*1024*1024)

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

ดังนั้นคำถามของฉันคือเธรดของเราใช้ harddisk เพื่อเก็บประมวลผล / เก็บข้อมูล

ถ้าใช่แล้วประสิทธิภาพนี้จะไม่ได้ผลหรือไม่? เราสามารถปรับปรุงประสิทธิภาพโดยการใส่ไว้ใน RAM หรือแคชได้หรือไม่? อย่างไร?

ถ้าไม่มีเธรดทำงานอย่างไร

ปรับปรุง:

ตามคำตอบที่ไร้ประโยชน์หน่วยความจำเสมือนเป็นระบบที่ประกอบด้วย:

  • หน่วยความจำกายภาพ (RAM)
  • swapfiles ใด ๆ ที่คุณแนบ
  • การสนับสนุนฮาร์ดแวร์สำหรับการแปลที่อยู่เสมือนจริงไปยังที่อยู่จริงและการออกหน้าผิดพลาดเมื่อไม่มีที่อยู่เสมือนในหน่วยความจำกายภาพ
  • ซอฟต์แวร์สนับสนุน (เคอร์เนล) สำหรับ: การจัดการตารางการค้นหาที่ใช้โดยฮาร์ดแวร์นั้นที่จัดการข้อบกพร่องของหน้าเหล่านั้นโดยการดึงหน้าเข้าจาก swap ตามต้องการ

ดังนั้นทุกอย่างที่อยู่ในหน่วยความจำเสมือนจึงเรียกรวมกันใน RAM (หน่วยความจำจริง) และฮาร์ดดิสก์ (สลับไฟล์) และอย่างที่เจมส์อธิบายในการตัดสินใจตอบของเขาเกี่ยวกับ Ram vs HDD นั้นถูกใช้โดยเคอร์เนล


2
เว้นแต่ว่าเซิร์ฟเวอร์ของคุณมี 10,000 CPU / Cores คุณจะเสียเวลา

@JarrodRoberson: ทำไมล่ะ?
dragosrsupercool

3
10,000 เธรดไม่ได้เป็นวิธีที่ดีในการทำให้ขนาดต่าง ๆ มันเป็นวิธีที่ดีในการทำให้เซิร์ฟเวอร์มีการรวบรวมข้อมูลมากกว่า 1 เธรดต่อซีพียูหรือคอร์จะทำการสลับบริบทของเซิร์ฟเวอร์และทำงานช้าลงไม่เร็วขึ้น

โดยเฉพาะเมื่อคุณพูดว่า "พยายามเพิ่มประสิทธิภาพเซิร์ฟเวอร์ Linux ของฉัน" - คุณพยายามเพิ่มประสิทธิภาพอะไร ถ้าเป็นปริมาณงานแสดงว่าหนึ่งเธรดต่อ CPU ที่มีมัลติเพล็กซ์และไม่บล็อก I / O น่าจะดีกว่า
ไร้ประโยชน์

คำตอบ:


12

เพื่อความรู้ที่ดีที่สุดของฉันหน่วยความจำเสมือนคือพื้นที่สวอปในเครื่อง Linux

ไม่หน่วยความจำเสมือนเป็นระบบที่ประกอบไปด้วยคร่าวๆ:

  • หน่วยความจำกายภาพ (RAM)
  • swapfiles ใด ๆ ที่คุณแนบ
  • การสนับสนุนฮาร์ดแวร์สำหรับการแปลที่อยู่เสมือนจริงไปยังที่อยู่จริงและการออกหน้าผิดพลาดเมื่อไม่มีที่อยู่เสมือนในหน่วยความจำกายภาพ
  • ซอฟต์แวร์สนับสนุน (เคอร์เนล) สำหรับ:
    • การจัดการตารางการค้นหาที่ใช้โดยฮาร์ดแวร์นั้น
    • การจัดการข้อบกพร่องของหน้าเหล่านั้นโดยการดึงหน้าเข้าจาก swap ตามต้องการ

มันขึ้นอยู่กับเคอร์เนลเพื่อให้แน่ใจว่าหน่วยความจำเสมือนที่คุณต้องการถูกแคชไว้ใน RAM เมื่อคุณต้องการ - ยกเว้นว่าคุณกำลังเขียนเลเยอร์ VM ของ userpace ของคุณเอง (เช่นฐานข้อมูลมักจะทำ iiuc) เพียงแค่ไม่ต้องกังวล


ตกลงดังนั้นสมมติฐานหน่วยความจำเสมือนของฉันผิด อย่างไรก็ตามคำถามติดตามอย่างรวดเร็ว .. ประสิทธิภาพของเธรดสูงสุดที่โหลดเต็มจะได้รับผลกระทบหรือไม่หาก SWAP Space มากกว่า RAM?
dragosrsupercool

@dragosrsupercool: พื้นที่สวอปของคุณจะใหญ่กว่าหน่วยความจำกายภาพเสมอมิฉะนั้นคุณจะต้องใช้หน่วยความจำเสมือน
Bryan Oakley

1
@BryanOakley: นั่นไม่จำเป็นต้องเป็นเรื่องจริง ระบบปฏิบัติการบางระบบจะจัดสรรหน้าแลกเปลี่ยนสำหรับทุกหน้าเสมือนที่จัดสรร (เช่นสลับต้องมีขนาดใหญ่เท่ากับฟิสิคัล) ระบบปฏิบัติการอื่นจัดสรรหน้าแลกเปลี่ยนเฉพาะเมื่อมีความจำเป็นต้องย้ายหน้าออกจากหน่วยความจำกายภาพ (เช่นการแลกเปลี่ยนอาจน้อยกว่าทางกายภาพ) ข้อได้เปรียบของอดีตคือถ้าการจัดสรรสำเร็จแล้วการสลับหน่วยความจำนั้นจะประสบความสำเร็จเสมอ ข้อดีของข้อหลังคือคุณไม่จำเป็นต้องจัดสรรไฟล์ swap ขนาดใหญ่ในแง่ร้ายเพื่อพิจารณาสถานการณ์ที่ค่อนข้างหายาก
mcmcc

1
@dragosrsupercool ประสิทธิภาพจะไม่ได้รับผลกระทบจากปริมาณ RAM, swap หรืออัตราส่วนระหว่างมันเว้นแต่ว่าคุณมี RAM น้อยและการเพจจริง sar สามารถบอกคุณเกี่ยวกับกิจกรรมการเพจ iirc (ตรวจสอบ: sar -Bบน Linux)
ไร้ประโยชน์

@ ไม่มีประโยชน์: ฉันต้องการเพิ่มจำนวนเธรดจนกว่าฉันจะใช้ RAM อย่างสมบูรณ์และไม่เริ่มเพจจิ้ง
dragosrsupercool

14

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

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

ที่อยู่เสมือนถูกจัดระเบียบเป็นกลุ่มที่เรียกว่าหน้า (โดยปกติจะเป็นบล็อก 4096 หรือ 8192 ไบต์)

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

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

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

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

  • ที่อยู่จะถูกแมปบนพื้นฐาน "ต่อกระบวนการ" ดังนั้นตัวอย่างเช่นโปรแกรม C ทั้งหมดในกล่อง Linux เริ่มกระบวนการ "หลัก" ที่ที่อยู่เดียวกัน
  • สิ่งนี้สามารถเปิดใช้งานกระบวนการ 32 บิตหลายอย่างเพื่อครอบครองและใช้มากกว่า 4GB บนเครื่องเนื่องจากที่อยู่เสมือน 32 บิตสามารถแมปกับที่อยู่ 64 บิตจริง
  • เมื่อกระบวนการสิ้นสุดหรือหน่วยความจำเป็นอย่างอื่น "ฟรี" ระบบจะทำเครื่องหมายหน้าเว็บว่าว่างเท่านั้นมันจะไม่ถูกคัดลอกกลับไปที่ดิสก์สว็อป
  • ในทำนองเดียวกันเมื่อมีการร้องขอบล็อกหน่วยเก็บข้อมูลใหม่ระบบจะคว้าหน้าที่ว่างในหน่วยความจำจริงไม่ใช่ดิสก์ IO เกิดขึ้น
  • ฟังก์ชันสลีปและไฮเบอร์เนตบังคับให้หน่วยความจำทั้งหมดถูกคัดลอกไปยังพื้นที่สว็อปเพื่อให้กระบวนการปัจจุบันทั้งหมดและมีเนื้อหาหน่วยความจำปัจจุบันที่สามารถสร้างขึ้นใหม่ได้เมื่อปลุก

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

7

ก่อนอื่นคุณต้องอ่านเพิ่มเติมเกี่ยวกับหน่วยความจำคอมพิวเตอร์เพราะคุณดูเหมือนจะขาดความรู้ในด้านนั้น

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

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


@VJonvic: +1 สำหรับคำอธิบายเธรดพื้นฐาน
dragosrsupercool

6

คำตอบสำหรับคำถามของคุณคือใช้หน่วยความจำเสมือน ทุกอย่างใช้หน่วยความจำเสมือนยกเว้นกระบวนการที่เกี่ยวข้องกับระบบปฏิบัติการ

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


3

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

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


ใช่ 10,000 มากเกินไปเพราะเซิร์ฟเวอร์ของฉันเป็นเครื่องหลัก 32 บิต ที่จริงแล้วเธรดไม่ใช่สิ่ง cpu ทั้งหมด เป็นเธรดตัวรวบรวมข้อมูลดังนั้นพวกเขาจึงอยากรอการตอบกลับจากเซิร์ฟเวอร์ในบางครั้ง ฉันมุ่งมั่นที่จะทำให้แน่ใจว่า cpu นั้นถูกครอบครองโดยสมบูรณ์ แต่ไม่เกินหรือต่ำกว่า แต่ฉันก็ยังไม่เข้าใจว่าจะรู้ได้อย่างไรว่า CPU นั้นว่างหรือไม่ว่างทั้งหมด มีเครื่องมือหรือคำสั่งบ้างไหม?
dragosrsupercool

ฉันคิดว่าคุณสามารถรับข้อมูลนั้นได้จากtopคำสั่ง
Karl Bielefeldt

@KarlBieledeldt: ใช่นั่นคือสิ่งที่ฉันกำลังมองหา .. อีกหนึ่งคำถามติดตาม: ฉันเพิ่งมาพร้อมกับความคิดในการรวบรวมข้อมูลว่าหากมีวิธีหนึ่งเธรดที่สามารถส่งคำร้องขอ URL ในขณะที่เธรดอื่นได้รับการตอบกลับจากเซิร์ฟเวอร์ การใช้งาน CPU สูงโดยไม่ต้องใช้เธรดมากเกินไป เป็นไปได้ไหม เช่นเดียวกับการส่งคำขอจากเธรดหนึ่งขณะรับการตอบกลับจากเธรดอื่น
dragosrsupercool

2

ปรับแต่งเซิร์ฟเวอร์ Linux ของฉันเพื่อจัดการ 10,000 เธรดต่อกระบวนการ

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

อ่านระบบปฏิบัติการ: สามชิ้นง่าย (ตำราเรียนที่ดาวน์โหลดได้อย่างอิสระ)

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

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

บน Linux กระบวนการเป็นเพียงกลุ่มของเธรดที่แชร์พื้นที่ที่อยู่เสมือนเดียวกัน(และแบ่งปันสิ่งอื่น ๆ เช่นตารางตัวอธิบายไฟล์ ฯลฯ ... ) บางกระบวนการมีเพียงเธรดเดียว

พื้นที่ที่อยู่เสมือนจะถูกกำหนดโดยวิกิพีเดีย

"ชุดช่วงของที่อยู่เสมือนที่ระบบปฏิบัติการทำให้กระบวนการ"

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

บน Linux proc (5)มีประโยชน์ในการทำความเข้าใจพื้นที่ที่อยู่เสมือนของกระบวนการบางอย่าง ลองทั้งสอง
cat /proc/self/mapsและcat /proc/$$/mapsในสถานี ดูเพิ่มเติมนี้และpmap (1)และPS (1)และด้านบน (1)

โปรแกรมพื้นที่ผู้ใช้ทั้งหมดกำลังทำงานในบางกระบวนการและใช้หน่วยความจำเสมือนดังนั้นทุกกระบวนการมีพื้นที่ที่อยู่เสมือนของตัวเอง RAMจริงเป็นทรัพยากรที่จัดการโดยเคอร์เนล Linux และแอปพลิเคชันไม่สามารถเข้าถึง RAM โดยตรง (ยกเว้นโดยmmap (2) -ing /dev/mem, ดูmem (4) )

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

คุณอาจมีเธรดสีเขียวด้านบนเธรดระบบ (แต่ไลบรารีเธรดสีเขียวนั้นยากต่อการปรับใช้และดีบัก) ดูgoroutines ที่ใช้ในGoเพื่อเป็นตัวอย่างแฟนซี ดูยังsetcontext (3)

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

ดูเพิ่มเติม - สำหรับ Linux- ทางแยก (2) , โคลน (2) , mmap (2) , madvise (2) , posix_fadvise (2) , mlock (2) , execve (2) , หนังสือรับรอง (7) , pthreads (7) , futex (7) , ความสามารถในการ (7)

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