ฉันจะสนใจในด้านต่างๆเช่น:
- ขอบเขต / คุณสมบัติ
- ประสิทธิภาพ
- วุฒิภาวะ
ฉันจะสนใจในด้านต่างๆเช่น:
คำตอบ:
Boost.Asioเป็นไลบรารี C ++ ที่เริ่มต้นด้วยการให้ความสำคัญกับระบบเครือข่าย แต่ความสามารถของ I / O แบบอะซิงโครนัสได้ถูกขยายไปยังทรัพยากรอื่น ๆ นอกจากนี้ด้วย Boost.Asio ซึ่งเป็นส่วนหนึ่งของห้องสมุด Boost ขอบเขตของมันจะแคบลงเล็กน้อยเพื่อป้องกันการทำซ้ำกับห้องสมุด Boost อื่น ๆ ตัวอย่างเช่น Boost.Asio จะไม่ให้เธรดนามธรรมเนื่องจากBoost.Threadมีหนึ่งเธรดอยู่แล้ว
บนมืออื่น ๆ , libuvเป็นห้องสมุด C ที่ออกแบบมาเพื่อเป็นแพลตฟอร์มชั้นสำหรับNode.js มันให้นามธรรมสำหรับIOCPบน Windows, kqueueบน macOS และepollบน Linux นอกจากนี้ดูเหมือนว่าขอบเขตจะเพิ่มขึ้นเล็กน้อยเพื่อรวม abstractions และฟังก์ชันเช่นเธรดเธรดพูลและการสื่อสารระหว่างเธรด
ที่แกนกลางของพวกเขาแต่ละห้องสมุดมีวงเหตุการณ์และความสามารถในการ I / O ไม่ตรงกัน มีการซ้อนทับกันสำหรับคุณสมบัติพื้นฐานบางอย่างเช่นตัวจับเวลาซ็อกเก็ตและการทำงานแบบอะซิงโครนัส libuv มีขอบเขตที่กว้างขึ้นและมีฟังก์ชันเพิ่มเติมเช่นเธรดและการซิงโครไนซ์, การทำงานของระบบไฟล์แบบซิงโครนัสและแบบอะซิงโครนัส, การจัดการกระบวนการ ฯลฯ ในทางตรงกันข้ามพื้นผิวโฟกัสเครือข่ายดั้งเดิม ความสามารถเช่น ICMP, SSL, การบล็อกแบบซิงโครนัสและการไม่บล็อกและการทำงานระดับสูงสำหรับงานทั่วไปรวมถึงการอ่านจากสตรีมจนกว่าจะได้รับการขึ้นบรรทัดใหม่
นี่คือการเปรียบเทียบแบบย่อโดยเปรียบเทียบกับคุณสมบัติที่สำคัญบางอย่าง เนื่องจากนักพัฒนาซอฟต์แวร์ที่ใช้ Boost.Asio มักจะมีห้องสมุด Boost อื่น ๆ ฉันจึงเลือกที่จะพิจารณาห้องสมุด Boost เพิ่มเติมหากพวกเขามีให้โดยตรงหรือใช้งานเล็กน้อย
เพิ่ม libuv ห่วงเหตุการณ์: ใช่ Asio Threadpool: ใช่ Asio + กระทู้ Threading: เธรด: ใช่เธรด การซิงโครไนซ์: ใช่เธรด การทำงานของระบบไฟล์: ซิงโครนัส: ใช่ FileSystem อะซิงโครนัส: ใช่ Asio + ระบบไฟล์ ตัวจับเวลา: ใช่ Asio Scatter / Gather I / O [1] : ไม่มี Asio เครือข่าย: ICMP: ไม่มี Asio การแก้ไข DNS: Async เฉพาะ Asio SSL: ไม่มี Asio TCP: Async-only Asio UDP: async-only Asio สัญญาณ: การจัดการ: ใช่ Asio กำลังส่ง: ใช่ไม่ใช่ IPC: ซ็อกเก็ตโดเมน UNIX: ใช่ Asio Windows Named Pipe: ใช่ Asio การจัดการกระบวนการ: กำลังถอด: ใช่กระบวนการ ท่อ I / O: ใช่กระบวนการ วางไข่: ใช่กระบวนการ คำค้นหาระบบ: CPU: ใช่ไม่ อินเทอร์เฟซเครือข่าย: ใช่ไม่ใช่ พอร์ตอนุกรม: ไม่ใช่ TTY: ใช่ไม่ การโหลดไลบรารีที่แชร์: ใช่ส่วนขยาย[2]
1. กระจาย / รวบรวม I / O
2. Boost.Extensionไม่เคยถูกส่งไปตรวจสอบเพื่อเพิ่ม ดังที่ระบุไว้ที่นี่ผู้เขียนเห็นว่าเสร็จสมบูรณ์
ในขณะที่ทั้ง libuv และ Boost.Asio จะมีลูปของเหตุการณ์
uv_default_loop()
) แทนที่จะสร้างลูปใหม่ ( uv_loop_new()
) เนื่องจากส่วนประกอบอื่นอาจใช้ลูปเริ่มต้นio_service
เป็นลูปของตนเองที่อนุญาตให้มีหลายเธรดให้ทำงาน เพื่อสนับสนุนการดำเนินการนี้ Boost.Asio ล็อคภายในที่ค่าใช้จ่ายของบางประสิทธิภาพ ประวัติการแก้ไขของ Boost.Asio ระบุว่ามีการปรับปรุงประสิทธิภาพหลายอย่างเพื่อลดการล็อกuv_queue_work
ผ่าน ขนาด threadpool UV_THREADPOOL_SIZE
กำหนดค่าผ่านทางตัวแปรสภาพแวดล้อม งานจะถูกดำเนินการนอกห่วงเหตุการณ์และภายในเธรดพูล เมื่องานเสร็จสมบูรณ์ตัวจัดการความสมบูรณ์จะเข้าคิวเพื่อให้ทำงานภายในลูปเหตุการณ์io_service
สามารถทำหน้าที่เป็นหนึ่งได้อย่างง่ายดายเนื่องจากio_service
อนุญาตให้เธรดจำนวนมากสามารถเรียกrun
ใช้ได้ สถานที่นี้ในความรับผิดชอบของการจัดการด้ายและพฤติกรรมให้กับผู้ใช้ในขณะที่สามารถเห็นได้ในนี้ตัวอย่างเช่นEAGAIN
EWOULDBLOCK
kill
และการจัดการสัญญาณด้วยuv_signal_t
ชนิดและuv_signal_*
การทำงานของมันkill
แต่signal_set
ให้การจัดการสัญญาณuv_pipe_t
ชนิดเดียวlocal::stream_protocol::socket
หรือlocal::datagram_protocol::socket
, และwindows::stream_handle
.แม้ว่า API จะแตกต่างกันไปตามภาษาเพียงอย่างเดียว แต่นี่คือความแตกต่างที่สำคัญบางประการ:
ภายใน Boost.Asio มีการแมปแบบหนึ่งต่อหนึ่งระหว่างการดำเนินการกับตัวจัดการ ตัวอย่างเช่นasync_write
การดำเนินการแต่ละรายการจะเรียกใช้WriteHandlerหนึ่งครั้ง สิ่งนี้เป็นจริงสำหรับการดำเนินการ libuv และตัวจัดการจำนวนมาก อย่างไรก็ตาม libuv uv_async_send
สนับสนุนการทำแผนที่หลายต่อหนึ่ง การuv_async_send
โทรหลายครั้งอาจส่งผลให้uv_async_cbถูกเรียกหนึ่งครั้ง
เมื่อต้องทำงานกับงานเช่นการอ่านจากสตรีม / UDP การจัดการสัญญาณหรือการรอตัวจับเวลาเครือข่ายการโทรแบบอะซิงโครนัสของ Boost.Asio จะมีความชัดเจนมากขึ้น ด้วย libuv ผู้เฝ้าดูถูกสร้างขึ้นเพื่อกำหนดความสนใจในเหตุการณ์เฉพาะ ลูปจะเริ่มขึ้นสำหรับผู้เฝ้าดูโดยที่มีการโทรกลับ เมื่อได้รับเหตุการณ์ที่น่าสนใจการเรียกกลับจะถูกเรียกใช้ ในทางกลับกัน Boost.Asio ต้องการการดำเนินการที่จะออกทุกครั้งที่แอปพลิเคชันสนใจในการจัดการเหตุการณ์
เพื่อช่วยแสดงให้เห็นถึงความแตกต่างนี้นี่คือลูปการอ่านแบบอะซิงโครนัสกับ Boost.Asio ซึ่งasync_receive
จะมีการโทรออกหลายครั้ง:
void start()
{
socket.async_receive( buffer, handle_read ); ----.
} |
.----------------------------------------------'
| .---------------------------------------.
V V |
void handle_read( ... ) |
{ |
std::cout << "got data" << std::endl; |
socket.async_receive( buffer, handle_read ); --'
}
และนี่คือตัวอย่างเดียวกันกับ libuv ซึ่งhandle_read
จะถูกเรียกใช้ในแต่ละครั้งที่ผู้สังเกตการณ์สังเกตว่าซ็อกเก็ตมีข้อมูล:
uv_read_start( socket, alloc_buffer, handle_read ); --.
|
.-------------------------------------------------'
|
V
void handle_read( ... )
{
fprintf( stdout, "got data\n" );
}
ผลที่ตามมาของสายอะซิงโครนัสโซ่ใน Boost.Asio และผู้ดูใน libuv การจัดสรรหน่วยความจำมักจะเกิดขึ้นในเวลาที่ต่างกัน ด้วย watchers, libuv จะยกเลิกการจัดสรรจนกว่าจะได้รับเหตุการณ์ที่ต้องใช้หน่วยความจำในการจัดการ การจัดสรรจะกระทำผ่านการติดต่อกลับของผู้ใช้เรียกใช้ภายในเป็น libuv และยกเลิกความรับผิดชอบในการจัดสรรคืนของแอปพลิเคชัน บนมืออื่น ๆ จำนวนมากของการดำเนินงาน Boost.Asio จำเป็นต้องให้หน่วยความจำได้รับการจัดสรรก่อนที่จะออกดำเนินการไม่ตรงกันเช่นกรณีของสำหรับbuffer
async_read
Boost.Asio มีให้null_buffers
ซึ่งสามารถใช้ในการฟังเหตุการณ์อนุญาตให้แอปพลิเคชันเลื่อนการจัดสรรหน่วยความจำจนกว่าจำเป็นต้องใช้หน่วยความจำแม้ว่าจะไม่สนับสนุนก็ตาม
ความแตกต่างการจัดสรรหน่วยความจำนี้ยังแสดงตัวเองภายในbind->listen->accept
วง ด้วย libuv uv_listen
สร้างเหตุการณ์วนรอบที่จะเรียกการเรียกกลับของผู้ใช้เมื่อการเชื่อมต่อพร้อมที่จะยอมรับ สิ่งนี้อนุญาตให้แอปพลิเคชันเลื่อนการจัดสรรของไคลเอ็นต์จนกว่าจะพยายามเชื่อมต่อ บนมืออื่น ๆ , Boost.Asio ก็เพียงเปลี่ยนสถานะของlisten
ฟังสำหรับเหตุการณ์การเชื่อมต่อและต้องเพียร์จะได้รับการจัดสรรก่อนที่จะถูกเรียกacceptor
async_accept
น่าเสียดายที่ฉันไม่มีตัวเลขมาตรฐานที่ชัดเจนเพื่อเปรียบเทียบ libuv และ Boost.Asio อย่างไรก็ตามฉันได้สังเกตประสิทธิภาพที่คล้ายกันโดยใช้ห้องสมุดในแอปพลิเคชันแบบเรียลไทม์และแบบเรียลไทม์ หากต้องการจำนวนมากการทดสอบเกณฑ์มาตรฐานของ libuv อาจใช้เป็นจุดเริ่มต้น
นอกจากนี้ในขณะที่การทำโปรไฟล์ควรทำเพื่อระบุปัญหาคอขวดจริงให้ระวังการจัดสรรหน่วยความจำ สำหรับ libuv กลยุทธ์การจัดสรรหน่วยความจำจะ จำกัด อยู่ที่การเรียกกลับตัวจัดสรร ในทางกลับกัน API ของ Boost.Asio ไม่อนุญาตให้มีการเรียกกลับตัวจัดสรรและผลักกลยุทธ์การจัดสรรให้กับแอปพลิเคชันแทน อย่างไรก็ตามตัวจัดการ / การโทรกลับใน Boost.Asio อาจคัดลอกจัดสรรและยกเลิกการจัดสรรได้ Boost.Asio อนุญาตให้แอปพลิเคชันจัดหาฟังก์ชันการจัดสรรหน่วยความจำแบบกำหนดเองเพื่อใช้กลยุทธ์การจัดสรรหน่วยความจำสำหรับตัวจัดการ
การพัฒนาของ Asio ย้อนกลับไปอย่างน้อย OCT-2004 และได้รับการยอมรับใน Boost 1.35 ในวันที่ 22 มีนาคม 2549 หลังจากผ่านการตรวจสอบแบบเพื่อน 20 วัน นอกจากนี้ยังทำหน้าที่เป็นผู้ดำเนินการอ้างอิงและ API สำหรับห้องสมุดเครือข่ายข้อเสนอสำหรับ TR2 Boost.Asio มีเอกสารจำนวนพอใช้ถึงแม้ว่าประโยชน์จะแตกต่างกันไปตามผู้ใช้
API ยังให้ความรู้สึกที่สอดคล้องกัน นอกจากนี้การดำเนินการแบบอะซิงโครนัสนั้นชัดเจนในชื่อของการดำเนินการ ตัวอย่างเช่นaccept
การบล็อกasync_accept
แบบซิงโครนัสและแบบอะซิงโครนัส API มีฟังก์ชันฟรีสำหรับงาน I / O ทั่วไปเช่นการอ่านจากสตรีมจนกระทั่ง a \r\n
ถูกอ่าน เรียนยังได้รับการกำหนดให้ซ่อนรายละเอียดเฉพาะบางเครือข่ายเช่นip::address_v4::any()
ตัวแทนอยู่ "การเชื่อมต่อทั้งหมด" 0.0.0.0
ของ
สุดท้าย Boost 1.47+ ให้การติดตามตัวจัดการซึ่งสามารถพิสูจน์ได้ว่ามีประโยชน์เมื่อทำการดีบั๊กเช่นเดียวกับการสนับสนุน C ++ 11
ขึ้นอยู่กับกราฟ GitHub ของพวกเขาวันพัฒนา Node.js กลับไปอย่างน้อยกุมภาพันธ์ 2009และวันที่ libuv ของการพัฒนามี.ค. 2011 uvbookเป็นสถานที่ที่ดีสำหรับการแนะนำ libuv เอกสาร API คือที่นี่
โดยรวมแล้ว API นั้นค่อนข้างสอดคล้องและใช้งานง่าย ความผิดปกติอย่างหนึ่งที่อาจทำให้เกิดความสับสนก็คือการuv_tcp_listen
สร้างลูปสำหรับเฝ้าดู นี้แตกต่างจากนักดูอื่น ๆ ที่โดยทั่วไปมีuv_*_start
และuv_*_stop
คู่ของฟังก์ชั่นในการควบคุมชีวิตของวงที่เฝ้าดู นอกจากนี้การuv_fs_*
ดำเนินการบางอย่างมีจำนวนอาร์กิวเมนต์ที่เหมาะสม (มากถึง 7) ด้วยพฤติกรรมแบบซิงโครนัสและแบบอะซิงโครนัสที่พิจารณาจากการโทรกลับ (อาร์กิวเมนต์สุดท้าย) การมองเห็นพฤติกรรมแบบซิงโครนัสสามารถลดลงได้
ในที่สุดการดูประวัติ libuv ที่กระทำอย่างรวดเร็วแสดงให้เห็นว่าผู้พัฒนามีความกระตือรือร้นมาก
uv_async_send
โทรหลายสายและจัดการได้ทั้งหมดด้วยการโทรกลับครั้งเดียว มันเป็นเอกสารที่นี่ ขอบคุณทุกคนด้วย
ตกลง. ฉันมีประสบการณ์ในการใช้ห้องสมุดทั้งสองและสามารถชี้แจงบางอย่าง
ก่อนอื่นจากมุมมองแนวคิดห้องสมุดเหล่านี้มีความแตกต่างในการออกแบบ พวกเขามีสถาปัตยกรรมที่แตกต่างกันเพราะมีขนาดแตกต่างกัน Boost.Asio เป็นห้องสมุดเครือข่ายขนาดใหญ่ที่มีวัตถุประสงค์เพื่อใช้กับโปรโตคอล TCP / UDP / ICMP, POSIX, SSL และอื่น ๆ Libuv เป็นเพียงเลเยอร์สำหรับข้ามนามธรรมของIOCPสำหรับ Node.js ซึ่งส่วนใหญ่ ดังนั้น libuv จึงทำหน้าที่เป็นชุดย่อยของ Boost.Asio (คุณสมบัติทั่วไปเท่านั้นเธรด TCP / UDP Sockets, ตัวนับ) ในกรณีนี้เราสามารถเปรียบเทียบไลบรารีเหล่านี้โดยใช้เกณฑ์เพียงไม่กี่ข้อ:
การรวมเข้ากับคุณสมบัติ C ++ ใหม่: Asio ดีกว่า (Asio 1.51 ใช้แบบจำลองอะซิงโครนัส C ++ 11 อย่างกว้างขวาง, ย้ายซีแมนทิกส์, เทมเพลตแบบแปรผัน). ในแง่ของการกำหนด, Asio เป็นโครงการที่เสถียรและเป็นผู้ใหญ่มากขึ้น คำอธิบายส่วนหัว) ข้อมูลจำนวนมากทั่วอินเทอร์เน็ต (วิดีโอพูดคุยบล็อก: http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg) = 1 , ฯลฯ ) และแม้กระทั่งหนังสือ (ไม่ใช่สำหรับมืออาชีพ แต่ก็ยัง: http://en.highscore.de/cpp/boost/index.html ) Libuv มีหนังสือออนไลน์เพียงเล่มเดียว (แต่ก็ยังดี) http://nikhilm.github.com/uvbook/index.htmlและวิดีโอพูดคุยหลายเรื่องดังนั้นจึงเป็นการยากที่จะรู้ความลับทั้งหมด (ห้องสมุดนี้มีพวกเขาจำนวนมาก) สำหรับการสนทนาที่เฉพาะเจาะจงมากขึ้นของฟังก์ชั่นดูความคิดเห็นของฉันด้านล่าง
โดยสรุปฉันควรบอกว่าทุกอย่างขึ้นอยู่กับวัตถุประสงค์โครงการและสิ่งที่คุณตั้งใจทำ
สิ่งที่แตกต่างอย่างหนึ่งคือผู้แต่ง Asio (Christopher Kohlhoff) กำลังเตรียมห้องสมุดของเขาไว้ในห้องสมุดมาตรฐาน C ++ ดูhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2175 .pdfและhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4370.html
การเพิ่มสถานะการพกพา: เมื่อโพสต์คำตอบนี้และเป็นไปตามความพยายามของฉัน: