Đối với số lượng rất nhỏ ổ cắm (thay đổi tùy thuộc vào phần cứng của bạn, tất nhiên, nhưng chúng ta đang nói về thứ gì đó trên thứ tự từ 10 trở xuống), chọn có thể đánh bại epoll khi sử dụng bộ nhớ và tốc độ thời gian chạy. Tất nhiên, đối với số lượng nhỏ các ổ cắm, cả hai cơ chế quá nhanh đến nỗi bạn không thực sự quan tâm đến sự khác biệt này trong phần lớn các trường hợp.
Một làm rõ. Cả hai lựa chọn và epoll quy mô tuyến tính. Một sự khác biệt lớn, mặc dù, là các API không gian người dùng phải đối mặt với sự phức tạp dựa trên những thứ khác nhau. Chi phí của cuộc gọi select
diễn ra với giá trị của bộ mô tả tệp được đánh số cao nhất mà bạn vượt qua. Nếu bạn chọn một fd, 100, thì nó đắt hơn gấp đôi so với lựa chọn trên một fd duy nhất, 50. Thêm nhiều fds dưới mức cao nhất không hoàn toàn miễn phí, vì vậy nó phức tạp hơn một chút so với thực tế, nhưng là một phép tính gần đúng đầu tiên cho hầu hết các triển khai.
Chi phí của epoll gần với số lượng mô tả tệp thực sự có sự kiện trên chúng. Nếu bạn đang giám sát 200 bộ mô tả tệp, nhưng chỉ 100 trong số chúng có sự kiện trên chúng, thì bạn (rất gần) chỉ trả tiền cho 100 bộ mô tả tệp đang hoạt động đó. Đây là nơi epoll có xu hướng cung cấp một trong những lợi thế chính của nó trên lựa chọn. Nếu bạn có một nghìn khách hàng chủ yếu là nhàn rỗi, thì khi bạn sử dụng lựa chọn bạn vẫn trả tiền cho tất cả một nghìn người trong số họ. Tuy nhiên, với epoll, nó giống như bạn chỉ có một vài - bạn chỉ trả tiền cho những người đang hoạt động tại bất kỳ thời điểm nào.
Tất cả điều này có nghĩa là epoll sẽ dẫn đến sử dụng ít CPU hơn cho hầu hết khối lượng công việc. Theo như sử dụng bộ nhớ đi, đó là một chút của một quăng lên. select
không quản lý để đại diện cho tất cả các thông tin cần thiết theo một cách rất nhỏ gọn (một bit cho mỗi bộ mô tả tập tin). Và giới hạn FD_SETSIZE (thường là 1024) về số lượng mô tả tệp bạn có thể sử dụng với select
có nghĩa là bạn sẽ không bao giờ chi tiêu nhiều hơn 128 byte cho mỗi bộ ba fd mà bạn có thể sử dụng với select
(đọc, viết, ngoại lệ). So với 384 byte tối đa, epoll là loại lợn. Mỗi bộ mô tả tập tin được biểu diễn bằng một cấu trúc nhiều byte. Tuy nhiên, về mặt tuyệt đối, nó vẫn sẽ không sử dụng nhiều bộ nhớ. Bạn có thể đại diện cho một số lượng lớn các bộ mô tả tập tin trong vài chục kilobyte (khoảng 20k cho mỗi 1000 bộ mô tả tập tin, tôi nghĩ). Và bạn cũng có thể ném vào thực tế là bạn phải chi tiêu tất cả 384 byte đó với select
nếu bạn chỉ muốn theo dõi một bộ mô tả tệp nhưng giá trị của nó xảy ra là 1024, các ảnh có epoll bạn chỉ tốn 20 byte. Tuy nhiên, tất cả những con số này là khá nhỏ, vì vậy nó không tạo ra nhiều khác biệt.
Và cũng có lợi ích khác của epoll, có lẽ bạn đã biết, rằng nó không giới hạn ở FD_SETSIZE mô tả tệp. Bạn có thể sử dụng nó để theo dõi nhiều bộ mô tả tập tin như bạn có. Và nếu bạn chỉ có một bộ mô tả tập tin, nhưng giá trị của nó lớn hơn FD_SETSIZE, thì epoll cũng hoạt động với nó, nhưng select
thì không.
Ngẫu nhiên, gần đây tôi đã phát hiện một hạn chế nhỏ đối với epoll
so với select
hoặc poll
.Mặc dù không có API nào trong số ba API này hỗ trợ các tệp bình thường (ví dụ: tệp trên hệ thống tệp), select
và poll
trình bày sự thiếu hỗ trợ này khi báo cáo các mô tả như luôn đọc được và luôn ghi. Điều này làm cho chúng không phù hợp với bất kỳ loại I/O hệ thống tập tin không bị chặn nào, một chương trình sử dụng select
hoặc poll
và xảy ra gặp phải một bộ mô tả tập tin từ hệ thống tập tin ít nhất sẽ tiếp tục hoạt động (hoặc không thành công) là vì select
hoặc poll
), mặc dù nó có lẽ không có hiệu suất tốt nhất.
Mặt khác, epoll
sẽ không nhanh với lỗi (EPERM
, rõ ràng) khi được yêu cầu giám sát bộ mô tả tệp như vậy. Nói đúng ra, điều này hầu như không chính xác. Nó chỉ đơn thuần là báo hiệu sự thiếu hỗ trợ của nó một cách rõ ràng. Thông thường tôi sẽ hoan nghênh điều kiện thất bại rõ ràng, nhưng điều này là không có giấy tờ (theo như tôi có thể nói) và kết quả trong một ứng dụng hoàn toàn bị hỏng, chứ không phải là một trong đó chỉ hoạt động với hiệu suất có khả năng bị suy thoái.
Trong thực tế, nơi duy nhất tôi thấy điều này xuất hiện là khi tương tác với stdio. Người dùng có thể chuyển hướng stdin hoặc stdout từ/sang tệp bình thường. Trong khi trước đó stdin và stdout sẽ có được một đường ống - được hỗ trợ bởi epoll tốt - nó sau đó trở thành một tập tin bình thường và epoll không lớn tiếng, phá vỡ các ứng dụng.
Câu trả lời rất hay. Hãy xem xét rõ ràng về hành vi của 'poll' cho tính đầy đủ? – quark
Hai xu của tôi về hành vi đọc từ các tập tin thông thường: Tôi thường thích thất bại hoàn toàn với suy thoái hiệu suất. Lý do là nó có nhiều khả năng được phát hiện trong quá trình phát triển, và do đó làm việc xung quanh đúng (nói bằng cách có một phương pháp thay thế để làm I/O cho các tập tin thực tế). YMMV tất nhiên: có thể không có sự suy giảm đáng chú ý trong trường hợp thất bại không tốt hơn. Nhưng sự chậm lại đáng kể xảy ra chỉ trong trường hợp đặc biệt có thể rất khó nắm bắt trong quá trình phát triển, để lại nó như một quả bom thời gian khi thực sự triển khai. – quark
Chỉ cần đọc toàn bộ nội dung chỉnh sửa của bạn. Theo một nghĩa nào đó, tôi đồng ý rằng nó có thể không đúng cho epoll không bắt chước người tiền nhiệm của nó nhưng sau đó tôi lại có thể tưởng tượng nhà phát triển đã triển khai lỗi EPERM nghĩ "Chỉ vì nó luôn bị hỏng, không làm cho tôi phá vỡ tốt." Và một lập luận truy cập khác, tôi là một lập trình viên phòng thủ bất cứ điều gì qua 1 + 1 là nghi ngờ và tôi mã theo cách như vậy để cho phép thất bại duyên dáng. Có hạt nhân cháy ra khỏi lỗi mong đợi không phải là tốt đẹp hoặc chu đáo. – David