/proc/interruptsに関するメモ
この記事はぴょこりんクラスタ:Re Advent Calendar 2016 - Adventarのために書いたものです。
サマリ
特に意味もなくLinuxの/proc/interruptsのアルファベット3文字の項目について説明する。
割り込みとは何か
処理を強制的に切り替える信号のようなもの。例えばキーボードのように、 入力に対する処理に即時性が必要だけど、全力でポーリングするのには割に合わないものに使われている。 ドライブやEthernetへのI/Oも普通は割り込みで動くんだけど(常にI/Oするわけじゃないし)、 なお、全力でポーリングすることでI/O性能を最大限出そうというのがSPDKとかDPDKっていうやつね。
割り込みが上がってくると、OSが割り込みの種類に合わせて処理をする。この処理のことを割り込みハンドラと呼ぶ。 割り込みハンドラはベクタと呼ばれるテーブルでOSのカーネルが管理している。 どのIRQ*1で 上がってきたら何番のベクタに登録されてるハンドラを使う、という運用になっている。
Linuxでの割り込みの取り扱い
各割り込みに仮想的なIRQを割り当ててハンドラを管理している。何でこんな複雑なことをするかというと、 多分このへんの理由なんだろうなと思う。あくまで思うだけで正解はわからない・・・
- 割り込みベクタの数が限られているから(たった255しかない)
- 同じベクタで複数のハンドラを動かしたいから(1つのベクタに対しては1つのハンドラしか登録できない)
で、/proc/interruptsとは何ですかね
Linuxにおいて、どういう割り込みがどれだけ上がっているかを調べられる特殊なファイルのこと。
/proc/interruptsの例
Virtualboxに入れたCentOSから見たときの/proc/interruptsはこんな感じ。 先頭列が数字のものとアルファベット3文字のがあるのがわかると思う。 数字はLinuxが管理している仮想的なIRQ番号を示していて、 アルファベット3文字のものはちょっと特別なやつを示している。 特別といってもハードウェア的には割り込みの上げ方に差はなくて、 特別なIRQが割り当てられているとか、特別なベクタが割り当てられているとかです。
/home/bisco/work/mem% cat /proc/interrupts CPU0 0: 127 IO-APIC-edge timer 1: 10 IO-APIC-edge i8042 8: 1 IO-APIC-edge rtc0 9: 0 IO-APIC-fasteoi acpi 12: 155 IO-APIC-edge i8042 14: 0 IO-APIC-edge ata_piix 15: 8285 IO-APIC-edge ata_piix 19: 42955 IO-APIC-fasteoi enp0s3 20: 3 IO-APIC-fasteoi vboxguest 21: 0 IO-APIC-fasteoi snd_intel8x0 23: 0 IO-APIC-fasteoi ohci_hcd:usb1 24: 14746 PCI-MSI-edge 0000:00:1f.2 NMI: 0 Non-maskable interrupts LOC: 281405 Local timer interrupts SPU: 0 Spurious interrupts PMI: 0 Performance monitoring interrupts IWI: 5644 IRQ work interrupts RTR: 0 APIC ICR read retries RES: 0 Rescheduling interrupts CAL: 0 Function call interrupts TLB: 0 TLB shootdowns TRM: 0 Thermal event interrupts THR: 0 Threshold APIC interrupts DFR: 0 Deferred Error APIC interrupts MCE: 0 Machine check exceptions MCP: 28 Machine check polls ERR: 0 MIS: 0 PIN: 0 Posted-interrupt notification event PIW: 0 Posted-interrupt wakeup event
アルファベット3文字のものについてざっくりとした解説
NMI:割り込みの世界では受取拒否のことを「割り込みをマスクする」と言うんだけど、文字通り受取拒否ができないもの。 0除算とかページフォルトとか、そういう緊急事態に上がってくる割り込み。
LOC:タイマ割り込み。それっぽい言葉でtickと言って、OSが時間管理に使う割り込みのこと。タイマで定期的に割り込みを上げてもらって、 時限処理とか、プロセスのスケジューリングをやったりする。割り込みを上げるのはLocal APICとTSCの組み合わせであったり、 HPETやらACPIやらのCPU外のデバイスについてる時計だったりする。昨今はLocal APICとTSCの組み合わせでやることが多い。
SPU:割り込み発生元がわからない割り込みのこと。(たぶん)ハードウェアが壊れたときとか設定を間違えたときに上がる割り込み。
PMI:Intel CPUにはPerformance Counter(PMC)を積んでるものがあって、クロック数やらキャッシュミス回数をカウントしてくれる。 そのカウンタが一定以上になったときに割り込みを上げる機能があって、それのこと。
IWI:割り込みハンドラを動かしているときは、CPUはちょっと特別なモードになっているんだけど、その特別なモードで割り込みじゃない処理を動かしたい ときがある*2。そのときにカウントされるのがこれ。 自分で自分に割り込み*3を打ち込んで動かすようである。
// Linux/arch/x86/kernel/irq_work.c 35 void arch_irq_work_raise(void) 36 { 37 #ifdef CONFIG_X86_LOCAL_APIC 38 if (!arch_irq_work_has_interrupt()) 39 return; 40 41 apic->send_IPI_self(IRQ_WORK_VECTOR); ★これ 42 apic_wait_icr_idle(); 43 #endif 44 }
- RTR:割り込みを上げようとして、Local APIC*4の ICR(Interrupt Command Register)を読んだときにbusyが返ってきたらリトライするんだけど、そのbusyが返ってきた回数をカウントしてる項目。 これ割り込みじゃないっぽいんだよなー。なお、このルートに入るのはNMI指定でIPIを投げつけたとき*5に限る。
// http://lxr.free-electrons.com/source/arch/x86/kernel/apic/apic.c#L250 250 u32 native_safe_apic_wait_icr_idle(void) 251 { 252 u32 send_status; 253 int timeout; 254 255 timeout = 0; 256 do { 257 send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; 258 if (!send_status) 259 break; 260 inc_irq_stat(icr_read_retry_count); ★ここでRTRがカウントされる 261 udelay(100); 262 } while (timeout++ < 1000); 263 264 return send_status; 265 }
RES:他のコアへスケジューリング要求を出すときの割り込み。
CAL:他のコアに何か関数コールしてほしいときに上げる割り込み。
TLB:TLB Shootdown*6のための割り込み。 特別枠になってるけど、実装はCALと同じでFunction Call Interruptsになっている。
TRM:CPUの温度が上がりすぎてるときに上がる割り込み。
THR:コレクタブルなエラー*7が発生したときに上がる割り込み
DFR:何かエラーが発生して、ハードウェアは何とかできなかったけど、ソフトウェアで何かする必要はないときに上がる割り込み。
MCE:Machine Check Exception。とにかくやばい障害。
MCP:定期的にMachine Checkが発生していないかを調べる割り込み。デフォルト5分だったかな。
ERR:Local APIC自体の障害
MIS:IOAPICの障害
PIN/POS:VMならではのもの。VMが割り込みを発生させるだけさせといて、VT-dが処理を遅らせたときに発生するようなやつ。
まとめ
Linuxの/proc/interruptsの、特にアルファベット3文字のものについて調べた。 わからない項目があっても、最悪ソースを読めばわかるというのはオープンソースのありがたいところですね。
今年読んだ本を振り返る
この記事はぴょこりんクラスタ:Re Advent Calendar 2016 - Adventarのために書いたものです。
サマリ
- ベスト本は失敗の本質
- ベスト漫画は東京喰種 re:。特別枠としてARIA。
良かった本(非漫画)とひとくちメモ
失敗の本質
- 思いつく限りの、俗に言う大企業の悪いところが網羅された本。僕たち(というか僕たちよりも上の世代だと思うけど)は60年以上たった今でも何も変わっていないことがわかる。多分自分もそのうち感化されてしまうので、これを定期的に読み返して心に釘をささねばという気持ちにさせられた本だった。読むのに体力を使うので来年かな・・・*1
- 今年のベスト
大本営参謀の情報戦記―情報なき国家の悲劇
- 失敗の本質とセットでどうぞ。この戦時中からの変わらなさは絶望であるけれど、問題がはっきりしているという点ではいいのかもしれない。
この世界が消えたあとの科学文明のつくりかた
- リアル北斗の拳状態になったあとで、どうやって生き延びて、どうやって文明レベルを戻していくかを書いた本。これ読んでると自分でだいたい何でもできそうな気がしてくるけどきっと気のせい。なお、冷静に考えると文明がなくなったあとで生きていける気はしなかった。。。
- いちばん印象に残っているのは、今食べてる農作物は実はそのまま種にできないということと(理由は忘れた)、種子バンクというものが世の中にはあって、ものすごく厳重に管理されているということだった。毎年祖父が苗やら種やら買ってるのが不思議でならなかったけど、そういうわけかと納得した覚えがある。
スティル・ライフ
- どことなく漂う他人事感というか、村上春樹とは違ったドライですっきりな感じが印象に残っている。1度読んだきりなのでうろ覚え。もう1度読まねば。
カエアンの聖衣
- キルラキルの原作(らしい)。服(というか服を作っている繊維)が意思を持っていて、着た人間を乗っ取ってしまうというお話。アニメをほとんどみない僕だけど、キルラキルは大変楽しく見られたし、このカエアンの聖衣も大変楽しく読めた。
コンテナ物語(まだ読んでる途中)
- コンピュータの世界でもコンテナが当たり前になりつつあるけれど、これは実世界のコンテナの話。コンテナがどのように始まって、どのように広がったかはもちろん、コンテナを中心に世界がどのように変わっていったかを書いた本。コンテナの拡大により仕事を失うことを恐れた沖仲仕(荷降ろしとかする人のこと)が、コンテナの拡大をなんとか防ごうと、ロビー活動したり組合活動したりストライキしたりしてがんばるシーンがあるんだけど(もちろん最後はコンテナが勝ってしまうが)、身近に似たようなことがあったのであまり笑えなかった。
闘うプログラマー ビル・ゲイツの野望を担った男達
- Windows 95を作ったときの話。すごいものはすごい天才からしか生まれないという厳しい現実を感じた。
ピープルウエア、ビジョナリーカンパニー、HARD THINGS
- この辺は面白かったのは覚えているけど、すでに記憶がおぼろげになっている。
正法眼蔵随聞記
- 「世を捨てたからといって、汚い身なりをしていいと思ったら大間違いだ。人並みに身なりに気を使え」という話があってびっくりした。
- 気分が沈んだときにこれを読むと、元気は出ないがあきらめに似た気持ちで前向きになれるのでよい。
- 全部が全部いい話かというとそういうわけでもなく、よくわからん話もけっこうある。
良かった本(漫画)
東京喰種 re:
- 「ハイルと食べたメロンパンはおいしかった」、このセリフの悲しさがたまらなく好き。
- だんだんと変わっていく初代Qsを見ていると心臓が鷲掴みされたような、そんな気持ちになる。
ARIA
- 僕はこれを読んで文字通り泣いてしまったわけだけど、何で泣いたかいまだによくわかっていない。
さびしすぎてレズ風俗に行きましたレポ
- 服装に気を使うようになったきっかけその2。自分は大切にしよう。
*1:これが悪いところかもしれない
英語の勉強代わりに見てみようと思ってるサイト
この記事はぴょこりんクラスタ:Re Advent Calendar 2016 - Adventarのために書いたものです。
サマリ
大学の授業がインターネットで見られるなんていい時代になった。
今日は力尽きたのでこのへんで・・・
CoreOSで遊ぶ(その2:特に意味もなくPukiwiki環境を作る)
この記事はぴょこりんクラスタ:Re Advent Calendar 2016 - Adventarのために書いたものです。
サマリ
はじめに
コンテナ連携ごっこがしたかったので、pukiwikiを動かすという名目で httpサーバ用コンテナとphp実行用コンテナを分けて動かしてみた*1。
単に動かしてみるところまで
使ったイメージはもちろんalpine linuxをベースにしている公式イメージで、とにかくサイズが小さいのがジャスティス。 楽をしたいならphp:apacheというDebianベースのイメージを使ったほうがよい。何よりはまらないしね。
ディレクトリのバインドはnginxコンテナとfpm-php両方にやる必要がある(当然ぽいけど僕ははまった)。 *.phpの要求が来る→fpm-phpコンテナに向かって要求を飛ばす→fpm-phpコンテナが要求を実行して結果を返す→nginxがレスポンスを返す、という流れですね。
$ docker run -v /home/bisco/pukiwiki:/var/www/html/wiki --name fpm-php -h fpm-php -d php:fpm-alpine $ docker run -v /home/bisco/pukiwiki:/var/www/html/wiki --name nginx -h nginx --link fpm-php:php -p 80:80 -d nginx:alpine
docker runするだけじゃダメで、nginx側に設定が追加で必要がある。
# alpine linuxのシェルは/bin/ash $ docker exec -it nginx /bin/ash $ cd /etc/nginx.conf/conf.d/ $ vi server.conf
server.confはこれ。fastcgi_pass php:9000
のphp
のところは、--linkで指定した名前を書く。
server { listen 80 default; server_name _; root /var/www/html; index index.php index.html index.htm; charset utf-8; access_log off; error_log off; location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
設定書いたら一応リスタートさせておく。
$ docker restart nginx
手作業でphpinfo.phpを放り込んでから、ブラウザでアクセスしてみると、うまく行ってればいつもの画面が表示されるはず。
$ docker exec -it fpm-php /bin/ash $ echo "<?php phpinfo(); ?>" > /var/www/html/index.php
phpの動作が確認できたら、pukiwiki.ini.phpの修正とcacheファイルの権限を CoreOSから変えておく。
# autoだとちゃんと認識できないのでURLを入れる。 $ vi pukiwiki.ini.php // Specify PukiWiki URL (default: auto) $script = 'http://xxx.xxx.xxx.xxx/wiki/'; // cache以下のファイルがライトできなかったので777にしておく $ sudo chmod 777 cache/*
この面倒な作業を全部勝手にやってほしい
docker-composeを使おう!!!
手順はこう。
- docker-composeをインストールする
- Dockerfileを作る
- docker-compose.yamlを作る
- docker-compose up -d
docker-composeのインストール
CoreOSにdocker-composeを導入 - Qiita に全部書いてあるのでコマンド履歴だけ。
$ mkdir -p /opt/bin $ curl -L https://github.com/docker/compose/releases/download/1.9.0/docker-compose-`uname -s`-`uname -m` > /opt/bin/docker-compose $ chmod +x /opt/bin/docker-compose $ docker-compose version docker-compose version docker-compose version 1.9.0, build 2585387 docker-py version: 1.10.6 CPython version: 2.7.9 OpenSSL version: OpenSSL 1.0.1t 3 May 2016
Dockerfileとかdocker-compose.yamlを作る
ディレクトリ構成をこうしてファイルを作る。
- ./
- docker-compose.yaml
docker-compose.yaml。imageを指定すると、buildしたイメージに名前がつけられる。
linkに指定する
version: '2' services: fpm-php: build: ./fpm-php image: fpm-php-sandbox container_name: fpm-php volumes: - /home/bisco/pukiwiki:/var/www/html/wiki nginx: build: ./nginx image: nginx-sandbox container_name: nginx ports: - 80:80 links: - fpm-php:php volumes: - /home/bisco/pukiwiki:/var/www/html/wiki
fpm-php/Dockerfile
FROM php:fpm-alpine COPY index.php /var/www/html
<?php phpinfo();?>
nginx/Dockerfile
FROM nginx:alpine ADD server.conf /etc/nginx/conf.d/server.conf
nginx/server.conf
server { listen 80 default; server_name _; root /var/www/html; index index.php index.html index.htm; charset utf-8; access_log off; error_log off; location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
docker-compose up -d
あとは何も考えずコマンドを実行すれば動いてくれる。
$ docker-compose up -d
CoreOSで遊ぶ(その1:とりあえずインストール)
この記事はぴょこりんクラスタ:Re Advent Calendar 2016 - Adventarのために書いたものです。
サマリ
Chinachu + Mirakurunをコンテナで入れられることにいたく感動したので、 コンテナの勉強をするべくCoreOSを入れて遊んでみたという話。
CoreOSとは何か
コンテナを動かすためだけのLinuxディストリビューション。 アプリケーションは基本的にコンテナに放り込んで動かすという思想の元、 OS自体をものすごく薄くしたもの、だと思う。
まだあまりよくわかってないけど、ほぼ全部コンテナで動くということは、 面倒なバージョン依存地獄から解放されるんだという期待で膨らみますね。
遊んでいる環境
Windows上のVirtualboxにCoreOSを入れている。
- Windows 10 Pro (x64)
- Virtualbox 5.1.10
- CoreOS(Beta Channel)
インストール
まずはじめに、ISOファイルをhttps://coreos.com/os/docs/latest/booting-with-iso.htmlから落としてくる。 VirtualboxにはもちろんCoreOS用の設定はないので、Other Linux(64bit)を選び、メモリを1GB以上にする。
立ち上げると普通にコンソールが出てくるので、公式のInstalling to Diskに従い、インストールすればOK。 Virtualboxの画面からやろうとすると、英語配列キーボードのせいでやりにくくて仕方ない上にキー配列が変えられないので、 PuTTYとかからsshしたほうが楽でよい。
$ sudo passwd core # デフォルトユーザは"core"なので、coreのパスワードを設定してやるとsshで入れる $ ifconfig # IP確認して、以後sshクライアントからログインして実施 $ sudo su - $ vi cloud-config.yaml $ coreos-install -d /dev/sda -c cloud-config.yaml -C beta #せっかくなのでbetaくらい入れてみる。alphaを入れる度胸はなかった。
cloud-config.yamlは最低限ssh_authorized_keysを設定しておけばいいんだけど、ユーザくらいは追加しておくようにする。 ユーザも最低限groupと公開鍵さえ登録しておけばいいと思う。パスワードは公開鍵登録しておけば不要。
先頭行の#cloud-config
はおまじないで、これがないと受け入れてもらえないので注意。あと、よく先頭の-
を忘れるので注意。
#cloud-config ssh_authorized_keys: - ssh-ed25519 ...... users - name: "bisco" groups: - "docker" - "sudo" ssh-authorized-keys: - "ssh-ed25519 ....."
インストールが終わると、リブートして再度立ち上がってくる。ISOファイルを外すのを忘れやすいし、現に僕は忘れてた*1。
Hello Worldする
動作確認といえばHello Worldだよね。ダウンロード時間が短くてすむbusyboxコンテナでHello Worldしてみよう。 手元にイメージがなくても、勝手にstore.docker.com(たぶん・・・)から落としてきてくれるので、気にせずrunすればいい。
bisco@core ~ $ docker run busybox /bin/echo "hello world" Unable to find image 'busybox:latest' locally latest: Pulling from library/busybox 56bec22e3559: Pull complete Digest: sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912 Status: Downloaded newer image for busybox:latest hello world
なお、原則として、Dockerコンテナ1つにつき1プロセスしか動けないので、サービスを複数動かそうとすると失敗する。 複数プロセス動かすときはsupervisordとかいれる必要がある。
次は?
これだけだとCoreOS試した意味があまりないので(単にdockerでコンテナ作っただけだし)fleetとかetcdを試してみる。
*1:勝手に外れてくれないというあれ
Linuxに関する性能問題に一緒に立ち向かってくれるperfという心強い味方
この記事はぴょこりんクラスタ:Re Advent Calendar 2016 - Adventarのために書いたものです。
サマリ
- perfというLinux性能問題に立ち向かうための強力なツールがあるのでみんな使おう!
- 今回は自分のよく使うperf top、perf record、perf scriptについて紹介するよ!
- manが詳しいので困ったらmanを読んだほうがいいよ!
背景
プログラムを作る上で、性能問題を回避することはできない。 自分のプログラムならトレースを仕掛ければいいんだけど、 OSが絡んでいたり、性能が出ないコードの書き方をしていたりするとトレースだけでは難しいこともある。 そんなとき、割と何でも見られるperfが役に立つこともあるかもしれない。
perfとは
Linux用のプロファイリング・トレーシングツール。 manを見ると"perf - Performance analysis tools for Linux"とあって、本当にそのままの名前。 ハードウェアのパフォーマンスカウンタを採取したり、カーネル内に仕掛けられたトレースポイントで 情報(カウントだけじゃなくトレースポイントに応じて)を取ったりできる。
perfのインストール
何も考えずにaptなりyumなりで入れられる。aptの場合はなぜかlinux-tools-genericに入っているので注意。自分でコンパイルしようとすると、Linuxのカーネルソースが必要な上に、いろいろ依存ライブラリが多くて面倒なのでおすすめはしない。
# Ubuntuの場合 $ sudo apt install linux-tools-generic # CentOSの場合 $ sudo yum install perf
とりあえずperf topで中を見てみる
perf topとは文字通りtopコマンドを関数単位で実行してくれるようなもので、プロファイリング結果をリアルタイムで覗けるツール。perf topをするとこんな感じ。 CentOSでいうところのdebuginfoが入っていないのでnodeやら何やらアドレス値しか見えないけど、debuginfoが入っているものや-g付きでコンパイルしたものは関数名が見える。
$ sudo perf top
perf top
はデフォルトでCPUのサイクルをいちばん食っている(要は時間)もの上位を出力してくれるけど、
もちろん違う指標でプロファイリングもできるし、コアやプロセス、スレッド狙い撃ちもできる。
よく使いそうなオプションはこの辺ですかね。
-C <cpu-list>
:デフォルトでシステム全体のところを、コアを狙い撃ちすることができる。-C 0-3
とか、-C 0,1,2,3
みたいに使う-p <pid>
:PID指定。-p 0,1,2
みたいに複数指定もできる-t <tid>
:TID指定。TIDはps auxww -L
で確認しよう-u <uid|user_name>
:uidもしくはuser_nameで指定したユーザが実行中のプロセスについて表示-c <count>
:イベントが<count>
回発生するごとに情報採取-f <freq>
:プロファイリング周期-e <event>
:プロファイルするイベント。ハードウェアのパフォーマンスカウンタ(例えばサイクル数とかキャッシュミス数とか)とか、カーネル内のトレースイベントを指定できる。
-e について
どんなものが指定できるか?
perf listで指定可能なイベントはほぼ全部見られる。ここで出てきた名前をそのまま-e
オプションに渡してやればいい。
親切な名前がついているので、おおよそ名前の通りのイベントが取れる。
$ perf list List of pre-defined events (to be used in -e): branch-instructions OR branches [Hardware event] branch-misses [Hardware event] bus-cycles [Hardware event] cache-misses [Hardware event] cache-references [Hardware event] cpu-cycles OR cycles [Hardware event] instructions [Hardware event] ref-cycles [Hardware event] <中略> L1-dcache-load-misses [Hardware cache event] L1-icache-load-misses [Hardware cache event] L1-icache-loads [Hardware cache event] LLC-loads [Hardware cache event] LLC-prefetch-misses [Hardware cache event] LLC-prefetches [Hardware cache event] LLC-store-misses [Hardware cache event] LLC-stores [Hardware cache event] branch-load-misses [Hardware cache event] branch-loads [Hardware cache event] dTLB-load-misses [Hardware cache event] iTLB-load-misses [Hardware cache event] iTLB-loads [Hardware cache event] <以下略>
ハードウェアのイベントの指定方法について
"ほぼ全部"なのは、perf listには載っていないけどCPUのアーキテクチャ依存な直接指定できるイベントが存在するから。
man perf topを見ると、perf stat -e r1a8 -a sleep 1
なんて例が載っているけど、CMASKとかINVとかの指定の仕方がわかりにくい*1ので、冗長だけどわかりやすい指定方法で指定すればいいと思う。
コアイベントだけじゃなく、uncoreイベントも同様に取れる。
# 以下の2つは同じ意味(のはず。CMASK指定してなさそうだし)。 # 最後のsleep 1は、1秒間だけ測定するときの定型句。 $ perf stat -e r1a8 -a sleep 1 $ perf stat -e cpu/event=0xa8,umask=0x1,name=LSD.UOPS,cmask=0/
ハードウェアのパフォーマンスカウンタに何があるか、どんな値を指定すればよいかは、IntelのDeveloper's Manual Vol.3Bを見よう。
perf recordとperf script
perf recordは文字通りハードウェアのイベント/ソフトウェアのトレースポイントでのイベントを採取してくれるもの。ソフトウェアのトレースポイントと言うのは、例えば、割り込みハンドラがいつ動いたかとか、どのプロセスからどのプロセスへコンテキストスイッチしたか、等々が該当する。
例として、結構よく取られそうなスケジューリング関連の統計情報イベントを取ってみる。
スケジューリング関係のイベントは、perf listで見たときに全部sched:
というprefixがついているのでわかりやすい。
その中の統計情報イベントはsched:sched_stat_xxxx
という形式で書かれている。
$ sudo perf list | grep sched: | grep stat sched:sched_stat_blocked [Tracepoint event] sched:sched_stat_iowait [Tracepoint event] sched:sched_stat_runtime [Tracepoint event] sched:sched_stat_sleep [Tracepoint event] sched:sched_stat_wait [Tracepoint event] sched:sched_stick_numa [Tracepoint event]
スケジューリング関連の統計情報イベントを5秒間採取するには、以下のコマンドを打てばOK。 以下のコマンドを実行すると、カレントディレクトリにperf.dataというバイナリファイルができあがっている*2。イベント間にスペース入れると実行できなくなるので注意*3。
# -aはシステム全体を情報採取対象とするオプション、-Tはタイムスタンプをつけるオプション $ sudo perf record -T -a -e sched:sched_stat_blocked,sched:sched_stat_iowait,sched:sched_stat_runtime,sched:sched_stat_sleep,sched:sched_stat_wait,sched:sched_stick_numa -- sleep 5
perf.dataができたら、perf scriptで中身を見てみよう。いっぱい行があって、"なるほど、わからん"という気分だと思う。
perf 25665 [000] 10703.314496: sched:sched_stat_runtime: comm=perf pid=25665 runtime=668711 [ns] vruntime=4029076279864 [ns] perf 25665 [000] 10703.314522: sched:sched_stat_runtime: comm=perf pid=25665 runtime=26659 [ns] vruntime=4029076306523 [ns] rcu_sched 10 [000] 10703.314524: sched:sched_stat_runtime: comm=rcu_sched pid=10 runtime=2203 [ns] vruntime=4029072613356 [ns] rcu_sched 10 [000] 10703.314525: sched:sched_stat_runtime: comm=rcu_sched pid=10 runtime=1190 [ns] vruntime=4029072614546 [ns] sleep 25666 [000] 10703.314970: sched:sched_stat_runtime: comm=sleep pid=25666 runtime=444092 [ns] vruntime=4029073055245 [ns] sleep 25666 [000] 10703.315009: sched:sched_stat_runtime: comm=sleep pid=25666 runtime=39401 [ns] vruntime=4029073094646 [ns] rcuos/0 11 [000] 10703.315042: sched:sched_stat_runtime: comm=rcuos/0 pid=11 runtime=32519 [ns] vruntime=4029072643672 [ns] rcuos/0 11 [000] 10703.315043: sched:sched_stat_runtime: comm=rcuos/0 pid=11 runtime=1479 [ns] vruntime=4029072645151 [ns] rcu_sched 10 [000] 10703.315044: sched:sched_stat_runtime: comm=rcu_sched pid=10 runtime=1413 [ns] vruntime=4029072615959 [ns] rcu_sched 10 [000] 10703.318039: sched:sched_stat_runtime: comm=rcu_sched pid=10 runtime=5552 [ns] vruntime=4029072621511 [ns] rcu_sched 10 [000] 10703.318040: sched:sched_stat_runtime: comm=rcu_sched pid=10 runtime=2378 [ns] vruntime=4029072623889 [ns] rcuos/0 11 [000] 10703.318047: sched:sched_stat_runtime: comm=rcuos/0 pid=11 runtime=6431 [ns] vruntime=4029072651582 [ns] memballoon 8171 [000] 10703.512849: sched:sched_stat_runtime: comm=memballoon pid=8171 runtime=67601 [ns] vruntime=4029072678754 [ns]
おおよそ察しはつくかもしれないけど、単にperf scriptを実行したときのsched_stat_runtimeのフォーマットはこんな感じ。
<プロセス名> <PID> [<コア番号>] <タイムスタンプ>: <イベント名>: comm=<実行中コマンド名> pid=<PID> runtime=<RUNNING状態だった時間> vruntime=<Linuxのスケジューラがスケジューリングに使う仮想的な時間>
runtimeは(たぶん)RUNNING状態だった時間であって、プログラムが動作し続けていた時間と必ずしも等しいわけじゃないことに注意されたし*4。vruntimeはスケジューラが使う仮想的な時間なので見てもあまり意味がない*5。
perf scriptにオレオレスクリプトでデータ整形してもらう
perf scriptはベタに結果を出力する機能以外にも、自分で作った整形スクリプト(言語はPerlもしくはPython)を使ってくれるという便利機能がある。 手順は以下の3ステップ。
例えば、runtimeの合計と平均を出すにはこんな感じ。
さいごに
perfは大変便利な道具ですが、道具に振り回されないようにがんばる必要がありますね。
Windowsに必ず入れるソフト
この記事はぴょこりんクラスタ:Re Advent Calendar 2016 - Adventarのために書いたものです。
サマリ
最近Windowsを新しくインストールする機会があり、せっかくなので備忘録的に何を入れたか残しておく。
一覧とちょっとしたコメント
- ブラウザ:Firefox(ツリー型タブとBeyond Australisのせいで捨てられない)
- Autopagerize
- Beyond Australis
- ツリー型タブ
- FireGestures
- はてブ
- Omnibarの開発が止まっていたけど、代替品としてBeyond Australisが使えるのでChromeに引っ越さなくてもよくなった。大変うれしい。
- 動画:VLC
- 音楽:iTunes
- ファイラ:As/R
- 機能をほとんど使いこなせていないけど、手に馴染んでてよい。
- ランチャ:Launchy
- マウスを極力使わなくてよくなるのでよい。
- テキストエディタ:Mery
- 軽くて気軽に使えるのがよい。
- クリーナ:CCleaner
- これなんで使ってるんだろうなあ・・・よくわからなくなってきたよ・・・
- 現像:Lightroom
- これがあるからwindowsにしているといっても過言ではない。
- 画像ビューア:MassiGra
- 軽くてよい
- IME:Google日本語入力
- これ実はMS-IMEでもいいような気がするけど、今回もいれてしまった。
- PuTTY:sshクライアント
- ここで配布してるやつだとed25519が使えてよい -> http://ice.hotmint.com/putty/
まとめ
ちゃんとした記事を書くには時間がいる。毎日何か書くのは大変だなあ・・・