OSのI/O抽象化戦略について

skySchemeの重要な視点は、OSのI/O抽象化戦略が全てにフィットすることは"絶対に無い"というもので、これ自体は非常に当たり前の事だが以下について示唆をもたらす。

シングルレベルストアは問題を解決しない

C言語が用意している唯一の抽象化はメモリ抽象化であると言える。つまり、メモリオペレーションだけが抽象化され(そしてCPUによって並び替えられ、)関数の呼び出しや他の仕事は完全にorderdに実行される。
この議論にHDDを含めるためにシングルレベルストアを仮定する。いわゆるキャッシュによって実現される遅延書き込みだとか投機的な読み取りも、OSがシングルレベルストアを頑張って実現しているとすれば自然に実現される。(現状のI/O戦略の問題点を理解するためにはシングルレベルストアの仮定を使う)
しかし、HDDとメモリの機能性は完全に同一というわけではないしレイテンシも異なる。CD-R(のような追記型システム)だとかSSDの存在は問題をさらに複雑にする。
C言語にはトランザクションを記述するための方法が無いから、(言語を拡張しない限りは)OS固有の方法で実現する必要が有る。例えばmutexのような同期プリミティブとか、syncシステムコールのようにデバイスによって異なる方法論が使われる。

非同期I/O

非同期I/OはI/O処理を『発行』と『完了』に分割し、I/O処理をバックグラウンドで行えるようにする。
これは一見完璧なモデルに見える。つまり、多くのI/O処理は確かにこのモデルに従う(途中で失敗しない限りは)。もっとも、いくつかの非同期I/Oは同期I/Oのwrapperでしかない。つまりI/O用のスレッドを立ち上げて内部で同期I/Oしている。
非同期I/Oに関しても、統一された仕組みは存在しない。
例えばI/Oシステムコールを同期I/Oに絞って、I/Oスレッドによって非同期I/Oを実現するのが常に正しいのかどうかはなんとも言えない。

一度失われた構造を完全に復元することはできない

バイナリを元に動作するエミュレータが、ネイティブ動作と同様の効率を得ることは難しい とか 完全な逆コンパイラを作ることは不可能であるということはすぐ理解できる。これらはコンパイルによって失われた構造をどうにかして復元する技術に相当する。
これらと同様に、キャッシュとかプリフェッチといった『予測』技術も実は失われた構造を『復元』するという側面がある。
しかし、世間的な認識では(同じ種類のテクニックであるにも関わらず)エミュレータは遅く、キャッシュは高速と捉えられている。
この違いは、どちらの技術も、構成要素である

  • 潜在的な構造の検出
  • 失われた構造の再現

の両方を含み、キャッシュは前者の側面が強調され、エミュレータは後者の側面が強調されているに過ぎない*1
キャッシュもエミュレータと同様の非効率要因を含んでいることに注目する必要が有る。一般に、コンパイルした後のコードを最適化するよりもコンパイルする前のコードを最適化するほうが好ましい。
skySchemeにとって重要なのは、I/Oに関するプログラムの構造はC言語に落とした段階で失われてしまうという主張で、I/O戦略のためのより構造化されたシステム(とコンパイラ)が必要だということになる。コンパイラがCPUごとに存在するのと同じように、コンパイラはI/O戦略ごとにも存在しなければならない。『I/O戦略ごとのコンパイラ』をC言語に対して作るのはあまり容易では無いだろう。
端的に言えば、以下のような対応を想像する。

I/O 演算
システムコール CPU命令セット
I/O抽象化戦略 VM命令セット
(skyScheme) C言語/FORTRAN
C言語 アセンブラ

演算におけるC言語がI/Oにおけるアセンブラに相当する。C言語FORTRANは演算の最適化には申し分ない。
たとえばJavaで数値演算を行うことが最善の方法でないことは容易に理解できる。CPU以外にもGPUとかDSPがあり、それらにとって最適なプログラムを供給するにはC言語(やそのバリアント)しか選択肢が無いからだ。
しかし、I/Oが演算でいうCPUとGPUDSPの戦いのように多様化しているとはみなされていない。CPUのシングルスレッド性能が停滞する中で、I/O性能はまだ1段階は成長の余地がある。そうなってきたときに初めて多彩なI/O戦略をポータブルに実現する手法が注目されるのかもしれない。
もっとも、skySchemeもこの領域に集中しているわけではなく、単にプロトコル記述言語を素直に作るとこの領域に対して挑戦することが出来るということでしかない。(もっとも、これはPRECCSのようにI/OプリミティブをC言語に頼る言語では出来ないのでアドバンテージではある)

*1:よって、エミュレータ潜在的な構造を検出することで高速化できる。実際、多くのエミュレータはJITCした後のコードをさらに最適化(たとえば不変レジスタロードの省略等)しているが、APIの変換などより踏み込んだ最適化も将来的には可能だろう。