2011年7月、Joyent社はMicrosoftの協力を得てNode.jsをWindowsへ移植することを発表しました。

この移植プロジェクトは現在も精力的に進められていますが、その過程で非常に重要な成果物が誕生しました。

それが、Node.jsのプラットフォーム依存コードを抽象化するために設計された新しいライブラリ「libuv」です。

本記事では、2011年9月時点におけるlibuvのステータスレポートに基づき、その設計思想や実装状況、そしてNode.js以外のプロジェクトへの広がりについて詳しく解説します。

libuvの目的と設計思想

libuvの主な目的は、Node.jsにおいてOSごとに異なるネットワークやシステムコールなどのコードを一箇所に集約し、抽象化することにあります。

これにより、V8エンジンへのバインディングを行う前に、コードの正確性とパフォーマンスを独立してテストすることが可能になりました。

Node.jsは、その設計の根幹として「完全にノンブロッキングであること」を掲げています。

libuvはこの思想を具現化するための基盤であり、それ自体がBSDライセンスで公開された、最小構成かつ高性能なクロスプラットフォーム・ネットワーキングライブラリとして機能します。

開発にあたっては、既存の優れた資産を無駄にしない「車輪の再発明を避ける」方針が採られています。

Unix系のバックエンドにおいては、Marc Lehmann氏が開発したlibevおよびlibeioをベースにしており、DNS解決にはDaniel Stenberg氏のC-Aresが統合されています。

また、ビルドシステムにはGoogle Chromeでも利用されているGYPを採用しています。

現在実装されている主要機能

2011年9月現在、libuvには以下の機能が既に実装されています。

特にWindows対応においては、IOCP(Input/Output Completion Port)を利用した効率的なノンブロッキングTCPソケットの実装が完了している点が大きなトピックです。

カテゴリ実装済みの機能
ネットワークノンブロッキングTCPソケット、UDP、名前付きパイプ
システムタイマー、子プロセスの生成
ファイル操作非同期ファイルシステムAPI(uv_fs_*)
その他高精度タイマー(uv_hrtime)、実行パス取得、スレッドプール

非同期ファイルシステム操作のAPIなどは、以下のようにC言語から利用できる設計になっています。

C言語
// libuvを使用したファイル情報の取得例
uv_fs_t req;
// 指定したパスのファイルステータスを非同期で取得
int result = uv_fs_stat(loop, &req, "/path/to/file", NULL);
if (result == 0) {
    // 成功した場合、ファイルサイズなどを表示
    printf("File size: %lld\n", req.statbuf.st_size);
}
// リクエストに使用したメモリのクリーンアップ
uv_fs_req_cleanup(&req);

開発中の次期機能

さらに、プラットフォームとしての完成度を高めるため、以下の機能が開発の最終段階にあります。

  • ファイルシステムイベント:現在はLinuxのinotifyやWindowsのReadDirectoryChangesWをサポートしていますが、今後はkqueueevent portsへの対応も予定されています。
  • VT100 TTY:端末制御を抽象化するためのuv_tty_tの実装。
  • プロセス間ソケット共有:プロセス間で通信を行うためのuv_ipc_tのAPI設計。

対応プラットフォームとコミュニティの広がり

libuvは、広範なオペレーティングシステムをサポートしています。

WindowsにおいてはWindows XP SP2以降をサポートしており、Visual StudioまたはMinGWでビルドが可能です。

その他のUnix系OSでも、Linux 2.6以降、Solaris 121以降、Macintosh Darwinなど、主要な環境を網羅しています。

驚くべきことに、libuvはその汎用性の高さから、Node.js v0.5の内部基盤としてだけでなく、他の多くのプロジェクトでも採用され始めています。

  • Mozillaが開発するプログラミング言語「Rust」
  • LuaでNode.jsのようなイベント駆動を実現するLuaNode
  • 非同期PHPを実現するプロジェクトPhode
  • C#向けのバインディングであるlibuv-csharp

このように、libuvは単なるNode.jsの一コンポーネントという枠を超え、次世代の非同期プログラミング基盤としての地位を確立しつつあります。

まとめ

libuvのステータスレポートからは、Node.jsが単にWindowsで動作するようになるという以上の進化を遂げていることが伺えます。

プラットフォームごとの差異を吸収し、どこでも一貫した高いパフォーマンスを発揮できる基盤が整ったことで、Node.jsの可能性はさらに広がりました。

また、Rustのような他の言語プロジェクトにも採用されている事実は、libuvがいかに洗練されたライブラリであるかを証明しています。

今後、ファイルシステムイベントやIPCなどの機能が完全に統合されることで、クロスプラットフォーム開発におけるデファクトスタンダードの一つとなっていくでしょう。

Node.jsコミュニティとlibuvの今後の進展に、引き続き注目が集まります。