Почему у ucontext такие высокие накладные расходы?
В документации для Boost.Context в Boost v1.59 представлены следующие результаты сравнения производительности:
+----------+----------------------+-------------------+-------------------+----------------+
| Platform | ucontext_t | fcontext_t | execution_context | windows fibers |
+----------+----------------------+-------------------+-------------------+----------------+
| i386 | 708 ns / 754 cycles | 37 ns / 37 cycles | ns / cycles | ns / cycles |
| x86_64 | 547 ns / 1433 cycles | 8 ns / 23 cycles | 16 ns / 46 cycles | ns / cycles |
+----------+----------------------+-------------------+-------------------+----------------+
Я считаю, что исходный код для этих экспериментов размещен на GitHub.
Мой вопрос: почему накладные расходы на ucontext в 20 раз выше, чем в реализации библиотеки Boost? Я не вижу никакой очевидной причины, по которой такая большая разница. Использует ли реализация Boost какой-то низкоуровневый трюк, который пропустили реализации ucontext, или что-то еще происходит здесь?
1 ответ
В документации Boost указано, почему Boost.context быстрее устаревшего ucontext_t
интерфейсы. В разделе Обоснование вы найдете это важное примечание:
Примечание. Переключатели контекста не сохраняют маску сигналов в системах UNIX.
и, по сравнению с makecontext
в других API:
ucontext_t сохраняет маску сигнала между переключателями контекста, которая включает системные вызовы, потребляющие много циклов ЦП.
Как указано, swapcontext
сохраняет маску сигнала, которая требует системного вызова и всех накладных расходов, которые влекут за собой. Так как это было точно ucontext_t
функции, это не может быть описано как недосмотр. (Если вы не хотите сохранять маску сигнала, вы можете использовать setjmp
а также longjmp
.)
Кстати, ucontext_t
функции были объявлены устаревшими в Posix редакции 6 и удалены в редакции 7, потому что (1) makecontext
интерфейс требует устаревшей функции C, которая вообще недоступна в C++; (2) интерфейсы используются редко; и (3) сопрограммы могут быть реализованы с использованием потоков Posix. (См. Примечание в редакции Posix 6.) (Очевидно, что потоки не являются идеальным механизмом для реализации сопрограмм, но и интерфейс не использует устаревшую функцию.)