netpoll
Netpoll ของ Go เป็นกลไก I/O multiplexing หลักที่ดำเนินการโดย Go runtime ทำให้ Go สามารถใช้บริการเครือข่ายประสิทธิภาพสูงด้วยโมเดลการเขียนโปรแกรมแบบ synchronous ที่เรียบง่าย (หนึ่ง Goroutine ต่อหนึ่งการเชื่อมต่อ) โดยพื้นฐานแล้วเป็นการรวมการเรียกระบบ I/O multiplexing ระดับล่างของระบบปฏิบัติการ (เช่น epoll ของ Linux) เข้ากับตัวจัดตาราง Goroutine ของ Go อย่างลึกซึ้ง
การเปรียบเทียบระหว่าง Netpoll กับ GoNet ดั้งเดิม
จำนวน Goroutine
- Go Net: หนึ่ง Goroutine มีหนึ่งการเชื่อมต่อ
- NetPoll: หนึ่ง Goroutine มีหลายการเชื่อมต่อ
แรงกดดันในการสลับบริบท goroutine
- Go Net: เมื่อมีความพร้อมใช้งานสูง แรงกดดันในการสลับสูง เนื่องจาก GoNet มีการเชื่อมต่อหนึ่งตัวต่อหนึ่ง goroutine เมื่อจำนวน goroutine มากจะสลับบ่อย
- NetPoll: เมื่อมีความพร้อมใช้งานสูง แรงกดดันในการสลับน้อย เนื่องจาก NetPoll หลายการเชื่อมต่อใช้ goroutine เดียวกัน จำนวนการสลับน้อย
การใช้หน่วยความจำ
- Go Net: การใช้หน่วยความจำสัมพันธ์เชิงบวกกับจำนวนการเชื่อมต่อ เมื่อมีความพร้อมใช้งานสูงอาจทำให้เกิดแรงกดดันหน่วยความจำเนื่องจากจำนวน Goroutine ระเบิด
- NetPoll: จัดสรรบัฟเฟอร์ล่วงหน้า สร้างพูลบัฟเฟอร์
วิธีการทริกเกอร์
- Go Net: ใช้ Edge Triggered (ET) อ่านข้อมูลจนหมดในครั้งเดียว การดำเนินการง่าย
- NetPoll: ใช้ Level Triggered (LT) ไม่จำเป็นต้องจัดสรรหน่วยความจำขนาดใหญ่ล่วงหน้าสำหรับบัฟเฟอร์ข้อมูล
รองรับการแชร์พูลบัฟเฟอร์ระหว่างเคอร์เนลและเลเยอร์ผู้ใช้ ลดการคัดลอกข้อมูลหนึ่งครั้ง
- Go Net: ไม่รองรับ
- NetPoll: รองรับ จัดการพูล Buffer โดยตรงให้เลเยอร์ผู้ใช้ ลดการคัดลอกข้อมูลหนึ่งครั้ง
สถานการณ์ที่เหมาะสม
- Go Net: สถานการณ์ง่ายที่มีความพร้อมใช้งานต่ำ
- NetPoll: สถานการณ์ที่มีความพร้อมใช้งานสูงและความหน่วงต่ำ
แนวคิดการออกแบบ netpoll
สถาปัตยกรรมพื้นฐาน ไลบรารีเครือข่ายดั้งเดิมพัฒนาบนพื้นฐานของโหมด epoll lt สถาปัตยกรรมพื้นฐานแสดงดังภาพด้านล่าง:

การใช้ goroutine มีพูลอ็อบเจ็กต์ poll แต่ละอ็อบเจ็กต์ poll มี epoll หนึ่งตัวและสอดคล้องกับ goroutine หนึ่งตัวจำนวน goroutine สัมพันธ์กับจำนวนอ็อบเจ็กต์ poll แต่ละอ็อบเจ็กต์ poll สามารถตรวจสอบไฟล์ descriptor fd ได้หลายตัว
ตรรกะการอ่าน/เขียน IO
- แต่ละอ็อบเจ็กต์ poll เปิด goroutine เพื่อวนลูปตรวจสอบเหตุการณ์ที่อ่านได้/เขียนได้บน epoll ปัจจุบัน
- แต่ละ epoll จะเชื่อมโยงกับ fd หลายตัว แต่ละ fd เชื่อมโยงกับ Buffer หนึ่งตัว
- เมื่อตรวจสอบเหตุการณ์ที่อ่านได้จาก fd จะอ่านข้อมูลลงใน Buffer
- วนลูปประมวลผลข้อมูลใน Buffer ต่อไป เมื่อพบว่าข้อมูลอ่านเสร็จแล้ว จะแจ้งให้พูล goroutine ของตรรกะการประมวลผลด้านหลัง GoPoll ดำเนินการ
- การโต้ตอบการเรียก系统与เคอร์เนลถูกควบคุมโดย netpoll อย่างสมบูรณ์ การอ่าน/เขียน Conn ของเลเยอร์ผู้ใช้เป็นเพียงการดำเนินการกับ Buffer ที่ใช้ร่วมกันเท่านั้น
ข้อดีและข้อเสีย
ข้อดี: รองรับความสามารถความพร้อมใช้งานสูงที่แข็งแกร่งกว่า
- (1) การวนลูปประมวลผลข้อมูลใน Buffer ไม่มีสถานการณ์ที่ข้อมูลไม่ได้รับการประมวลผล
- (2) หนึ่ง goroutine สอดคล้องกับหลายการเชื่อมต่อ แม้ว่าการเชื่อมต่อมีจำนวนมาก ค่าใช้จ่ายในการจัดสรรทรัพยากรและการสลับก็ไม่มาก
- (3) รองรับผู้ใช้และเคอร์เนลแชร์ buff ลดการดำเนินการคัดลอกข้อมูลหนึ่งครั้ง เพิ่มประสิทธิภาพ
ข้อเสีย: ต้องใช้หน่วยความจำมากขึ้น
