การเตรียมพร้อมกับการใช้หน่วยความจำ Async IO เสร็จสมบูรณ์หรือไม่


12

ฉันกำลังดูการสนทนานี้เกี่ยวกับการใช้ Async IO ใน Rust และ Carl กล่าวถึงแบบจำลองที่มีศักยภาพสองแบบ ความพร้อมและความสำเร็จ

โมเดลความพร้อม:

  • คุณบอกเคอร์เนลที่คุณต้องการอ่านจากซ็อกเก็ต
  • ทำสิ่งอื่นเพื่อสักครู่ ...
  • เคอร์เนลจะบอกคุณเมื่อซ็อกเก็ตพร้อม
  • คุณอ่าน (เติมบัฟเฟอร์)
  • ทำสิ่งที่คุณต้องการ
  • ฟรีบัฟเฟอร์ (เกิดขึ้นโดยอัตโนมัติด้วยสนิม)

เสร็จสิ้นรูปแบบ:

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

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

ตอนนี้สมมติฐานของฉัน:

ภายใต้ประทุน (ในพื้นที่เคอร์เนล) เมื่อซ็อกเก็ตถูกกล่าวว่าเป็น "พร้อม" ข้อมูลมีอยู่แล้ว มันเข้ามาในซ็อกเก็ตผ่านเครือข่าย (หรือจากที่ใดก็ได้) และระบบปฏิบัติการนั้นก็เก็บข้อมูลไว้

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

นี่คือโมเดลการเตรียมพร้อมในการแก้ไขของฉัน:

  • คุณบอกเคอร์เนลที่คุณต้องการอ่านจากซ็อกเก็ต
  • ทำสิ่งอื่นเพื่อสักครู่ ...
  • การแก้ไข: ข้อมูลเข้าสู่ระบบปฏิบัติการ (บางที่ในหน่วยความจำเคอร์เนล)
  • เคอร์เนลบอกคุณซ็อกเก็ตพร้อม
  • คุณอ่าน (กรอกบัฟเฟอร์อื่นแยกต่างหากจากบัฟเฟอร์เคอร์เนลในต่างประเทศ (หรือคุณได้รับตัวชี้ไป?))
  • ทำสิ่งที่คุณต้องการ
  • ฟรีบัฟเฟอร์ (เกิดขึ้นโดยอัตโนมัติด้วยสนิม)

/ สมมติฐานของฉัน

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


ฉันมาถึงที่นี่จากการพูดคุยของ YouTube ด้วย สำหรับทุกคนที่เรียนรู้เกี่ยวกับวิธีการ async IO หรือวิธีการใช้ลูปเหตุการณ์ทีม Rust มีเพลย์ลิสต์ของ "Aysnc Interviews" ที่นี่สัมภาษณ์คนที่มีความรู้มากจากชุมชน
cacoder

คำตอบ:


5

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

ในรุ่นที่สมบูรณ์ปริมาณการใช้หน่วยความจำจะแปรผันตามปริมาณการเรียกใช้ซ็อกเก็ตที่โดดเด่น

หากมีซ็อกเก็ตจำนวนมากที่ไม่มีการใช้งานเป็นส่วนใหญ่โมเดลการเตรียมพร้อมจะใช้หน่วยความจำน้อยกว่า

มีการแก้ไขที่ง่ายสำหรับตัวแบบที่สมบูรณ์: เริ่มต้นการอ่าน 1 ไบต์ สิ่งนี้ใช้เพียงบัฟเฟอร์เล็ก ๆ เมื่อการอ่านเสร็จสิ้นให้อ่านอีกฉบับ (อาจจะซิงโครนัส) อ่านเพื่อรับข้อมูลส่วนที่เหลือ

ในบางภาษาตัวแบบเสร็จสมบูรณ์นั้นใช้ง่ายมาก ฉันถือว่ามันเป็นตัวเลือกเริ่มต้นที่ดี


1

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

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

ข้อดีคือในขณะที่รุ่นที่สมบูรณ์แล้วจะใช้หน่วยความจำมากกว่า แต่ก็สามารถ (บางครั้ง) ทำการคัดลอกได้น้อยลงเพราะการรักษาบัฟเฟอร์รอบ ๆ หมายความว่าฮาร์ดแวร์สามารถ DMA โดยตรงหรือเข้าออกได้ ฉันยังสงสัย (แต่ไม่ค่อยแน่ใจ) ว่ารุ่นจำลองมีแนวโน้มที่จะดำเนินการคัดลอกจริง (เมื่อมีอยู่) ในเธรดอื่นอย่างน้อยสำหรับ IOCP ของ Windows ในขณะที่รุ่นความพร้อมใช้งานเป็นส่วนหนึ่งของการไม่ปิดกั้นread()หรือwrite()โทร.

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