Готовність проти завершення Використання пам'яті Async IO?


12

Я дивився цю розмову про впровадження Async IO в Rust, а Карл згадує про дві потенційні моделі. Готовність та завершення.

Модель готовності:

  • ви скажете ядро, яке ви хочете прочитати з сокета
  • робити інші речі на деякий час ...
  • ядро повідомляє вам, коли сокет готовий
  • ви читаєте (заповнюйте буфер)
  • робіть все, що вам потрібно
  • звільніть буфер (відбувається автоматично з Rust)

Модель завершення:

  • Ви виділяєте буфер для ядра для заповнення
  • робити інші речі на деякий час ...
  • ядро повідомляє вам, коли буфер був заповнений
  • робити все, що вам потрібно, з даними
  • звільнити буфер

На прикладі Карла, використовуючи модель готовності, ви можете переглядати заповнення готових сокетів і звільняти глобальний буфер, завдяки чому здається, що він буде використовувати набагато менше пам'яті.

Тепер мої припущення:

Під кришкою (у просторі ядра), коли сокет вважається "готовим", дані вже є. Він потрапив у сокет через мережу (або з будь-якого місця), і ОС тримає дані.

Це не так, якби магічне розподілення пам'яті не відбувається в моделі готовності. Просто ОС це абстрагує це від вас. У моделі завершення ОС вимагає виділити пам'ять до того, як дані дійсно надходять, і очевидно, що відбувається.

Ось моя змінена версія моделі готовності:

  • ви скажете ядро, яке ви хочете прочитати з сокета
  • робити інші речі на деякий час ...
  • ЗМІНА: дані надходять в ОС (деяке місце в пам'яті ядра)
  • ядро повідомляє вам, що сокет готовий
  • ви читаєте (заповніть інший буфер окремо від буфера ядра abover (або ви отримаєте вказівник на нього?))
  • робіть все, що вам потрібно
  • звільніть буфер (відбувається автоматично з Rust)

/ Мої припущення

Мені подобається, щоб програма для простору користувачів була невеликою, але я просто хотів трохи уточнити, що насправді відбувається тут. Я не бачу, щоб одна модель по суті використовувала менше пам'яті або підтримувала більш високий рівень одночасного вводу-виводу. Я хотів би почути думки та глибші пояснення цього.


Я також приїхав сюди з тієї розмови на YouTube. Для всіх, хто дізнається про те, як асинхронізувати IO або як реалізувати цикли подій, команда Rust має цей список відтворення "Aysnc Interviews" тут, опитуючи дуже знаючих людей із спільноти
cacoder

Відповіді:


5

У моделі готовності споживання пам’яті пропорційно кількості даних, що не споживаються програмою.

У моделі завершення споживання пам'яті пропорційно кількості викликів у розетці.

Якщо є багато розеток, які в основному простоюють, то модель готовності витрачає менше пам’яті.

Існує просте виправлення моделі завершення: ініціюйте зчитування в 1 байт. При цьому витрачається лише крихітний буфер. Коли зчитування завершено, видайте інше (можливо синхронне) зчитування, яке отримує решту даних.

У деяких мовах модель завершення надзвичайно проста у виконанні. Я вважаю це гарним вибором за замовчуванням.


1

У моделі завершення ОС вимагає виділити пам'ять до того, як дані дійсно надходять, і очевидно, що відбувається.

Але що станеться, якщо надійде більше даних, ніж ви виділили місце? Ядро все ще має виділити власний буфер, щоб не скидати дані. (Наприклад, саме тому 1-байтний трюк для читання, згаданий у відповіді usr, працює.)

Компроміс полягає в тому, що, хоча Модель завершення споживає більше пам’яті, вона також може (іноді) робити менше операцій з копіюванням, оскільки зберігання буфера навколо означає, що апаратне забезпечення може DMA безпосередньо виходити з нього або в нього. Я також підозрюю (але менш впевнений), що Модель завершення має тенденцію виконувати фактичну операцію копіювання (коли вона існує) на іншій потоці, принаймні для IOCP Windows, в той час як модель готовності робить це як частину неблокуючої read()або write()дзвінок.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.