Sẵn sàng so với hoàn thành Async IO Sử dụng bộ nhớ?


12

Tôi đã xem bài nói chuyện này về việc triển khai Async IO trong Rust và Carl đề cập đến hai mô hình tiềm năng. Sẵn sàng và hoàn thành.

Mô hình sẵn sàng:

  • bạn nói với kernel bạn muốn đọc từ socket
  • làm những việc khác trong một lúc
  • kernel cho bạn biết khi socket đã sẵn sàng
  • bạn đọc (điền vào một bộ đệm)
  • làm bất cứ điều gì bạn cần
  • giải phóng bộ đệm (xảy ra tự động với Rust)

Mô hình hoàn thành:

  • bạn cấp phát một bộ đệm cho kernel để điền vào
  • làm những việc khác trong một lúc
  • kernel cho bạn biết khi bộ đệm đã được lấp đầy
  • làm bất cứ điều gì bạn cần với dữ liệu
  • giải phóng bộ đệm

Trong ví dụ của việc sử dụng các mô hình sẵn sàng Carl bạn có thể lặp trên ổ cắm sẵn sàng điền và giải phóng một bộ đệm toàn cầu mà làm cho nó có vẻ như nó sẽ sử dụng nhiều ít bộ nhớ.

Bây giờ giả định của tôi:

Dưới mui xe (trong không gian kernel) khi ổ cắm được cho là "sẵn sàng", dữ liệu đã tồn tại. Nó đã đi vào ổ cắm qua mạng (hoặc từ bất cứ đâu) và HĐH đang giữ dữ liệu.

Không giống như việc phân bổ bộ nhớ một cách kỳ diệu không xảy ra trong mô hình sẵn sàng. Chỉ là hệ điều hành đang trừu tượng hóa nó từ bạn. Trong mô hình Hoàn thành, HĐH đang yêu cầu bạn phân bổ bộ nhớ trước khi dữ liệu thực sự chảy vào và rõ ràng điều gì đang xảy ra.

Đây là phiên bản sửa đổi của Mô hình Sẵn sàng:

  • bạn nói với kernel bạn muốn đọc từ socket
  • làm những việc khác trong một lúc
  • SỬA ĐỔI: dữ liệu đi vào HĐH (một số vị trí trong bộ nhớ kernel)
  • kernel cho bạn biết socket đã sẵn sàng
  • bạn đọc (điền vào một bộ đệm khác tách biệt với bộ đệm hạt nhân abover (hoặc bạn có một con trỏ tới nó?))
  • làm bất cứ điều gì bạn cần
  • giải phóng bộ đệm (xảy ra tự động với Rust)

/ Giả định của tôi

Tôi tình cờ thích giữ chương trình không gian người dùng nhỏ nhưng tôi chỉ muốn làm rõ một chút về những gì thực tế đang xảy ra ở đây. Tôi không thấy rằng một mô hình vốn dĩ sẽ sử dụng ít bộ nhớ hơn hoặc hỗ trợ mức IO đồng thời cao hơn. Tôi muốn nghe suy nghĩ và giải thích sâu hơn về điều này.


Tôi cũng đến đây từ buổi nói chuyện trên YouTube. Đối với bất kỳ ai tìm hiểu về cách async IO hoặc cách triển khai các vòng lặp sự kiện, nhóm Rust có danh sách phát "Phỏng vấn Aysnc" này tại đây để phỏng vấn những người rất am hiểu từ cộng đồng
cacoder

Câu trả lời:


5

Trong mức tiêu thụ bộ nhớ Mô hình sẵn sàng tỷ lệ thuận với lượng dữ liệu mà ứng dụng chưa biết đến.

Trong Mô hình Hoàn thành, mức tiêu thụ bộ nhớ tỷ lệ thuận với số lượng cuộc gọi ổ cắm chưa xử lý.

Nếu có nhiều ổ cắm hầu hết không hoạt động thì Mô hình sẵn sàng tiêu thụ ít bộ nhớ hơn.

Có một cách khắc phục dễ dàng cho Mô hình Hoàn thành: Bắt đầu đọc 1 byte. Điều này chỉ tiêu thụ một bộ đệm nhỏ. Khi đọc xong sẽ phát hành một lần đọc khác (có thể đồng bộ) để lấy phần còn lại của dữ liệu.

Trong một số ngôn ngữ, Mô hình Hoàn thành cực kỳ đơn giản để thực hiện. Tôi coi đó là một lựa chọn mặc định tốt.


1

Trong mô hình Hoàn thành, HĐH đang yêu cầu bạn phân bổ bộ nhớ trước khi dữ liệu thực sự chảy vào và rõ ràng điều gì đang xảy ra.

Nhưng điều gì xảy ra nếu có nhiều dữ liệu đến hơn không gian bạn phân bổ? Hạt nhân vẫn phải phân bổ bộ đệm riêng để không làm rơi dữ liệu. (Ví dụ, đây là lý do tại sao thủ thuật đọc 1 byte được đề cập trong câu trả lời của usr hoạt động.)

Sự cân bằng là trong khi Mô hình Hoàn thành tiêu tốn nhiều bộ nhớ hơn, đôi khi nó cũng có thể thực hiện ít thao tác sao chép hơn, bởi vì giữ bộ đệm xung quanh có nghĩa là phần cứng có thể DMA trực tiếp thoát ra hoặc vào nó. Tôi cũng nghi ngờ (nhưng ít chắc chắn hơn) rằng Mô hình Hoàn thành có xu hướng thực hiện thao tác sao chép thực tế (khi nó tồn tại) trên một luồng khác, ít nhất là đối với IOCP của Windows, trong khi Mô hình Sẵn sàng thực hiện như một phần của việc không chặn read()hoặc write()gọi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.