SQL*Plus でログインして、自分の PID を調べる
[oracle@localhost ~]$ sqlplus neo/zion SQL> select s.sid, s.serial#, p.spid from v$session s, v$process p where p.addr = s.paddr and s.sid = sys_context('USERENV','SID'); SID SERIAL# SPID ---------- ---------- ------------------------ 17 19 3164
サーバープロセスに strace をしかける
[root@localhost ~]# /usr/bin/strace -p 3164 -o strace.log Process 3164 attached - interrupt to quit
SQL> select count(*) from agent; COUNT(*) ---------- 10000000 SQL> exit
サーバープロセスが終了して、strace もアタッチするプロセスがなくなり、終了する
[root@localhost ~]# /usr/bin/strace -p 3164 -o strace.log Process 3164 attached - interrupt to quit Process 3164 detached
strace で取得したシステムコールのトレースを見てみる
[root@localhost ~]# head -20 strace.log read(9, "\1?\0\0\6\0\0\0\0\0\30>\334\361\0\0\0\0\0\21i\35\376\377\377\377\1\0\0\0\4\0"..., 8208) = 319 gettimeofday({1353546605, 695700}, NULL) = 0 getrusage(RUSAGE_SELF, {ru_utime={0, 3999}, ru_stime={0, 33994}, ...}) = 0 times({tms_utime=0, tms_stime=3, tms_cutime=0, tms_cstime=0}) = 429525137 gettimeofday({1353546605, 695915}, NULL) = 0 getrusage(RUSAGE_SELF, {ru_utime={0, 3999}, ru_stime={0, 33994}, ...}) = 0 getrusage(RUSAGE_SELF, {ru_utime={0, 3999}, ru_stime={0, 33994}, ...}) = 0 times({tms_utime=0, tms_stime=3, tms_cutime=0, tms_cstime=0}) = 429525137 getrusage(RUSAGE_SELF, {ru_utime={0, 3999}, ru_stime={0, 33994}, ...}) = 0 times({tms_utime=0, tms_stime=3, tms_cutime=0, tms_cstime=0}) = 429525137 getrusage(RUSAGE_SELF, {ru_utime={0, 3999}, ru_stime={0, 33994}, ...}) = 0 getrusage(RUSAGE_SELF, {ru_utime={0, 3999}, ru_stime={0, 33994}, ...}) = 0 getrusage(RUSAGE_SELF, {ru_utime={0, 3999}, ru_stime={0, 33994}, ...}) = 0 gettimeofday({1353546605, 696013}, NULL) = 0 gettimeofday({1353546605, 696038}, NULL) = 0 getrusage(RUSAGE_SELF, {ru_utime={0, 3999}, ru_stime={0, 33994}, ...}) = 0 times({tms_utime=0, tms_stime=3, tms_cutime=0, tms_cstime=0}) = 429525137 getrusage(RUSAGE_SELF, {ru_utime={0, 3999}, ru_stime={0, 33994}, ...}) = 0 getrusage(RUSAGE_SELF, {ru_utime={0, 3999}, ru_stime={0, 33994}, ...}) = 0 times({tms_utime=0, tms_stime=3, tms_cutime=0, tms_cstime=0}) = 429525137
getrusage システムコールの ru_utime はユーザーモードでCPUを使った時間、ru_stime はカーネルモードで使った時間。おそらく、ru_stime はシステムコールで使った時間で、割込みで使われた時間は含まれなさそうな気がする。
また、機会があればその先を追ってみようと思う。
ru_utime
This is the total amount of time spent executing in user mode, expressed in a timeval structure (seconds plus microseconds).
ru_stime
getrusage(2): resource usage - Linux man page
This is the total amount of time spent executing in kernel mode, expressed in a timeval structure (seconds plus microseconds).
Linux 2.6 では、この行に 3つの欄が追加されている: iowait (I/O の完了を待っていた時間; 2.5.41 以降); irq (割り込み処理を行った時間; 2.6.0-test4 以降); softirq (ソフト割り込みの処理を行った時間; 2.6.0-test4 以降)。
Man page of PROC
- include/linux/resource.h
#ifndef _LINUX_RESOURCE_H #define _LINUX_RESOURCE_H #include <linux/time.h> struct task_struct; /* * Resource control/accounting header file for linux */ /* * Definition of struct rusage taken from BSD 4.3 Reno * * We don't support all of these yet, but we might as well have them.... * Otherwise, each time we add new items, programs which depend on this * structure will lose. This reduces the chances of that happening. */ #define RUSAGE_SELF 0 #define RUSAGE_CHILDREN (-1) #define RUSAGE_BOTH (-2) /* sys_wait4() uses this */ struct rusage { struct timeval ru_utime; /* user time used */ struct timeval ru_stime; /* system time used */ long ru_maxrss; /* maximum resident set size */ long ru_ixrss; /* integral shared memory size */ long ru_idrss; /* integral unshared data size */ long ru_isrss; /* integral unshared stack size */ long ru_minflt; /* page reclaims */ long ru_majflt; /* page faults */ long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* messages sent */ long ru_msgrcv; /* messages received */ long ru_nsignals; /* signals received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary " */ }; struct rlimit { unsigned long rlim_cur; unsigned long rlim_max; }; #define PRIO_MIN (-20) #define PRIO_MAX 20 #define PRIO_PROCESS 0 #define PRIO_PGRP 1 #define PRIO_USER 2 /* * Limit the stack by to some sane default: root can always * increase this limit if needed.. 8MB seems reasonable. */ #define _STK_LIM (8*1024*1024) /* * GPG wants 32kB of mlocked memory, to make sure pass phrases * and other sensitive information are never written to disk. */ #define MLOCK_LIMIT (8 * PAGE_SIZE) /* * Due to binary compatibility, the actual resource numbers * may be different for different linux versions.. */ #include <asm/resource.h> int getrusage(struct task_struct *p, int who, struct rusage __user *ru); #endif
- kernel/sys.c
/* * It would make sense to put struct rusage in the task_struct, * except that would make the task_struct be *really big*. After * task_struct gets moved into malloc'ed memory, it would * make sense to do this. It will make moving the rest of the information * a lot simpler! (Which we're not doing right now because we're not * measuring them yet). * * When sampling multiple threads for RUSAGE_SELF, under SMP we might have * races with threads incrementing their own counters. But since word * reads are atomic, we either get new values or old values and we don't * care which for the sums. We always take the siglock to protect reading * the c* fields from p->signal from races with exit.c updating those * fields when reaping, so a sample either gets all the additions of a * given child after it's reaped, or none so this sample is before reaping. * * Locking: * We need to take the siglock for CHILDEREN, SELF and BOTH * for the cases current multithreaded, non-current single threaded * non-current multithreaded. Thread traversal is now safe with * the siglock held. * Strictly speaking, we donot need to take the siglock if we are current and * single threaded, as no one else can take our signal_struct away, no one * else can reap the children to update signal->c* counters, and no one else * can race with the signal-> fields. If we do not take any lock, the * signal-> fields could be read out of order while another thread was just * exiting. So we should place a read memory barrier when we avoid the lock. * On the writer side, write memory barrier is implied in __exit_signal * as __exit_signal releases the siglock spinlock after updating the signal-> * fields. But we don't do this yet to keep things simple. * */ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) { struct task_struct *t; unsigned long flags; cputime_t utime, stime; memset((char *) r, 0, sizeof *r); utime = stime = cputime_zero; rcu_read_lock(); if (!lock_task_sighand(p, &flags)) { rcu_read_unlock(); return; } switch (who) { case RUSAGE_BOTH: case RUSAGE_CHILDREN: utime = p->signal->cutime; stime = p->signal->cstime; r->ru_nvcsw = p->signal->cnvcsw; r->ru_nivcsw = p->signal->cnivcsw; r->ru_minflt = p->signal->cmin_flt; r->ru_majflt = p->signal->cmaj_flt; if (who == RUSAGE_CHILDREN) break; case RUSAGE_SELF: utime = cputime_add(utime, p->signal->utime); stime = cputime_add(stime, p->signal->stime); r->ru_nvcsw += p->signal->nvcsw; r->ru_nivcsw += p->signal->nivcsw; r->ru_minflt += p->signal->min_flt; r->ru_majflt += p->signal->maj_flt; t = p; do { utime = cputime_add(utime, t->utime); stime = cputime_add(stime, t->stime); r->ru_nvcsw += t->nvcsw; r->ru_nivcsw += t->nivcsw; r->ru_minflt += t->min_flt; r->ru_majflt += t->maj_flt; t = next_thread(t); } while (t != p); break; default: BUG(); } unlock_task_sighand(p, &flags); rcu_read_unlock(); cputime_to_timeval(utime, &r->ru_utime); cputime_to_timeval(stime, &r->ru_stime); } int getrusage(struct task_struct *p, int who, struct rusage __user *ru) { struct rusage r; k_getrusage(p, who, &r); return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0; } asmlinkage long sys_getrusage(int who, struct rusage __user *ru) { if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN) return -EINVAL; return getrusage(current, who, ru); }
環境は以下の通り
[root@localhost ~]# cat /etc/issue Enterprise Linux Enterprise Linux Server release 5.5 (Carthage) Kernel \r on an \m [root@localhost ~]# uname -a Linux localhost.localdomain 2.6.18-194.17.1.0.1.el5 #1 SMP Wed Sep 29 15:40:03 EDT 2010 i686 i686 i386 GNU/Linux SQL> select * from v$version; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production PL/SQL Release 11.2.0.2.0 - Production CORE 11.2.0.2.0 Production TNS for Linux: Version 11.2.0.2.0 - Production NLSRTL Version 11.2.0.2.0 - Production