アプリケーション全体でのLinux APIの分析
この記事では、さまざまなアプリケーションでのLinux APIの使用についてレビューし、重要な発見を強調しています。
― 1 分で読む
目次
この記事では、Linux APIがさまざまなアプリケーションでどのように使われているかを見ていくよ。116のアプリケーションを調べて、彼らのニーズや異なる分析手法の比較をしてみたんだ。目的は、分析手法の精度の重要性や、互換性のために必要な機能、アプリケーションの要件が時間とともにどう変わるかについてのいくつかの重要な質問に答えること。
研究質問
主にこの質問に焦点を当てるよ:
- 様々な分析手法の精度はどう比較されるの?特にナイーブな動的分析と静的分析の間で。
- Linux用に互換性レイヤーを作るとき、どのシステムコールを実装する必要があって、どれをフェイクやスタブできる?
- テストスイートが正しく動作するために必要な最小限のコールは?
- アプリケーションで最も一般的に要求されるコールは?
- なぜ特定のコールはフェイクやスタブできるの?それがパフォーマンスやリソース使用に与える影響は?
- アプリケーションやライブラリの要件は時間とともにどう変化するの?
分析手法
主に静的分析とナイーブな動的分析の2つの手法を使ってる。静的分析はコードを実行せずに見る方法で、ナイーブな動的分析はプログラムが動いてる間のコールを追跡する。ナイーブな動的分析は実際に必要なAPIの数を多く見積もっちゃうことが多いんだ。
調べたアプリケーションに基づいて、各APIの重要性を計算したよ。動的分析で呼ばれるけど、スタブやフェイクで置き換えられない場合、そのAPIは必要だと見なされる。結果として、ナイーブ分析とリアルな要件の間にズレがあることがわかった。
静的分析の結果
アプリケーションに対して静的分析を実施して、必要なシステムコールを特定した。ただ、必要なコールの数を過大評価しちゃったりもして、調査したアプリケーションではだいたい20個くらいのコールだけが通常必要ってわかった。静的分析はもっと高い数を報告しがちなんだ。
例えばRedisの場合、静的分析では103のコールが必要って出たけど、動的トレースだと68しか必要なかった。こういうパターンは多くのアプリケーションに当てはまって、コア機能の総合的なサポートが生の静的分析の結果より扱いやすいってことを示してる。
スタブとフェイクへの耐性
システムコールをフェイクやスタブできる能力を分析したところ、相当数のコールが置き換え可能だってわかった。平均して、テストスイートでは約46%、ベンチマークでは60%がスタブやフェイクできるから、人気アプリケーションのコア機能をサポートしやすくなるんだ。
分析では、コールを2つのグループに分類した:一般的に呼ばれるものと、新しい機能に関連するもの。最初のカテゴリのコール、例えば基本的なネットワーク機能などは、より安定していて、しばしば安全にスタブできるんだ。
耐性の理由
アプリケーションは特定のコールが失敗した場合に対処できる仕組みを持ってることが多い。特定の失敗を無視したり、代わりのコールに切り替えたり、問題に直面したときに安全なデフォルト値を使ったりすることがある。この柔軟性のおかげで、特定のシステムコールが利用できなくてもアプリケーションは機能し続けられるんだ。
特定のコールはアプリケーションのコア機能に与える影響が少ない。例えば、getrlimit
が失敗したら、Redisはデフォルト値を設定するだけで動作を止めることはない。ただ、すべてのコールが問題なく置き換えられるわけじゃなくて、プログラムの実行や基本的I/O操作に関連する重要なコールは一般的にスタブやフェイクできない。
戻り値チェックと関係
戻り値をチェックすることがコールのフェイクやスタブできる能力に関係があるかも調べたよ。全体的に、チェックがある多くのAPIもまだスタブやフェイクできるってことで、APIの性質やアプリケーションの挙動が重要な要因だってことがわかった。
パフォーマンスとリソース使用への影響
システムコールのフェイクやスタブがパフォーマンスやリソース使用にどんな影響を与えるかは重要な懸念だ。私たちの研究では、こういった変更は通常、顕著な変動をもたらさないって結果が出た。ほとんどのコールは、フェイクやスタブしてもパフォーマンスに大きな影響を与えないんだ。
ただ、特定のコールはパフォーマンスに良い影響も悪い影響も与えることがあった。例えば、Nginxサーバーで書き込みコールをスタブしたら、不要なログ書き込みを減らしてパフォーマンスが向上した。でも、Redisで同期コールをフェイクしたら、パフォーマンスが大幅に低下して、いくつかのコールは安全に置き換えられないってことが確認できた。
リソース使用への影響
パフォーマンスの影響と同様に、フェイクやスタブによるリソース使用の変化もしばしば最小限だ。私たちの焦点は主に、Nginx、Redis、iPerf3の3つのアプリケーションにあった。リソース消費の変更は微々たるもので、影響を与えるコールはほんの一部だった。
リソース割り当てコールをフェイクした場合、しばしばメモリ使用量が増加したり、オープンファイルディスクリプタが増えたりした。例えば、Redisで特定のメモリ管理コールをフェイクしたら、メモリ消費が増えたけど、コア機能には影響はなかった。
スタブとフェイクの影響評価の重要性
互換性レイヤーを設計する際には、パフォーマンスやリソース使用に対するフェイクやスタブの影響を評価することが重要だ。私たちの研究結果は、大半のコールは重大な結果をもたらさずにフェイクやスタブできることを示してる。ただ、問題が発生した場合は、これらの戦略を実装する前に慎重に考慮する必要があるかもしれない。
パフォーマンスの変化が不安定さから来ているなら、関連するシステム機能はフェイクしない方が良い。逆に、置き換えがアプリケーションにあまり影響しない場合は、目的に応じて許容できるかもしれない。
API関数の部分的実装
これまでの議論ではAPI要素を全体的な機能として扱ってたけど、異なるアプリケーションは複雑なコールの特定の部分しか必要ないことが多い。つまり、フル実装は多くのアプリケーションには必要ないってこと。
例えば、多くのアプリケーションはprctl
コールを必要とするけど、実際にはスレッド管理に関連する特定の機能だけが必要で、すべてのオプションが必要ってわけじゃない。同様に、他の複雑なコールであるioctl
も、アプリケーションごとに頻繁に必要な特定の部分だけがあるんだ。
時間とともに使われる安定性
アプリケーションが発展するにつれて、システムコールの必要性がどう変化するかも調べたよ。私たちの結果は、一度OSがアプリケーションをサポートすれば、そのサポートを維持するのは通常最小限の作業で済むってことを示してる。
新しいバージョンのアプリが出ても、必要なコールのコアセットは安定してる。例えば、Nginxを年単位でいろんなライブラリと見直したとき、必要なコールの変化は最小限だった。こういう安定性は、OSプロトタイプを作る開発者にとっては良い励みになるんだ。
CライブラリのAPI使用への影響
多くのアプリケーションはシステムコールのためにC標準ライブラリ(libc)に依存してる。libcの選択によって、どのAPIが呼ばれるかに大きな影響がある。例えば、glibcはmuslとは異なる関数を呼ぶことがあって、使用にズレが生じるんだ。
libcの初期化コードは、必要なコールを決定する上で重要な役割を果たす。libcの実装によって、必要なコールの順序が大きく異なって、互換性レイヤーのサポートに影響を及ぼすことがある。
正しいCライブラリの選択
libcの選択に基づくAPI使用の顕著な違いを考えると、開発者はOS設計のために単一のライブラリを選ぶ必要がある。この選択は、アプリケーションをサポートするための実装作業を大幅に削減できる。
まとめると、Linux APIは複雑で、互換性レイヤーを作るときには慎重な考慮が必要なんだ。私たちの分析を通じて、多くのAPIはコア機能に影響を与えずに安全にスタブやフェイクできることが分かったし、選択されたlibcがアプリケーションの挙動や要件を形作る上で重要な役割を果たすことも強調できた。
タイトル: Loupe: Driving the Development of OS Compatibility Layers
概要: Supporting mainstream applications is fundamental for a new OS to have impact. It is generally achieved by developing a layer of compatibility allowing applications developed for a mainstream OS like Linux to run unmodified on the new OS. Building such a layer, as we show, results in large engineering inefficiencies due to the lack of efficient methods to precisely measure the OS features required by a set of applications. We propose Loupe, a novel method based on dynamic analysis that determines the OS features that need to be implemented in a prototype OS to bring support for a target set of applications and workloads. Loupe guides and boosts OS developers as they build compatibility layers, prioritizing which features to implement in order to quickly support many applications as early as possible. We apply our methodology to 100+ applications and several OSes currently under development, demonstrating high engineering effort savings vs. existing approaches: for example, for the 62 applications supported by the OSv kernel, we show that using Loupe, would have required implementing only 37 system calls vs. 92 for the non-systematic process followed by OSv developers. We study our measurements and extract novel key insights. Overall, we show that the burden of building compatibility layers is significantly less than what previous works suggest: in some cases, only as few as 20% of system calls reported by static analysis, and 50% of those reported by naive dynamic analysis need an implementation for an application to successfully run standard benchmarks.
著者: Hugo Lefeuvre, Gaulthier Gain, Vlad-Andrei Bădoiu, Daniel Dinca, Vlad-Radu Schiller, Costin Raiciu, Felipe Huici, Pierre Olivier
最終更新: 2023-09-27 00:00:00
言語: English
ソースURL: https://arxiv.org/abs/2309.15996
ソースPDF: https://arxiv.org/pdf/2309.15996
ライセンス: https://creativecommons.org/licenses/by/4.0/
変更点: この要約はAIの助けを借りて作成されており、不正確な場合があります。正確な情報については、ここにリンクされている元のソース文書を参照してください。
オープンアクセスの相互運用性を利用させていただいた arxiv に感謝します。