Libxev는 크로스 플랫폼 이벤트 루프입니다. Libxev는 비 차단 IO, 타이머, 신호, 이벤트 등에 대한 통합 이벤트 루프 추상화를 제공합니다. Zig로 작성되었지만 C 호환 API를 내보내고 있습니다 (이는 C API와 통신 할 수있는 모든 언어와 호환됩니다).
프로젝트 상태 :? 불안정하고 알파에 대한 품질. 기능 목록은 여러 플랫폼에서 상당히 우수하지만 누락 된 기능이 많이 있습니다. 이 프로젝트는 실제 환경에서 잘 테스트되지 않았으며 성능 최적화를위한 많은 저급 과일이 있습니다. 이 시점에서 API 호환성을 약속하지는 않습니다. 생산 준비, 고품질의 일반화 된 이벤트 루프 구현 Libuv, Libev 등을 확인하십시오.
새로운 이벤트 루프 라이브러리 인 이유는 무엇입니까? 몇 가지 이유. 하나는 Zig에 Libuv와 비슷한 일반화 된 이벤트 루프가 부족하다고 생각합니다 ( "일반화 된"은 핵심 단어입니다). 둘째, 나는 io_uring의 디자인 패턴을 중심으로 이와 같은 라이브러리를 만들고 싶었고, 다른 OS 프리미티브 (이 멋진 블로그 게시물의 신용)에서 스타일을 모방했습니다. 셋째, WebAssembly (WASI 및 FREESTANDING)에 구축 할 수있는 이벤트 루프 라이브러리를 원했고 EMScripten과 같은 매우 무거운 무언가를 가져 오지 않고 기존 라이브러리의 API 스타일의 목표에 적합하지 않은 이벤트 루프 라이브러리를 원했습니다. 이 도서관의 동기는 주로 내 가려움증을 긁는 것입니다!
크로스 플랫폼. Linux ( io_uring and epoll ), macos ( kqueue ), webassembly + wasi ( poll_oneoff , 스레드 및 비 스레드 런타임). (Windows 지원이 계획되고 곧 출시됩니다)
Proactor API. 작업은 libxev 이벤트 루프에 제출되며 발신자는 작업 준비 와 달리 작업 완료 를 통보합니다.
제로 런타임 할당. 이를 통해 런타임 성능을보다 예측 가능하게 만들고 Libxev가 임베디드 환경에 적합합니다.
타이머, TCP, UDP, 파일, 프로세스. 타이머, TCP/UDP 소켓, 파일, 프로세스 등과의 상호 작용을위한 고급 플랫폼 공연 API. Async IO를 지원하지 않는 플랫폼의 경우 파일 작업이 스레드 풀로 자동 예약됩니다.
일반 스레드 풀 (선택 사항). 일반 스레드 풀을 만들고 리소스 사용을 구성하며이를 사용하여 사용자 정의 배경 작업을 수행 할 수 있습니다. 스레드 풀은 일부 백엔드에서 신뢰할 수없는 비 블로킹 API (예 : kqueue 를 사용한 로컬 파일 작업)가없는 비 블로킹 작업을 수행하는 데 사용됩니다. 스레드 풀은 여러 스레드 및 이벤트 루프에서 공유하여 리소스 활용을 최적화 할 수 있습니다.
저수준 및 고급 API. 높은 수준의 API는 플랫폼 비석이지만 의견이 많은 행동과 유연성이 제한되어 있습니다. 고급 API가 권장되지만 저수준 API는 항상 사용 가능한 탈출 해치입니다. 낮은 수준 API는 플랫폼별로 다르며 Libxev 사용자가 최대 성능을 짜낼 수있는 메커니즘을 제공합니다. 저수준 API는 OS 인터페이스보다 충분히 추상화되어 눈에 띄는 성능을 희생하지 않으면 서 쉽게 사용할 수 있습니다.
나무 흔들림 (zig). 이것은 Zig의 기능이지만 Libxev와 같은 라이브러리에 실질적으로 이익을줍니다. Zig에는 실제로 사용하는 기능 호출 및 기능 만 포함됩니다. 특정 종류의 높은 수준의 감시자 (예 : UDP 소켓)를 사용하지 않으면 해당 추상화와 관련된 기능은 최종 바이너리에 전혀 컴파일되지 않습니다. 이를 통해 Libxev는 옵션을 지원할 수 있으며 경우에 따라 "bloat"로 간주 될 수 있지만 최종 사용자는 비용을 지불 할 필요가 없습니다.
종속성이 없습니다. libxev는 런타임에 내장 된 OS API 외에 다른 종속성이 없습니다. C 라이브러리는 LIBC에 따라 다릅니다. 이것은 크로스 컴파일하기가 매우 쉽습니다.
여전히 추가하고 싶은 빠진 기능이 많이 있습니다.
그리고 더 ...
성능 향상의 여지가 많이 있으며, 최적화 작업을 많이하지 않았다는 것을 완전히 분명히하고 싶습니다. 그럼에도 불구하고 성능은 좋아 보입니다. Libxev API를 사용하기 위해 많은 Libuv 벤치 마크를 포트하려고했습니다.
더 나은 환경을 확보 할 때까지 특정 벤치 마크 결과를 게시하지 않을 것입니다. 매우 광범위한 일반화 로서, 다른 주요 이벤트 루프와 비교하여 libxev를 사용하는 속도가 느려지지 않아야합니다. 이는 기능별로 다를 수 있으며, 문제에서 성능이 저하 될 수 있다면 문제를 해결하는 데 관심이 있습니다!
아래의 예는 Zig 및 C로 작성된 동일한 프로그램을 Libxev를 사용하여 단일 5S 타이머를 실행합니다. 이것은 얼마나 간단한 지 거의 어리석지 만 실용적인 사용 사례가 아닌 라이브러리의 전반적인 느낌을 전달하기위한 것입니다.
| 급격한 변경 | 기음 |
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 다운 스트림 사용자 전용입니다. C API에서 libxev를 사용하는 경우 "빌드"섹션을 참조하십시오.
이 패키지는 Zig 0.11에 도입 된 Zig 패키지 관리자와 함께 작동합니다. 다음과 같은 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" ));? 문서는 진행중인 작업입니다. ?
현재 문서는 사람 페이지 , 예제 및 코드 댓글의 세 가지 형태로 제공됩니다. 앞으로 웹 사이트 양식으로 자세한 안내서와 API 문서를 작성할 계획이지만 현재 사용할 수 없습니다.
남자 페이지는 비교적 상세합니다! xev(7) 전체 라이브러리에 대한 좋은 개요를 제공합니다. xev-zig(7) 및 xev-c(7) 각각 ZIG 및 C API의 개요를 제공합니다. 거기에서 xev_loop_init(3) 와 같은 API-Specifc Man 페이지를 사용할 수 있습니다. 이것은 현재 최고의 문서입니다.
남자 페이지를 탐색하는 방법에는 여러 가지가 있습니다. 가장 친근한 점은 웹 브라우저의 docs/ 디렉토리에서 Raw Man 페이지 소스를 찾아 보는 것입니다. Man Page 소스는 Markdown과 같은 구문이므로 Github를 통해 브라우저에서 괜찮습니다 .
또 다른 방법은 zig build -Dman-pages 실행하는 것이며 Man Pages는 zig-out 에서 사용할 수 있습니다. 이를 위해서는 SCDOC를 설치해야합니다 (대부분의 패키지 관리자에서 사용할 수 있음). Man Pages를 구축하면 경로별로 렌더링 할 수 있습니다.
$ 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 값은 확장자를 포함한 파일 이름이어야합니다.
Zig 코드는 잘 댓글을 달았습니다. 코드 댓글을 읽는 것이 편한 경우 그 안에서 많은 통찰력을 찾을 수 있습니다. 소스는 src/ 디렉토리에 있습니다.
빌드에는 최신 Zig Nightly를 설치해야합니다. Libxev에는 다른 빌드 종속성이 없습니다.
일단 설치되면 zig build install 자체는 전체 라이브러리를 구축하고 zig-out 의 FHS 호환 디렉토리를 출력합니다. --prefix 플래그로 출력 디렉토리를 사용자 정의 할 수 있습니다.
Libxev에는 크고 성장하는 테스트 스위트가 있습니다. 현재 플랫폼에 대한 테스트를 실행하려면 :
$ zig build test
...이렇게하면 현재 호스트 플랫폼에 대한 모든 지원되는 기능에 대한 모든 테스트가 실행됩니다. 예를 들어, Linux에서는 전체 io_uring 및 epoll 테스트 스위트를 모두 실행합니다.
테스트 실행 파일을 교차 컴파일하여 대상 기계에 복사하여 실행하여 다른 플랫폼에 대한 테스트를 구축하고 실행할 수 있습니다 . 예를 들어, 아래는 Linux에서 MacOS 테스트를 교차 컴파일하고 구축하는 방법을 보여줍니다.
$ zig build -Dtarget=aarch64-macos -Dinstall-tests
...
$ file zig-out/bin/xev-test
zig-out/bin/xev-test: Mach-O 64-bit arm64 executableWASI는 특별한 사례입니다. WASMTime이 설치된 경우 WASI 테스트를 실행할 수 있습니다.
$ zig build test -Dtarget=wasm32-wasi -Dwasmtime
...