Libxev-кроссплатформенный цикл событий. Libxev предоставляет унифицированную абстракцию цикла событий для неблокирующего ввода-вывода, таймеров, сигналов, событий и многого другого, который работает на MacOS, Windows, Linux и Webassembly (браузер и WASI). Он написан в Zig, но экспортирует C-совместимый API C (что дополнительно делает его совместимым с любым языком, который может общаться с C API).
Статус проекта:? Нестабильное, альфа-качество. Список функций довольно хороший на нескольких платформах, но есть много недостающих функций. Проект не был хорошо протестирован в реальной среде, и существует множество низко висящих фруктов для оптимизации производительности. На этом этапе я тоже не обещаю никакой совместимости API. Если вы хотите, чтобы производство готово, высококачественное, обобщенное внедрение цикла событий Проверьте Libuv, Libev и т. Д.
Почему новая библиотека цикла событий? Несколько причин. Во -первых, я думаю, что у Zig не хватает обобщенной петли событий, сравнимых с либеву, по функциям («обобщенное» является ключевым словом здесь). Во -вторых, я хотел создать такую библиотеку вокруг дизайнерских шаблонов IO_URY, даже имитируя его стиль поверх других примитивов ОС (кредит на этот удивительный пост в блоге). В -третьих, я хотел библиотеку цикла событий, которая могла бы построить в Webassembly (как WASI, так и отдельно стоящий), и это не очень хорошо вписывалось в цели стиля API существующих библиотек, не привлекая что -то очень тяжелое, похожее на Emscripten. Мотивация для этой библиотеки, в первую очередь, - это царапает мой собственный зуд!
Кроссплатформенный. Linux ( io_uring and epoll ), macos ( kqueue ), webassembly + wasi ( poll_oneoff , резьбовые и неоттрачиваемые время выполнения). (Поддержка Windows запланирована и скоро появится)
Проактор API. Работа представлена в цикл событий Libxev, а вызывающий абонент уведомляется о завершении работы, в отличие от готовности к работе.
Нулевое распределение времени выполнения. Это помогает сделать производительность выполнения более предсказуемой и делает Libxev хорошо подходящим для встроенных сред.
Таймеры, TCP, UDP, файлы, процессы. Высокоуровневые API-агенты для взаимодействия с таймерами, розетками TCP/UDP, файлами, процессами и многим другим. Для платформ, которые не поддерживают Async IO, операции файлов автоматически запланированы в пул потоков.
Общий бассейн потоков (необязательно). Вы можете создать общий пул потоков, настроить его использование ресурсов и использовать его для выполнения пользовательских фоновых задач. Пул потоков используется некоторыми бэкэнами для выполнения неблокирующих задач, которые не имеют надежных не блокирующих API (например, локальные операции с файлами с kqueue ). Пул потоков может быть использован по нескольким потокам и циклам событий для оптимизации использования ресурсов.
API низкого уровня и высокого уровня. API высокого уровня зависит от платформы, но имеет некоторое самоуверенное поведение и ограниченную гибкость. Рекомендуется высокоуровневый API, но API низкого уровня всегда является доступным люком Escape. Низкоуровневый API является специфичным для платформы и обеспечивает механизм для пользователей LibxEV, чтобы выжать максимальную производительность. Низкоуровневый API-это достаточно абстракции над интерфейсом ОС, чтобы облегчить его использование, не жертвуя заметной производительностью.
Дерево встряхивая (зиг). Это особенность Zig, но существенно приносит пользу, таким как Libxev. Zig будет включать только функциональные вызовы и функции, которые вы на самом деле используете. Если вы не используете конкретный вид наблюдателя высокого уровня (например, розетки UDP), то функциональность, связанная с этой абстракцией, вообще не составлена в ваш последний бинар. Это позволяет Libxev поддержать необязательную функцию «Nice-To Have», которая в некоторых случаях может считаться «раздутым», но конечным пользователю не нужно платить за это.
Без зависимости. У Libxev нет зависимостей, кроме встроенных APIS OS во время выполнения. Библиотека C зависит от LIBC. Это очень легко перекрестно занято.
Есть много недостающих функций, которые я все еще хочу добавить:
И еще ...
Существует много возможностей для улучшения производительности, и я хочу быть совершенно ясно, что я не выполнил много работы оптимизации. Тем не менее, производительность выглядит хорошо. Я пытался перенести многие тесты Libuv, чтобы использовать API Libxev.
Я не буду публиковать конкретные результаты эталона, пока у меня не будет лучшей среды для их запуска. В качестве очень широкого обобщения вы не должны замечать замедление с помощью Libxev по сравнению с другими основными петлями событий. Это может отличаться на основе функции, и если вы можете показать действительно плохую работу в проблеме, я заинтересован в ее разрешении!
В приведенном ниже примере показана идентичная программа, написанная в Zig и в C, которая использует Libxev для запуска одного таймера 5S. Это почти глупо, насколько это просто, но предназначено, чтобы просто передать общее ощущение библиотеки, а не практическое использование.
| Zig | В |
const xev = @import ( "xev" );
pub fn main () ! void {
var loop = try xev . Loop . init (.{});
defer loop . deinit ();
const w = try xev . Timer . init ();
defer w . deinit ();
// 5s timer
var c : xev.Completion = undefined ;
w . run ( & loop , & c , 5000 , void , null , & timerCallback );
try loop . run ( .until_done );
}
fn timerCallback (
userdata : ? * void ,
loop : * xev.Loop ,
c : * xev.Completion ,
result : xev . Timer . RunError ! void ,
) xev.CallbackAction {
_ = userdata ;
_ = loop ;
_ = c ;
_ = result catch unreachable ;
return .disarm ;
} | # include < stddef . h >
# include < stdio . h >
# include < xev . h >
xev_cb_action timerCallback ( xev_loop * loop , xev_completion * c , int result , void * userdata ) {
return XEV_DISARM ;
}
int main ( void ) {
xev_loop loop ;
if ( xev_loop_init ( & loop ) != 0 ) {
printf ( "xev_loop_init failure n " );
return 1 ;
}
xev_watcher w ;
if ( xev_timer_init ( & w ) != 0 ) {
printf ( "xev_timer_init failure n " );
return 1 ;
}
xev_completion c ;
xev_timer_run ( & w , & loop , & c , 5000 , NULL , & timerCallback );
xev_loop_run ( & loop , XEV_RUN_UNTIL_DONE );
xev_timer_deinit ( & w );
xev_loop_deinit ( & loop );
return 0 ;
} |
Эти инструкции предназначены только для пользователей Zig Downstream. Если вы используете API C в Libxev, см. Раздел «сборка».
Этот пакет работает с менеджером Zig Package, представленным в Zig 0.11. Создайте файл build.zig.zon как это:
.{
. name = "my-project" ,
. version = "0.0.0" ,
. dependencies = .{
. libxev = .{
. url = "https://github.com/mitchellh/libxev/archive/<git-ref-here>.tar.gz" ,
. hash = "12208070233b17de6be05e32af096a6760682b48598323234824def41789e993432c" ,
},
},
} И в вашем build.zig :
const xev = b . dependency ( "libxev" , .{ . target = target , . optimize = optimize });
exe . addModule ( "xev" , xev . module ( "xev" ));? Документация-это неверная работа. ?
В настоящее время документация доступна в трех формах: Man страниц , примеров и комментариев кода. В будущем я планирую написать подробные руководства и документацию по API в форме веб -сайта, но в настоящее время это недоступно.
Страницы управления относительно детализированы! xev(7) даст вам хороший обзор всей библиотеки. xev-zig(7) и xev-c(7) предоставит обзоры Zig и C API соответственно. Оттуда доступны API-Specifc Man Pages, такие как xev_loop_init(3) . Это лучшая документация в настоящее время.
Есть несколько способов просмотра лишних страниц. Наиболее сразу же дружелюбным является просто просмотреть источники страниц Raw Man в docs/ каталоге в вашем веб -браузере. Источник страницы Man-это синтаксис , похожий на Markdown, так что он видно в вашем браузере через GitHub.
Другой подход-запустить zig build -Dman-pages , и страницы Man будут доступны в zig-out . Это требует установки SCDOC (это доступно в большинстве менеджеров пакетов). После того, как вы построили страницы Man, вы можете отображать их по пути:
$ man zig-out/share/man/man7/xev.7
И окончательный подход заключается в установке Libxev через вашего любимого менеджера пакетов (если и когда они будут доступны), который, как мы надеемся, должны поместить страницы вашего человека на путь вашего человека, так что вы можете просто сделать man 7 xev .
В examples/ папке доступны примеры. Примеры доступны как в C, так и в Zig, и вы можете сказать, какой из них использует расширение файла.
Чтобы построить пример, используйте следующее:
$ zig build -Dexample-name=_basic.zig
...
$ zig-out/bin/example-basic
...
Значение -Dexample-name должно быть именем файла, включая расширение.
Зиг -код хорошо прокомментирован. Если вам удобно читать комментарии кода, вы можете найти в них много понимания. Источник находится в src/ Directory.
Сборка требует установки последних Zig Nightly. У Libxev нет других зависимостей для сборки.
После установки zig build install самостоятельно построит полную библиотеку и выведет FHS-совместимый каталог в zig-out . Вы можете настроить выходной каталог с помощью флага --prefix .
У Libxev большой и растущий тестовый набор. Чтобы запустить тесты для текущей платформы:
$ zig build test
...Это запустит все тесты для всех поддерживаемых функций для текущей хост -платформы. Например, на Linux это будет запускать как полный набор IO_URY и Epoll Test.
Вы можете создавать и запускать тесты для других платформ, перекрестно скомпилируя тестовый исполняемый файл, копируя его на целевую машину и выполняя его. Например, ниже показано, как перекрестно компилировать и построить тесты для macOS из Linux:
$ zig build -Dtarget=aarch64-macos -Dinstall-tests
...
$ file zig-out/bin/xev-test
zig-out/bin/xev-test: Mach-O 64-bit arm64 executableWASI-это специальный случай. Вы можете запустить тесты для WASI, если у вас установлен Wasmtime:
$ zig build test -Dtarget=wasm32-wasi -Dwasmtime
...