3.5. SystemTap でのアレイ演算
3.5.1. 関連する値の割り当て
= を使います。
array_name[index_expression] = value
index_expression と value の両方として使用することもできます。たとえば以下のように、アレイを使用して、タイムスタンプをプロセス名 (これを一意の鍵として使用) への関連する値として設定することができます。
例3.12 タイムスタンプをプロセス名に関連付ける
arr[tid()] = gettimeofday_s()
tid() 値 (つまり、スレッドの ID。これは一意の鍵として使用されます) を返します。同時に SystemTap は関数 gettimeofday_s() を使って、対応するタイムスタンプを関数 tid() で定義されている一意の鍵への関連する値として設定します。これで、スレッド ID とタイムスタンプを含む鍵のペアで構成されるアレイが作成されます。
tid() がアレイ arr で既に定義されている値を返すと、この演算はその値に関連付けられている元の値を破棄し、gettimeofday_s() からの現行タイムスタンプで置き換えます。
3.5.2. アレイからの値の読み取り
array_name[index_expression] ステートメントを数式に要素として含めます。例を示します。
例3.13 単純計算でのアレイ値の使用
delta = gettimeofday_s() - arr[tid()]
arr が構築されていることを想定しています。これで 参照ポイント となるタイムスタンプが設定され、delta の計算に使用されます。
gettimeofday_s() から鍵 tid() の関連する値を差し引くことで変数 delta の値を計算します。このコンストラクトは、tid() の値をアレイから読み取る ことで計算を行います。このコンストラクトは、読み取り操作の開始と完了など、2 つのイベント間の時間を判定する際に便利なものです。
注記
index_expression が一意の鍵を見つけられない場合は、0 の値 (例3.13「単純計算でのアレイ値の使用」 の場合など、数値演算) もしくは null (空) の文字列の値 (文字列の演算の場合) がデフォルトで返されます。
3.5.3. 関連する値の増加
++ を使用します。
array_name[index_expression] ++
index_expression にハンドラー関数を使用できます。たとえば、仮想ファイルシステムへの読み込み (vfs.read イベントを使用) を特定のプロセスが実行した回数を計算したい場合は、以下のプローブを使用します。
例3.14 vfsreads.stp
probe vfs.read
{
reads[execname()] ++
}
gnome-terminal を返す際 (つまり、gnome-terminal が初めて VFS 読み込みを実行する際)、そのプロセス名は一意の鍵 gnome-terminal に関連する値 1 が付いたものになります。プローブがプロセス名 gnome-terminal を次に返す際には、SystemTap は gnome-terminal の関連する値を 1 増やします。SystemTap は、プローブがプロセス名を返す際にこの演算をすべてのプロセス名に対して実行します。
3.5.4. アレイ内での複数要素の処理
reads アレイで鍵のペアをプリントすることです。
foreach ステートメントを使用することです。以下の例を見てみましょう。
例3.15 cumulative-vfsreads.stp
global reads
probe vfs.read
{
reads[execname()] ++
}
probe timer.s(3)
{
foreach (count in reads)
printf("%s : %d \n", count, reads[count])
}
foreach ステートメントが count 変数を使用して reads アレイ内の一意の鍵の反復を参照しています。同じプローブ内の reads[count] アレイステートメントは、一意の鍵の関連する値を取得します。
foreach ステートメントは、順不同でアレイ内のプロセス名の 全 反復をプリントすることに注意してください。+ (昇順) または - (降順) を使用すると、スクリプトに特定の順番で反復をプロセスするよう指示することができます。さらに、limit value オプションを使うと、スクリプトがプロセスする反復数を制限することもできます。
probe timer.s(3)
{
foreach (count in reads- limit 10)
printf("%s : %d \n", count, reads[count])
}
foreach ステートメントは、スクリプトにアレイ reads 内の要素を (関連する値の) 降順で処理するよう指示します。limit 10 オプションは、foreach に最初の 10 の反復のみを処理するよう指示します (つまり、値の高い上位 10 位の反復のみをプリントします)。
3.5.5. アレイおよびアレイ要素の消去/削除
delete 演算子を使ってアレイ内の要素またはアレイ全体を削除すると、これが実行できます。以下の例を見てみましょう。
例3.16 noncumulative-vfsreads.stp
global reads
probe vfs.read
{
reads[execname()] ++
}
probe timer.s(3)
{
foreach (count in reads)
printf("%s : %d \n", count, reads[count])
delete reads
}
delete reads ステートメントは、プローブ内の reads アレイを消去します。
注記
global reads, totalreads
probe vfs.read
{
reads[execname()] ++
totalreads[execname()] ++
}
probe timer.s(3)
{
printf("=======\n")
foreach (count in reads-)
printf("%s : %d \n", count, reads[count])
delete reads
}
probe end
{
printf("TOTALS\n")
foreach (total in totalreads-)
printf("%s : %d \n", total, totalreads[total])
}
reads と totalreads のアレイが同じ情報を追跡し、同様の方式でプリントします。唯一の違いは、reads は 3 秒ごとに消去されるのに対して、totalreads は増え続けるという点です。
3.5.6. 条件付きステートメントにおけるアレイの使用
if ステートメントでも使用することができます。これは、アレイ内の値が特定の条件に一致した場合にサブルーチンを実行するという場合に便利です。以下の例を見てみましょう。
例3.17 vfsreads-print-if-1kb.stp
global reads
probe vfs.read
{
reads[execname()] ++
}
probe timer.s(3)
{
printf("=======\n")
foreach (count in reads-)
if (reads[count] >= 1024)
printf("%s : %dkB \n", count, reads[count]/1024)
else
printf("%s : %dB \n", count, reads[count])
}
if ステートメントがこれを変換し、kB でプリントします。
if([index_expression] in array_name) statement
例3.18 vfsreads-stop-on-stapio2.stp
global reads
probe vfs.read
{
reads[execname()] ++
}
probe timer.s(3)
{
printf("=======\n")
foreach (count in reads+)
printf("%s : %d \n", count, reads[count])
if(["stapio"] in reads) {
printf("stapio read detected, exiting\n")
exit()
}
}
if(["stapio"] in reads) ステートメントは、一意の鍵 stapio がアレイ reads に追加されたら stapio read detected, exiting をプリントするようにスクリプトに指示します。
3.5.7. 統計集計 (Statistical Aggregates) の計算
<<< value を使用します。
例3.19 stat-aggregates.stp
global reads
probe vfs.read
{
reads[execname()] <<< count
}
<<< count が、reads アレイ内の対応する execname() の関連する値に count が返した数字を保存します。これらの値は 保存されるのであって、各一意の鍵の関連する値に追加されたり、現行の関連する値に置き換わるものではありません。各一意の鍵 (execname()) に複数の関連する値があり、ハンドラーが実行するプローブで累積していると考えればよいでしょう。
注記
@extractor(variable/array index expression) という構文書式を使用します。extractor は以下の整数抽出のいずれかにします。
- count
- variable/array index expression に保存されたすべての値の数を返します。例3.19「stat-aggregates.stp」 のサンプルプローブでは、
@count(writes[execname()])の式は、アレイwritesの各一意の鍵に保存されている値の数を返します。 - sum
- variable/array index expression に保存されたすべての値の合計を返します。例3.19「stat-aggregates.stp」 のサンプルプローブでは、
@sum(writes[execname()])の式は、アレイwritesの各一意の鍵に保存されている値すべての合計を返します。 - min
- variable/array index expression に保存されているすべての値で最も小さいものを返します。
- max
- variable/array index expression に保存されているすべての値で最も大きいものを返します。
- avg
- variable/array index expression に保存されているすべての値の平均を返します。
例3.20 複数のアレイインデックス
global reads
probe vfs.read
{
reads[execname(),pid()] <<< 1
}
probe timer.s(3)
{
foreach([var1,var2] in reads)
printf("%s (%d) : %d \n", var1, var2, @count(reads[var1,var2]))
}
reads が収集した情報を処理してプリントする方法を示しています。foreach ステートメントは、最初のプローブのアレイ reads の最初のインスタンスに含まれる変数 (var1 および var2) と同じ数を使用している点に注意してください。

Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.