今回は、Linuxのアプリケーションをターゲットとして、「ファイル書き出し」接続のオーバーヘッドについて検証します。
動的テストツールDT10(以下、DT10)は、Linuxを搭載したターゲットのアプリケーション層のトレースデータを取得できるだけでなく、デバイスドライバの実行経路や処理時間、プロセス・スレッドの遷移状態および占有率などカーネル層のトレースデータも同時に取得ができて、システム全体のソフトウェアの動きを俯瞰し、ステップ単位での詳細な動きまでを把握できるようになります。製品の分野を問わず、Linux搭載機器の開発において、DT10が広く採用される理由はここにあります。

DT10を活用する際にポイントとなるのは、トレースデータを出力する時のオーバーヘッドです。アプリケーション層とカーネル層を同時にトレースすることを考えると、カーネル層のデバイスドライバでは、特に時間的にシビアな処理を求められることが多いと思います。比較的オーバーヘッドが小さく、導入時の手間が掛からないため、特に「ファイル書き出し」接続をDT10で使用するユーザー様が多いです。

今回は、その「ファイル書き出し」接続において、さらにオーバーヘッドを小さくできないかを検証しました。

 

オーバーヘッドの違いを検証

 
DT10用のデバイスドライバについて

カーネル層の処理からトレースデータを出力する際に、カーネル層からファイルIOの操作はできません。では、アプリケーション層とカーネル層のトレースデータの取得をどのようにして両立しているのか?DT10用のデバイスドライバでは、どちらのトレースデータも一度カーネル層の内部メモリに貯めておくという方法を取っています。

アプリケーション層からもこのカーネル層で確保された内部メモリにアクセスしなければなりませんが、アプリケーション層からは、このメモリに直接アクセスはできません。そこで、弊社で提供するサンプルのDT10用のデバイスドライバにおいては、procファイルシステムを使用して、このメモリにアクセスをしています。

図1 トレースデータを内部共有メモリに貯める

最終的にこの内部メモリのデータはサンプルドライバに付属している簡易アプリケーションによってファイル化され、ログデータとして保存されるといった仕組みです。

図2 トレースデータのファイル出力

 
検証した処理

「ファイル書き出し」接続において、オーバーヘッドを小さくするためにはどうしたら良いのか?
それはトレースデータを貯める内部メモリにアクセスする時間を小さくするということになります。この検証では、アプリケーション層のトレースデータ出力時にカーネル層のメモリにアクセスする仕組みを以下のように変更することで、テストポイントの出力処理にかかる時間、つまり、それらの仕組みにおいて、メモリに対してアクセスする時の処理時間がどのように変化するのかを計測します。

1)procファイルシステム(以下、procfs)
⇒ write
2)デバイスファイル(以下dev)
⇒ write
3)debugファイルシステム(以下、debugfs)
⇒ write
4)システムコール(以下、syscall)

 
テスト条件

▼ターゲットのコード
アプリケーション層で以下のプログラムを実行したときに、赤色で表示されているテストポイントが実行されます。

▼オーバーヘッドの計測方法
・上の図のターゲットのソースコードに連続した2つのテストポイントをトレースした時の差分時間をDT10アプリで計測します。
・ターゲットのソースコードを実行し、DT10アプリの「2点間実行時間レポート」を計測結果とします。
・時間データは、テストポイントによる通過情報の出力時にドライバ側で付加します。”getnstimeofday”関数を使用しています。

▼検証したターゲットのスペック
 ・ターゲットボード:Armadillo-440 ( ARM9プロセッサ搭載ボード/株式会社アットマーク・テクノ社製)
プロセッサ:Freescale i.MX257
CPUコア: ARM926EJ-S
CPUコアクロック: 400MHz
バスクロック: 133MHz
RAM: 128MB(LPDDR SDRAM)
Flash ROM 32MB(NOR型)
・OS:Linux2.6-26

 

検証結果

 
syscallが最速

最もオーバーヘッドが小さいのは、syscallを使用した場合でした。平均時間ではprocfsに比べて、オーバーヘッドが2usも小さくなっていることが分かります。次いで、debugfsが小さい値を示しています。一方、devは最もオーバーヘッドが大きいという結果になりました。
オーバーヘッドが最小となったsyscallとほかの仕組みとの大きな違いは、データ出力時の処理(手続き)の数が大きく異なる、という点です。データ出力時にデバイスドライバで”write”関数が呼び出されますが、どのデバイスドライバのものか、OS内部で判別が行われた上で、メモリへと書き込まれます。システムコールではそのような処理を経ることなく、メモリに値を書き込むことになるため、オーバーヘッドは他と比べて、より小さいという結果になります。

 
syscall使用時のトレードオフ

この検証データだけ見るとsyscallに大きなアドバンテージがあるように思いますが、DT10用のシステムコールを登録するなどCPUに依存するセットアップなどが必要で、ファイル書き出しの導入の容易さという利点をある程度犠牲にしている側面もあります。他の仕組みにおいては、DT10用のデバイスドライバだけをカスタマイズすれば容易に使用することができます。

 

まとめ

Linuxでの「ファイル書き出し」接続においては、syscallを使って速度を優先するのか、導入の容易さを確保するために今回検証した他の仕組みにするのか、何を優先するかよって、ベターな選択があるということが分かりました。
今回の検証に関連して、弊社ではsyscallを使用したドライバを公開しています。チュートリアル(ユーザー様限定のページです)も公開しておりますので、ぜひ参考にしていただきたいと思います。

Linuxでオーバーヘッドが削減できるsyscallを使ったドライバ

・ 従来のデバイスドライバを使うサンプルドライバよりも、オーバーヘッドを削減できます。
・ テストポイントを挿入したアプリが、ファイルアクセス権限によって、procファイルへアクセスできないシステムでも使えます。
※サポートサイト。ログインが必要です。

チュートリアル、サンプルドライバのダウンロードはこちら