2010-01-09 25 views
88

Mọi thứ tôi đã đọc và trải nghiệm (ứng dụng dựa trên Tornado) dẫn tôi tin rằng ePoll là một sự thay thế tự nhiên cho mạng Chọn và Cuộc thăm dò ý kiến, đặc biệt là với Twisted. Điều khiến tôi hoang tưởng, khá hiếm khi có một kỹ thuật hay phương pháp tốt hơn để không đi kèm với giá cả.Các lò phản ứng chọn lọc/thăm dò so với epoll trong Twisted

Đọc một vài chục so sánh giữa epoll và lựa chọn thay thế cho thấy rằng epoll rõ ràng là nhà vô địch về tốc độ và khả năng mở rộng, đặc biệt là quy mô trong một thời trang tuyến tính đó là tuyệt vời. Điều đó nói rằng, những gì về xử lý và sử dụng bộ nhớ, là epoll vẫn là nhà vô địch?

Trả lời

180

Đố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), selectpoll 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.

+0

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

+6

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

+1

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

3

Trong các thử nghiệm tại công ty của tôi, một vấn đề với epoll() đã xuất hiện, do đó chi phí duy nhất so với lựa chọn.

Khi cố gắng đọc từ mạng với thời gian chờ, tạo epoll_fd (thay vì FD_SET) và thêm fd vào epoll_fd, tốn kém hơn nhiều so với việc tạo FD_SET (là một malloc đơn giản). Theo câu trả lời trước, khi số lượng FD trong quá trình trở nên lớn, chi phí của select() trở nên cao hơn, nhưng trong thử nghiệm của chúng tôi, ngay cả với giá trị fd trong 10.000, chọn vẫn là một người chiến thắng . Đây là những trường hợp chỉ có một fd mà một chuỗi đang chờ đợi, và chỉ đơn giản là cố gắng vượt qua thực tế là đọc mạng và ghi mạng, không hết thời gian khi sử dụng một mô hình chuỗi chặn. Tất nhiên, việc chặn các mô hình luồng có hiệu suất thấp so với các hệ thống lò phản ứng không chặn, nhưng có những trường hợp, để tích hợp với một cơ sở mã kế thừa cụ thể, nó là bắt buộc.

Loại trường hợp sử dụng này hiếm khi xảy ra trong các ứng dụng hiệu suất cao, vì mô hình lò phản ứng không cần phải tạo epoll_fd mới mỗi lần. Đối với mô hình nơi epoll_fd tồn tại lâu dài --- được ưu tiên rõ ràng cho bất kỳ thiết kế máy chủ hiệu suất cao nào --- epoll là người chiến thắng rõ ràng theo mọi cách.

+5

Nhưng bạn thậm chí không thể sử dụng 'select()' nếu bạn có các giá trị mô tả tập tin trong phạm vi 10k + - trừ khi bạn biên dịch lại một nửa hệ thống của bạn để thay đổi FD_SETSIZE - vì vậy tôi tự hỏi chiến lược này hoạt động như thế nào. Đối với kịch bản mà bạn mô tả, tôi có thể nhìn vào 'poll()' giống như 'select()' hơn là 'epoll()' - nhưng loại bỏ giới hạn FD_SETSIZE. –

+0

Bạn có thể sử dụng select() nếu bạn có các giá trị mô tả tập tin trong phạm vi 10K, bởi vì bạn có thể malloc() một FD_SET. Trong thực tế, vì FD_SETSIZE là thời gian biên dịch và giới hạn fd thực tế là thời gian chạy, việc sử dụng AN TOÀN duy nhất của FD_SET kiểm tra số lượng bộ mô tả tệp dựa trên kích thước của FD_SET, và thực hiện một malloc (hoặc đạo đức tương đương) nếu FD_SET là quá nhỏ. Tôi đã bị sốc khi tôi thấy điều này trong sản xuất với một khách hàng. Sau khi lập trình các ổ cắm trong 20 năm, tất cả mã tôi từng viết - và hầu hết các hướng dẫn trên web - đều không an toàn. –

+5

Điều này không đúng, theo như tôi biết, trên mọi nền tảng phổ biến. 'FD_SETSIZE' là một hằng số thời gian biên dịch được thiết lập khi thư viện * C * của bạn được biên dịch. Nếu bạn định nghĩa nó thành một giá trị khác khi bạn xây dựng ứng dụng của bạn thì ứng dụng của bạn và thư viện C sẽ không đồng ý và mọi thứ sẽ kém đi. Nếu bạn có tài liệu tham khảo tuyên bố nó là an toàn để xác định lại 'FD_SETSIZE' tôi muốn được quan tâm để xem chúng. –

Các vấn đề liên quan