Подходы к завершению и готовности к Futures: Rust против языков на основе времени выполнения - PullRequest
1 голос
/ 26 апреля 2020

У меня есть вопрос о подходе «готовности» к асинхронному планированию и выполнению в Rust, поскольку он относится (и отличается от) к подходу «завершения» языков на основе времени выполнения (Python, Node.js). Я использую «готовность» и «завершение», следуя терминологии сообщения в блоге , который вдохновил этот вопрос.

Если я правильно понял, фьючерсы на Rust (начиная с std-futures) реализовано в соответствии с подходом «готовности»:

  1. заключены в Задачи, которые хранят частный стек вызовов упакованного Future в памяти, чтобы обеспечить его прерывание и возобновление, предполагая, что другие Futures работают в интервал;
  2. опрашиваются по их задаче переноса в результате вызова задачи некоторыми участниками ввода-вывода (посредством обратного вызова, задание зарегистрировано для соответствующего субъекта ввода-вывода);
  3. возвращать значение тогда и только тогда, когда все другие Задачи или субъекты ввода / вывода в цепочке Задач, для которых его Задача зарегистрировала обратный вызов, были разбужены в результате готовности их собственного Будущего к опросу.

Основное различие - и то, что якобы объясняет, почему фьючерсы Rust более эффективны, чем их аналоги, основанные на времени выполнения, - это что фьючерсы не передают автоматически свое вычисленное значение на один уровень вверх по цепочке фьючерсов, вызывая следующие задачи. Вместо этого, это до последнего преемника в цепочке задач, чтобы все его предшественники инициировали каскадный опрос друг друга, вычисляя значение последнего будущего как подходящее. Таким образом, может показаться, что основное преимущество подхода «готовности» в Rust напоминает основное преимущество очереди: если вы используете фьючерсы достаточно быстро, данные не накапливаются в стеке, а потребление памяти остается низким.

И теперь, наконец, вопрос: если эта модель более эффективна, чем модель, в которой Futures создает свое собственное всплытие, не дожидаясь последнего опроса-преемника, почему такой подход не используется в Python или Nodejs? Интуитивно кажется, что преимущество этого подхода хорошо переносится на языки, основанные на времени выполнения. Обращаются ли эти языки к альтернативе «завершения», потому что они не могут использовать данные своего будущего достаточно быстро?

1 Ответ

1 голос
/ 28 апреля 2020

Не думаю, что вы правильно охарактеризовали различия между двумя моделями или основное преимущество, которое привело Rust к выбору модели «готовности».

Принципиальное отличие (как описано в Tokio Web Site ):

Асинхронная модель ржавчины основана на тяге. Вместо того, чтобы Future отвечал за передачу данных в обратный вызов, он полагается на что-то еще, спрашивающее, завершено ли оно.

Одна из ключевых целей проекта состоит в том, чтобы он представлял абстракция нулевой стоимости - которая требует, чтобы при написании асинхронного кода с использованием фьючерсов характеристики производительности были такими же хорошими, как этого можно было бы достичь путем ручного кодирования собственного события l oop и решения на основе конечного автомата.

Выбор модели на основе готовности вытекает из этого требования: если бы использовалась модель на основе завершения, для композиции фьючерсов потребовалось бы выделить соответствующие обратные вызовы для кучи (статья в блоге Вы связали показывает, почему это так). Распределение кучи обходится дорого, и цель абстракции с нулевой стоимостью не будет достигнута.

Используя модель на основе готовности, выделения кучи можно минимизировать или даже вообще избежать (особенно полезно для некоторых встроенных сред, где есть без кучи).

У этой модели есть и другие преимущества, одним из которых является простота применения противодавления, которое вы назвали ключевым преимуществом, но я не думаю, что они были решающим фактором при выборе этой модели. .

Получив это с пути:

И, наконец, вопрос: если эта модель более эффективна, чем модель, в которой Futures создает свое собственное всплывающее окно без ожидания почему в последнем опросе преемников не применяется подход, применяемый в Python или Nodejs?

Языки высокого уровня не стремятся обеспечить возможности низкого уровня, необходимые для обеспечения нулевой стоимости абстракции. Например, спецификация языка Javascript даже не говорит в терминах стека или кучи, и хотя некоторые реализации JS действительно оптимизируют локальные переменные в стеке, программисты не могут это контролировать. При выборе модели для асинхронного программирования способность составлять фьючерсы без выделения кучи не входит в уравнение.

Это не означает, что некоторые другие преимущества могут оказаться неэффективными в других средах программирования. - возможно, так оно и будет, - но поскольку большинство этих языков уже остановились на модели, основанной на завершении, и, поскольку они не имеют того же самого драйвера абстракции с нулевой стоимостью, у них может не быть желания пересмотреть проект.

...