1. hana_shin

    Posted

    hana_shin
Changes in title
+SystemTapの使い方(その2)
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,381 @@
+#1 はじめに
+systemtapの使い方の続編です。
+
+インストール方法やその他の使い方は、下記を参照ください。
+[SystemTapの使い方](https://qiita.com/hana_shin/items/9b265b4f9a51f98d0f4d)
+[SystemTapの使い方(グルモード編)](https://qiita.com/hana_shin/items/f2806e68493c89fbbef8)
+[SystemTapの使い方(User-Space Probing)](https://qiita.com/hana_shin/items/6bca693206bf5f887cb3)
+
+
+本記事の説明は、説明を簡単にするため、すべて`begin`プローブ内でスクリプトを実行しました。
+`begin`以外の`end`プローブ内や本体の部分で実行できます。
+
+#2 環境
+VMware Workstation 14 Player上の仮想マシンを使いました。
+仮想マシンのOS版数は以下のとりです。
+
+```console:OS版数
+[root@server ~]# cat /etc/redhat-release
+CentOS Linux release 7.6.1810 (Core)
+
+[root@server ~]# uname -r
+3.10.0-95
+```
+
+#3 連想配列(Associative arrays)の使い方
+連想配列とは、添え字にスカラー数値以外のデータ型(文字列型等)も使用できる配列のことです。
+SystemTapの連想配列の構文は、`配列名[インデックス]`になります。
+さらに、インデックスはカンマ区切りで最大9個までの値を指定できます。
+たとえば、`test["Hello"]`や`foo[1,2,3,4,5,6,7,8,9]`のような配列を定義することができます。
+
+
+##3.1 連想配列への値の代入方法、参照方法
+配列testに10、配列fooに20を代入します。
+そして、代入した値を表示してみます。
+
+```console:サンプル
+[root@server ~]# cat tp.stp
+#!/usr/bin/stap
+global test
+global foo
+
+probe begin
+{
+ test["Hello"] = 10
+ foo[1,2,3,4,5,6,7,8,9] = 20
+
+ printf("test=%d,foo=%d\n",test["Hello"], foo[1,2,3,4,5,6,7,8,9])
+ delete test
+ exit()
+}
+```
+
+```console:実行結果
+[root@server ~]# stap tp.stp
+test=10,foo=20
+```
+
+
+
+
+##3.2 連想値(associated value)のインクリメント、デクリメント
+配列testに10、配列fooに20を代入します。
+次に、testは1インクリメント、fooは1デクリメントします。
+そして、連想値を表示してみます。
+
+```console:サンプル
+[root@server ~]# cat tp.stp
+#!/usr/bin/stap
+global test
+global foo
+
+probe begin
+{
+ test["Hello"] = 10
+ foo[1,2,3,4,5,6,7,8,9] = 20
+ printf("test=%d,foo=%d\n",test["Hello"], foo[1,2,3,4,5,6,7,8,9])
+
+ test["Hello"] ++
+ foo[1,2,3,4,5,6,7,8,9] --
+ printf("test=%d,foo=%d\n",test["Hello"], foo[1,2,3,4,5,6,7,8,9])
+
+ delete test
+ exit()
+}
+```
+
+
+```console:実行結果
+[root@server ~]# stap tp.stp
+test=10,foo=20
+test=11,foo=19
+```
+
+##3.3 繰り返しの使い方(foreach)
+
+
+```console:サンプル
+[root@server ~]# cat tp.stp
+#!/usr/bin/stap
+global test
+
+probe begin
+{
+ test[1, "Hello"] = 30
+ test[2, "Hello"] = 10
+ test[3, "Hello"] = 20
+
+ foreach ([a,b] in test) {
+ printf("a=%d,b=%s,test=%d\n",a,b,test[a,b])
+ }
+
+ delete test
+ exit()
+}
+```
+
+
+```console:実行結果
+[root@server ~]# stap tp.stp
+a=1,b=Hello,test=30
+a=2,b=Hello,test=10
+a=3,b=Hello,test=20
+```
+
+
+##3.4 繰り返しの使い方(降順に表示する方法)
+配列testの第1インデックスをキーに降順に連想値を表示してみます。
+降順に表示するため、`[a,b]`を`[a-,b]`に変更します。
+
+```console:サンプル(その1)
+[root@server ~]# cat tp.stp
+#!/usr/bin/stap
+global test
+
+probe begin
+{
+ test[1, "Hello"] = 30
+ test[2, "Hello"] = 10
+ test[3, "Hello"] = 20
+
+ foreach ([a-,b] in test) {
+ printf("a=%d,b=%s,test=%d\n",a,b,test[a,b])
+ }
+
+ delete test
+ exit()
+}
+```
+
+```console:実行結果
+[root@server ~]# stap tp.stp
+a=3,b=Hello,test=20
+a=2,b=Hello,test=10
+a=1,b=Hello,test=30
+```
+
+今度は、配列testの連想値をキーに降順に連想値を表示してみます。
+降順に表示するため、`test`を`test-`に変更します。
+
+```console:サンプル(その2)
+[root@server ~]# cat tp.stp
+#!/usr/bin/stap
+global test
+
+probe begin
+{
+ test[1, "Hello"] = 30
+ test[2, "Hello"] = 10
+ test[3, "Hello"] = 20
+
+ foreach ([a,b] in test-) {
+ printf("a=%d,b=%s,test=%d\n",a,b,test[a,b])
+ }
+
+ delete test
+ exit()
+}
+```
+
+
+```console:実行結果
+[root@server ~]# stap tp.stp
+a=1,b=Hello,test=30
+a=3,b=Hello,test=20
+a=2,b=Hello,test=10
+```
+
+##3.5 連想配列がキーを持つかどうかを判定する方法
+
+```console:サンプル
+[root@server ~]# cat tp.stp
+#!/usr/bin/stap
+global test
+
+probe begin
+{
+ test[1, "Hello"] = 30
+ test[2, "Hello"] = 10
+ test[3, "Hello"] = 20
+
+ if([1,"Hello"] in test)
+ printf("1000\n")
+ if([2,"Hello"] in test)
+ printf("2000\n")
+ if([3,"Hello"] in test)
+ printf("3000\n")
+
+ delete test
+ exit()
+}
+```
+
+```console:実行結果
+[root@server ~]# stap tp.stp
+1000
+2000
+3000
+```
+
+
+
+
+#4 統計集計 (Statistical Aggregates) の使い方
+統計集計に値を追加するには、演算子`<<<`を使用します。
+
+
+##4.1 個数を求める方法(`@count`)
+配列testに10を代入してみます。
+
+```console:スクリプト(個数が1個の場合)
+[root@server ~]# cat tp.stp
+#!/usr/bin/stap
+global test
+
+probe begin
+{
+ test[100] <<< 10
+ printf("count=%d\n", @count(test[100]))
+ delete test
+ exit()
+}
+```
+
+```console:実行結果
+[root@server ~]# stap tp.stp
+count=1
+```
+
+
+配列testに10と20を代入してみます。
+
+```console:スクリプト(個数が2個の場合)
+[root@server ~]# cat tp.stp
+#!/usr/bin/stap
+global test
+
+probe begin
+{
+ test[100] <<< 10
+ test[100] <<< 20
+ printf("count=%d\n", @count(test[100]))
+ delete test
+ exit()
+}
+```
+
+```console:実行結果
+[root@server ~]# stap tp.stp
+count=2
+```
+
+##4.2 最小(`@min`)、最大(`@max`)、平均(`@avg`)、合計(`@sum`)、を求める方法
+
+```console:スクリプト
+[root@server ~]# cat tp.stp
+#!/usr/bin/stap
+global test
+
+probe begin
+{
+ test["hello"] <<< 10
+ test["hello"] <<< 20
+ test["hello"] <<< 30
+
+ printf("count=%d,min=%d,max=%d,avg=%d,sum=%d\n",
+ @count(test["hello"]),
+ @min(test["hello"]),
+ @max(test["hello"]),
+ @avg(test["hello"]),
+ @sum(test["hello"])
+ )
+ delete test
+ exit()
+}
+```
+
+
+```console:実行結果
+[root@server ~]# stap tp.stp
+count=3,min=10,max=30,avg=20,sum=60
+```
+
+
+#5 ヒストグラフの描き方( Histogram extractors)
+ヒストグラムの書き方を以下に示します。
+
+##5.1 hist_linearの使い方(`@hist_linear`)
+
+```console:スクリプト
+[root@server ~]# cat tp.stp
+#!/usr/bin/stap
+global test
+
+probe begin
+{
+ test <<< 100
+ test <<< 110
+ test <<< 700
+ print(@hist_linear(test, 0, 1000, 50))
+ delete test
+ exit()
+}
+```
+
+```console:実行結果
+[root@server ~]# stap tp.stp
+value |-------------------------------------------------- count
+ 0 | 0
+ 50 | 0
+ 100 |@@ 2
+ 150 | 0
+ 200 | 0
+ ~
+ 600 | 0
+ 650 | 0
+ 700 |@ 1
+ 750 | 0
+ 800 | 0
+```
+
+##5.2 hist_logの使い方(`@hist_log`)
+
+
+```console:スクリプト
+[root@server ~]# cat tp.stp
+#!/usr/bin/stap
+global test
+
+probe begin
+{
+ test <<< 100
+ test <<< 110
+ test <<< 700
+ print(@hist_log(test))
+ delete test
+ exit()
+}
+```
+
+
+```console:実行結果
+[root@server ~]# stap tp.stp
+value |-------------------------------------------------- count
+ 16 | 0
+ 32 | 0
+ 64 |@@ 2
+ 128 | 0
+ 256 | 0
+ 512 |@ 1
+ 1024 | 0
+ 2048 | 0
+```
+
+
+
+
+#Z 参考情報
+[3.5. SYSTEMTAP でのアレイ演算](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/systemtap_beginners_guide/arrayoperators)
+[SystemTap Language Reference](https://sourceware.org/systemtap/langref.pdf)
+[mmitouの日記](https://mmitou.hatenadiary.org/entry/20120721/1342879187)
+[SystemTap 3.2 SystemTap Beginners Guide](https://lrita.github.io/images/posts/systemtap/SystemTap_Beginners_Guide.pdf)