OpenBSD แสดงความเร็วในการสร้าง Socket เหนือกว่า Linux ถึง 10 เท่า เนื่องจากปัญหาคอขวดของ RCU Synchronization

ทีมชุมชน BigGo
OpenBSD แสดงความเร็วในการสร้าง Socket เหนือกว่า Linux ถึง 10 เท่า เนื่องจากปัญหาคอขวดของ RCU Synchronization

การทดสอบประสิทธิภาพล่าสุดเผยให้เห็นช่องว่างด้านประสิทธิภาพที่น่าประหลาดใจระหว่าง OpenBSD และ Linux เมื่อสร้างเครือข่าย socket ในแอปพลิเคชันแบบ multi-threaded การทดสอบซึ่งเกี่ยวข้องกับสอง thread ที่แต่ละตัวสร้าง TCP socket จำนวน 256 ตัว แสดงให้เห็นว่า OpenBSD สามารถทำงานให้เสร็จสิ้นในเวลาประมาณ 2-6 มิลลิวินาที ในขณะที่ Linux ใช้เวลา 17-26 มิลลิวินาที ซึ่งเป็นความแตกต่างของประสิทธิภาพที่เร็วกว่าถึง 10 เท่า

ผลการเปรียบเทียบประสิทธิภาพ:

  • ประสิทธิภาพของ Linux : 17-26 มิลลิวินาที (0.017770s - 0.026309s)
  • ประสิทธิภาพของ OpenBSD : 2-6 มิลลิวินาที (0.002326s - 0.006096s)
  • ความแตกต่างของความเร็ว: เร็วกว่าใน OpenBSD ถึง 10 เท่า
  • สถานการณ์การทดสอบ: 2 เธรดที่สร้าง TCP socket อย่างละ 256 ตัว (รวม 512 file descriptor)

สาเหตุหลัก: การขยาย File Descriptor Table

ความแตกต่างด้านประสิทธิภาพเกิดจากวิธีที่แต่ละระบบปฏิบัติการจัดการการขยาย file descriptor table เมื่อมี thread หลายตัวเข้ามาเกี่ยวข้อง ใน Linux file descriptor table เริ่มต้นด้วย 256 slot โดยค่าเริ่มต้น เมื่อสอง thread สร้าง socket อย่างละ 256 ตัว (รวม 512 file descriptor) ระบบจะต้องขยาย table นี้ในระหว่างกระบวนการ

ในระหว่างการขยายนี้ kernel ของ Linux จะตรวจสอบว่า thread หลายตัวใช้ file descriptor table เดียวกันหรือไม่ เมื่อตรวจพบการเข้าถึงร่วมกัน (ตามที่แสดงโดย reference count ที่มากกว่า 1) ระบบจะเรียกฟังก์ชันที่เรียกว่า synchronize_rcu() เพื่อให้มั่นใจในความปลอดภัยของ thread ฟังก์ชันนี้รอให้ RCU grace period เต็มรอบเสร็จสิ้น ซึ่งอาจใช้เวลาหลายมิลลิวินาทีและสร้างคอขวดด้านประสิทธิภาพที่สังเกตได้

RCU (Read-Copy-Update) เป็นวิธีการซิงโครไนเซชันที่อนุญาตให้ thread หลายตัวอ่านข้อมูลได้อย่างปลอดภัยในขณะที่ thread หนึ่งอัปเดตข้อมูล แต่ต้องมีช่วงเวลารอเพื่อให้มั่นใจว่าผู้อ่านทั้งหมดได้อ่านเสร็จแล้ว

รายละเอียดทางเทคนิค:

  • ขนาดตาราง FD เริ่มต้นของ Linux : 256 ช่อง
  • ตัวกระตุ้นคอขวด: การขยายตาราง file descriptor เมื่อ reference count > 1
  • วิธีการ Synchronization ของ Linux : RCU (Read-Copy-Update) พร้อมการเรียกใช้ synchronize_rcu()
  • วิธีการ Synchronization ของ OpenBSD : read-write locks แบบดั้งเดิม
  • วิธีแก้ไขชั่วคราว: ขยายตาราง FD ล่วงหน้าโดยใช้ dup2(0, 666) ก่อนสร้าง thread

แนวทางที่เรียบง่ายของ OpenBSD

OpenBSD ใช้แนวทางที่แตกต่างออกไปโดยสิ้นเชิง แทนที่จะใช้ RCU synchronization ระบบนี้อาศัย read-write lock แบบดั้งเดิมเมื่อแก้ไข file descriptor table วิธีการนี้หลีกเลี่ยงความล่าช้าจากการซิงโครไนเซชันที่ยาวนานซึ่งเป็นปัญหาใน Linux ในสถานการณ์เฉพาะนี้ ส่งผลให้เวลาในการสร้าง socket เร็วขึ้นมาก

การทดสอบยังแสดงให้เห็นวิธีแก้ไขปัญหาสำหรับ Linux ด้วย โดยการขยาย file descriptor table ล่วงหน้าโดยใช้ dup2(0, 666) ก่อนสร้าง thread เพิ่มเติม ปัญหาด้านประสิทธิภาพจะหายไปเนื่องจาก table ไม่จำเป็นต้องขยายในระหว่างการสร้าง socket

ข้อมูลเชิงลึกจากชุมชนและผลกระทบในวงกว้าง

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

หัวข้อที่ดีกว่า: โปรแกรมทดสอบที่ผิดปกติซึ่งออกแบบมาสำหรับ Linux ไม่ทำให้เกิดพฤติกรรมผิดปกติใน OpenBSD

การทดสอบนี้เน้นย้ำให้เห็นว่าการตัดสินใจออกแบบ kernel ที่แตกต่างกันสามารถสร้างลักษณะประสิทธิภาพที่ไม่คาดคิดได้ ในขณะที่แนวทาง RCU ของ Linux ให้ข้อได้เปรียบในหลายสถานการณ์ แต่ก็สามารถสร้างคอขวดในกรณีพิเศษเฉพาะ เช่น การจัดสรร file descriptor อย่างรวดเร็วในโปรแกรม multi-threaded

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

อ้างอิง: Is OpenBSD 10x faster than Linux?