2014/4/24に社内で低レイヤー芸人*1として、ターミナルを開いてコマンドを打ちながら話したときのメモ。口頭でしゃべったことやホワイトボードに書いたことは書いていません、本当にただのメモです。
ねらい
- 知らない世界に案内し、興味を持ってもらう(時間も短いので網羅性より面白さ重視)
何がわかるようになるか
サマリ
- iowait の割合が高い場合、CPU は忙しいのか暇なのか?
- dstat、htop、perf、crash などのコマンドの紹介
- vmstat も上記のようなコマンドも /proc を参照していて、/proc の実体はメモリ上のカーネル空間のデータ構造(たぶんだいたい)
- /proc で参照できるようなデータは定期的に割込みが入って累積値が積み上げられていき、vmstat などは差分を算出して表示している(たぶんだいたい)
- Brendan D. Gregg の USE Method の話
内容
コマンド
- 一般ユーザで実行したコマンド
dstat -ta 2 fio -rw=randread -bs=4k -size=300m -directory=/tmp -numjobs=5 -name=file1 python -c 'while 1: pass' & strace -e open dstat 1 1 strace -e open vmstat 1 1 strace -e open iostat 1 1 htop strace htop pkill python perl -e 'while(1){}' & pkill perl
- rootで実行したコマンド
perf top crash crash> runq crash> kmem -i crash> kmem -f crash> dis メモリアドレス
Linuxカーネルのソースでプロセスアカウンティングの仕組みを解説
/* * Called from the timer interrupt handler to charge one tick to the current * process. user_tick is 1 if the tick is user time, 0 for system. */ void update_process_times(int user_tick) { struct task_struct *p = current; int cpu = smp_processor_id(); /* Note: this timer irq context must be accounted for as well. */ account_process_tick(p, user_tick); run_local_timers(); rcu_check_callbacks(cpu, user_tick); printk_tick(); #ifdef CONFIG_IRQ_WORK if (in_irq()) irq_work_run(); #endif scheduler_tick(); run_posix_cpu_timers(p); }
/* * Account a single tick of cpu time. * @p: the process that the cpu time gets accounted to * @user_tick: indicates if the tick is a user or a system tick */ void account_process_tick(struct task_struct *p, int user_tick) { cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); struct rq *rq = this_rq(); if (sched_clock_irqtime) { irqtime_account_process_tick(p, user_tick, rq); return; } if (user_tick) account_user_time(p, cputime_one_jiffy, one_jiffy_scaled); else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET)) account_system_time(p, HARDIRQ_OFFSET, cputime_one_jiffy, one_jiffy_scaled); else account_idle_time(cputime_one_jiffy); } ... /* * Account for idle time. * @cputime: the cpu time spent in idle wait */ void account_idle_time(cputime_t cputime) { struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; cputime64_t cputime64 = cputime_to_cputime64(cputime); struct rq *rq = this_rq(); if (atomic_read(&rq->nr_iowait) > 0) cpustat->iowait = cputime64_add(cpustat->iowait, cputime64); else cpustat->idle = cputime64_add(cpustat->idle, cputime64); }
今後紹介したいもの
- perf、/proc/meminfo、fio、blktrace。crash、DTrace、oratop、MOTAS など。
*1:低レイヤー芸人と言えるほどではないですが、とりあえずそういうくくりでやりました