Eio

Eio

libeio C 라이브러리를 통해 비동기 POSIX I/O를 제공하는 확장이에요. 파일 작업을 블로킹하지 않고 요청으로 쌓아 두고 나중에 처리하는 방식이라, 대용량 파일 I/O를 효과적으로 다룹니다.

출처: Eio

본문

이 확장은 Marc Lehmann이 작성한 libeio C 라이브러리를 통해 비동기 POSIX I/O를 제공합니다. Windows 플랫폼에서는 사용할 수 없어요.

여기서 꼭 알아두어야 할 점이 있습니다. 요청 하나하나는 스레드에서 실행되기 때문에, 큐에 계속 쌓인 요청들의 실행 순서는 기본적으로 예측할 수 없어요. 예를 들어 아래 코드는 올바르지 않습니다.

<?php
// Request to create symlink of $filename to $link
eio_symlink ( $filename , $link );

// Request to move $filename to $new_filename
eio_rename ( $filename , $new_filename );

// Process requests
eio_event_loop ();
?>

위 예시에서 eio_rename() 요청이 eio_symlink()보다 먼저 끝날 수 있어요. 이 문제를 해결하려면 eio_rename()eio_symlink()의 콜백에서 호출하면 됩니다.

<?php
function my_symlink_done ( $filename , $result ) {
	// Request to move $filename to $new_filename
	eio_rename ( $filename , "/path/to/new-name" );

	// Process requests
	eio_event_loop ();
}

// Request to create symlink of $filename to $link
eio_symlink ( $filename , $link , EIO_PRI_DEFAULT , "my_symlink_done" , $filename );

// Process requests
eio_event_loop ();
?>

또는 요청 그룹(request group)을 만들어 처리할 수도 있어요.

<?php
/* Is called when the group requests are done */
function my_grp_done ( $data , $result ) {
	// ...
}

function my_symlink_done ( $filename , $result ) {
	// Create eio_rename request and add it to the group
	$req = eio_rename ( $filename , "/path/to/new-name" );
	eio_grp_add ( $grp , $req );
	// You might want to add more requests...
}

// Create a request group
$grp = eio_grp ( "my_grp_done" , "my_grp_data" );

// Create eio_symlink request and add it to the group
// Pass $filename to the callback
$req = eio_symlink ( $filename , $link ,
	EIO_PRI_DEFAULT , "my_symlink_done" , $filename );
eio_grp_add ( $grp , $req );

// Process requests
eio_event_loop ();
?>

그룹은 일반 eio 요청들의 집합을 쌓아 둘 수 있는 특별한 종류의 요청이에요. 파일을 열고 읽고 닫는 복잡한 요청을 만들 때도 이 그룹을 사용할 수 있습니다.

0.3.0 alpha 버전부터는 libeio와 내부적으로 통신에 쓰는 변수를 eio_get_event_stream()으로 가져올 수 있어요. 이 변수를 다른 확장이 지원하는 이벤트 루프에 바인딩할 수 있습니다. 예를 들어 eio와 libevent를 함께 동작시키는 간단한 이벤트 루프를 구성할 수 있어요.

<?php
function my_eio_poll ( $fd , $events , $arg ) {
	/* Some libevent regulation might go here .. */
	if ( eio_nreqs ()) {
		eio_poll ();
	}
	/* .. and here */
}

function my_res_cb ( $d , $r ) {
	var_dump ( $r ); var_dump ( $d );
}

$base = event_base_new ();
$event = event_new ();

// This stream is used to bind with libevent
$fd = eio_get_event_stream ();

eio_nop ( EIO_PRI_DEFAULT , "my_res_cb" , "nop data" );
eio_mkdir ( "/tmp/abc-eio-temp" , 0750 , EIO_PRI_DEFAULT , "my_res_cb" , "mkdir data" );
/* some other eio_* calls here ... */

// set event flags
event_set ( $event , $fd , EV_READ /*| EV_PERSIST*/ , "my_eio_poll" , array( $event , $base ));

// set event base
event_base_set ( $event , $base );

// enable event
event_add ( $event );

// start event loop
event_base_loop ( $base );

/* The same will be available via buffered libevent interface */
?>

더 알아보기