파이버는 작업 단위 간의 상호협동성 을 극대화한 병행처리 기법이자 각 작업 단위를 가르키는 단어입니다.
D 언어에 구현된 이 기법은 core.thread
모듈 안에 정의되어있습니다.
파이버가 상호협동성 을 가진 병행처리 기법이 된 배경에는, 프로그램에 제공될 입력을 무한정 기다릴 이유가 없다는 사실이 있습니다.
만약 어떤 입력을 기다려야한다면, 기다리는 동안에 현재 작업을 일시정지하고 Fiber.yield()
를 실행하여 입력이 준비될 동안 다른 작업을 수행하는 게 효율적일 것입니다.
Fiber.yield()
를 통해 입력값을 기다리던 상위 작업으로 돌아감과 동시에, 현재까지 실행 중이던 컨텍스트(함수 호출 스택에 저장되어있음)를 백업합니다. 그리고 상위 작업이 다시 Fiber.yield()
를 호출하여 프로그램 입력을 기다리던 작업에게 실행 순서를 반납해주면 일시정지된 작업이 다시 동작합니다.
void foo() {
writeln("Hello");
Fiber.yield();
writeln("World");
}
// ...
auto f = new Fiber(&foo);
f.call(); // Hello 출력하고, 이 Fiber는 일시정지됨
f.call(); // 다음 호출에서 재개되어 World 출력
파이버의 이런 실행 특성을 활용해 하나의 CPU 코어를 여러 파이버가 효율적으로 나눠쓸 수 있게 만들 수 있습니다.
쓰레드를 여러개 사용할 때와 파이버를 여러개 사용할 때를 비교해보면, 파이버는 컨텍스트 스위칭(context switching)이 필요하지 않아 시스템 자원 소모를 아낄 수 있는 장점이 있습니다. 반대로 쓰레드는 서로 다른 쓰레드가 동작할 때 지속적인 컨텍스트 스위칭이 발생합니다.
D 언어 라이브러리 중 파이버를 잘 활용하는 예로는 vibe.d 프레임워크 라는 비동기 I/O를 이용해 깔끔한 코드를 유지하면서도 높은 성능을 보여주는 웹 프레임워크가 있습니다.