-*- outline -*-
#
# $B%$%Y%s%H%^%9%/$rA*Br$G$-$k$h$&$K(B API $B$N3HD%$r9T$J$$$^$7$?!#(B
# $B$3$NJ8=q$O(BAPI$B3HD%A0$NFbMF$J$N$G!"8=>u$H$O9g$C$F$$$^$;$s!#(Bm(__)m
#

* $B%f!<%6%W%m%0%i%`MQ(B API $B$N@bL@(B

$B%f!<%6%W%m%0%i%`MQ(B API $B$O9b%l%Y%k(BAPI$B$HDc%l%Y%k(BAPI$B$N(B2$B$D$N%l%$%d$K$o$+$l(B
$B$^$9!#9b%l%Y%k(BAPI$B$O%f!<%6%"%W%j%1!<%7%g%s$K4JC1$KAH$_9~$a$k$h$&$K$7$?(B
$B4JN,$J(BAPI$B$G$9!#Dc%l%Y%k(BAPI$B$O$h$j>\:Y$K@)8f$G$-$k(BAPI$B$G$9!#(B

$B$^$:!"%f!<%6%W%m%0%i%`$G;HMQ$9$k9=B$BN$N@bL@$r9T$J$C$F$+$i!"Dc%l%Y%k(B
API$B$rMQ$$$?%$%Y%s%H%W%m%U%!%$%j%s%0$N@bL@!"%W%m%0%i%`AH$_9~$_MQ(B API $B$N(B
$B@bL@$r9T$$$^$9!#(B

* $B9=B$BN$N@bL@(B
** $B%F%s%W%l!<%H9=B$BN(B

hardmeter $B$N85$H$J$C$?(B perfctr $B$G$O!"B,Dj$9$k%$%Y%s%HKh$K!V$I$N%Q%U%)!<(B
$B%^%s%9%b%K%?%j%s%0%+%&%s%?$r;HMQ$9$k$N$+!"$^$?!"$=$l$>$l$N%+%&%s%?$N3F(B
$B%S%C%H$K$I$N$h$&$JCM$r@_Dj$9$k$N$+!W$rL@<(E*$K;XDj$7$^$9!#$3$l$i$N>pJs(B
$B$r;XDj$9$k$K$O(B Intel $B$N%^%K%e%"%k$H<s$C$T$-$K$I$3$K$I$N$h$&$JCM$rF~$l$k(B
$BI,MW$,$"$k$+$rD4$Y$kI,MW$,$"$j$^$9!#(B

hardmeter $B$G$O%f!<%6$NJX$N$?$a!"$3$l$i$N%$%Y%s%H$r%F%s%W%l!<%H$H$7$F$^(B
$B$H$a$F!"%F%s%W%l!<%H$NL>A0$r;XDj$9$k$@$1$GI,MW$J>pJs$rF@$i$l$k$h$&$K$7(B
$B$^$7$?!#(Bhardmeter$B$rMxMQ$9$k>l9g$O!";HMQ$9$k%F%s%W%l!<%H$H<c43$N%Q%i%a!<(B
$B%?$r;XDj$9$k$@$1$G%$%Y%s%H$NB,Dj$,$G$-$k$h$&$K$7$F$"$j$^$9!#%F%s%W%l!<(B
$B%H$N9=B$$O0J2<$N$h$&$K$J$C$F$$$^$9!#(B

struct hardmeter_template_t {
	const char *name;
	const char *description;
	const struct vperfctr_control *control;
	const hardmeter_event_mask_t *eventmask;
	int type;
};
typedef struct hardmeter_template_t hardmeter_template_t;

name $B$K%F%s%W%l!<%H$NL>A0!"(Bdescription $B$K$=$N@bL@$,$O$$$j$^$9!#(B
control, eventmask $B$O%F%s%W%l!<%H$N<B:]$N@_Dj$,$O$$$C$F$$$kItJ,$J$N$G!"(B
$B%f!<%6%W%m%0%i%`B&$,5$$K$9$kI,MW$O$"$j$^$;$s!#(Btype $B$K$=$N%F%s%W%l!<(B
$B%H$,(B Precise EBS $B$J$N$+!"(BNon-preciese EBS $B$J$N$+!"%+%&%s%?$J$N$+$N6hJL$,(B
$B$O$$$C$F$$$^$9!#%f!<%6%W%m%0%i%`B&$G$O$3$l$i$NCM$N;2>H$N$_$r9T$C$F$/$@$5(B
$B$$!#(B

name $B$N$_$,Dj5A$5$l$F$$$F!"B>$N%a%s%P!<$,(B NULL $B$N%(%s%H%j$b$"$j$^$9$,!"(B
$B$3$l$O(B ebs $B%3%^%s%I$,2hLL$K%$%Y%s%H0lMw$r=PNO$9$k$H$-$N%3%a%s%H$H$7$F(B
$B$"$D$+$o$l$^$9!#(B

$B%F%s%W%l!<%H$N0lMw$r<hF@$9$k$H$-$O!"(Bhardmeter_get_templates() $B$rMxMQ$7(B
$B$F$/$@$5$$!#8=:_F0$$$F$$$k%^%7%s$N(B CPU $B$N<oN`$KBP1~$7$?%F%s%W%l!<%H$r(B
$BLa$9$h$&$K$J$C$F$$$^$9!#8=:_$N<BAu$G$O(B Pentium 4 $B$KBP1~$7$?%F%s%W%l!<(B
$B%H$N$_$rMQ0U$7$F$"$j$^$9$,!">-MhE*$K$O3HD%$9$kM=Dj$G$9!#(B

$B%F%s%W%l!<%H$NL>A0$G$b$C$F%F%s%W%l!<%H$r8!:w$9$k$H$-$O!"(B
hardmeter_search_template() $B$,MxMQ$G$-$^$9!#(B

** $B%*%W%7%g%s9=B$BN(B

hardmeter $B$GB,Dj3+;O$9$k$N$KI,MW$J%*%W%7%g%s$O!"(Bhardmeter_option_t $B$K(B
$B$^$H$a$F$"$j$^$9!#(B

struct hardmeter_option_t {
	const hardmeter_template_t *template;
	int user;
	int kernel;
	int interval;
	int count;
};
typedef struct hardmeter_option_t hardmeter_option_t;

template $B$K$OA0=R$N%F%s%W%l!<%H9=B$BN$N%]%$%s%?$rF~$l$^$9!#(B
user $B$O%f!<%6%b!<%I$G$N%$%Y%s%H$r:N<h$9$k$+$I$&$+$N%U%i%0!"(Bkernel $B$O%+!<(B
$B%M%k%b!<%I$G$N%$%Y%s%H$r:N<h$9$k$+$I$&$+$N%U%i%0!"(Binterval $B$O2?2s%$%Y(B
$B%s%H$,5/$3$C$?$i%G!<%?$r:N<h$9$k$+!"(Bcount $B$K$O:N<h$9$k%G!<%?$N:GBgCM$r(B
$B;XDj$7$^$9!#(B

$B%*%W%7%g%s9=B$BN$N%a%s%P!<$rKd$a$F$+$i!"(Bhardmeter $B$rMQ$$$?%$%Y%s%H$N:N(B
$B<h$K$O$$$j$^$9!#(B

$BNc(B:
    int foo(....)
    {
         hardmeter_option_t opt;
         const char *err;

         opt.template = hardmeter_search_template("l1_cache_miss", &err);
         opt.user = 1;
         opt.kernel = 0;
         opt.interval = 10000;
         opt.count = 2000;
         ... start sampling ...

    }


* $BDc%l%Y%k(BAPI$B$N@bL@(B

** hardmeter $B$N=i4|2=(B

$B$^$::G=i$K!"(Bhardmeter_init() $B$G$b$C$F(B hardmeter $B$,;HMQ$G$-$k$+$I$&$+$N(B
$B%A%'%C%/$r9T$$$^$9!#(B

   const char *err;

   if (hardmeter_init(&err) != 0) {
     printf("Cannot use hardmeter.\nreason: %s\n", err);
     exit(1);
   }

$BLa$jCM$,(B 0 $B$N$H$-@.8y$G!"(B-1 $B$N$H$-%(%i!<$G$9!#%(%i!<$N$H$-$O0z?t$NCM$,(B
NULL $B0J30$N$H$-!"0z?t$N%]%$%s%?$KBP$7$F%(%i!<J8;zNs$N%]%$%s%?$r@_Dj$7$^$9!#(B

** $B%W%m%U%!%$%j%s%0$N3+;O(B

$BHFMQE*$J(B API$B$G$b$C$F%$%Y%s%H%W%m%U%!%$%j%s%0$r3+;O$9$kJ}K!$O0J2<$N(B3$B<oN`$"(B
$B$j$^$9!#(B

(1)hardmeter_open()
   $B<+J,<+?H$N%W%m%;%9$KBP$7$FB,Dj$r3+;O$7$^$9!#(B

(2)hardmeter_attach_process()
   $B0z?t$K;XDj$5$l$?%W%m%;%9$KBP$7$FB,Dj$r3+;O$7$^$9!#$3$N$H$-B,Dj$7$h(B
   $B$&$H$9$k%W%m%;%9$HF1$8%f!<%6$+!"$^$?$O<+?H$,%9!<%Q!<%f!<%6$G$J$$$H(B
   $BB,Dj3+;O$K<:GT$7$^$9!#(B

(3)hardmeter_start_process()
   $B0z?t$G;XDj$5$l$?%3%^%s%I$r;R%W%m%;%9$H$7$F<B9T$7!";R%W%m%;%9$KBP$7(B
   $B$FB,Dj$r3+;O$7$^$9!#(B

$B$=$l$>$l$N4X?t$NLa$jCM$,!"(Bhardmeter $B$G%5%s%W%j%s%0$9$k$?$a$N%O%s%I%k$H(B
$B$J$j!"0J9_$N4X?t$O$9$Y$F$3$N%O%s%I%k7PM3$G;HMQ$7$^$9!#(B
$B%(%i!<$K$J$C$?$H$-$OLa$jCM$,(B NULL $B$H$J$j!"(Berr $B$K$=$NM}M3$,F~$j$^$9!#(B

$BNc(B1: $B<+%W%m%;%9$N%W%m%U%!%$%j%s%0(B

    hardmeter_t *handle;
    hardmeter_option_t opt;
    const char *err;

    .... opt $B$r=i4|2=(B ....
    hardmeter = hardmeter_open(&opt, &err);
    if (hardmeter == NULL) {
      printf("Cannot start hardmeter.\nreason: %s\n", err);
      exit(1);
    }

$BNc(B2: $B$9$G$KF0$$$F$$$kJL%W%m%;%9$K%"%?%C%A$7$F%W%m%U%!%$%j%s%0(B

    hardmeter_t *handle;
    hardmeter_option_t opt;
    pid_t pid;
    const char *err;

    .... opt $B$r=i4|2=(B ....
    .... pid $B$K%"%?%C%A$9$k%W%m%;%9$N%W%m%;%9(BID$B$r@_Dj(B ....
    hardmeter = hardmeter_attach_processs(&opt, pid, &err);
    if (hardmeter == NULL) {
      printf("Cannot start hardmeter.\nreason: %s\n", err);
      exit(1);
    }

$BNc(B3: $BJL%W%m%;%9$r5/F0$7$F%W%m%U%!%$%j%s%0(B

    hardmeter_t *handle;
    hardmeter_option_t opt;
    char *argv;
    const char *err;

    .... opt $B$r=i4|2=(B ....
    .... argv $B$K5/F0$9$k%3%^%s%I$NL>A0$H0z?t$r;XDj(B ....
    hardmeter = hardmeter_start_process(&opt, argv[0], argv, &err);
    if (hardmeter == NULL) {
      printf("Cannot start hardmeter.\nreason: %s\n", err);
      exit(1);
    }

$B%W%m%U%!%$%k%G!<%?$O%+!<%M%k6u4V$N%P%C%U%!$KC_$($i$l$F$$$-$^$9!#(B

** $B%W%m%U%!%$%j%s%0$N=*N;(B

hardmeter_terminate() $B$G%W%m%U%!%$%j%s%0$,=*N;$7$^$9!#(B
$B%W%m%U%!%$%k%G!<%?$O(B hardmeter_close() $B$5$l$k$^$G%a%b%j>e$NJ];}$5$l$F(B
$B$$$^$9!#(B

** $B%W%m%U%!%$%k%G!<%?$N=PNO(B

$B%W%m%U%!%$%k%G!<%?$O(B hardmeter_dump() $B$G$b$C$F%U%!%$%k$K=PNO$5$l$^$9!#(B

$BNc(B:
    hardmeter_t *handle;
    const char *err;

    hardmeter_dump(handle, "profile.dat", 0, &err);

$BBh(B1$B0z?t$K(B hardmeter $B$N%O%s%I%k!"Bh(B2$B0z?t$K=PNO$9$k%U%!%$%kL>!"Bh(B3$B0z?t$K(B
$B%V%m%C%-%s%0%b!<%I(B/$BHs%V%m%C%-%s%0%b!<%I$N%U%i%0!"Bh(B4$B0z?t$K%(%i!<J8;zNs(B
$B$r@_Dj$9$k%]%$%s%?$r;XDj$7$^$9!#(B

$BBh(B3$B0z?t$,(B 0 $B$N$H$-!"%V%m%C%-%s%0%b!<%I$G$9!#%V%m%C%-%s%0%b!<%I$N$H$-$O!"(B
$BB,DjBP>]$N%W%m%;%9$,=*N;$9$k$+!"(Bhardmeter_otpion_t $B$N(B count $B$G;XDj$7$?(B
$B?t$^$GB,Dj$9$k$^$G%V%m%C%/$7$^$9!#(B

$BBh(B3$B0z?t$,(B $BHs(B0 $B$N$H$-!"Hs%V%m%C%-%s%0%b!<%I$G$9!#Hs%V%m%C%-%s%0%b!<%I$N(B
$B$H$-$O!"8=:_C_$($i$l$F$$$k%W%m%U%!%$%k%G!<%?$r$9$Y$F%U%!%$%k$KJ]B8$7$?(B
$B$i=*N;$7$^$9!#(B

** $B%W%m%U%!%$%j%s%0$N8e;OKv(B

hardmeter_close() $B$G%W%m%U%!%$%k%G!<%?$r3+J|$7$^$9!#(B
hardmeter_terminate() $B$,8F$P$l$F$J$$$H$-$O!"%W%m%U%!%$%j%s%0$r=*N;$7$F(B
$B$+$i%W%m%U%!%$%k%G!<%?$r3+J|$7$^$9!#$3$N4X?t$,8F$P$l$?8e$O!"(Bhardmeter
$B$N%O%s%I%k$OL58z$K$J$j$^$9!#(B

$BB>%W%m%;%9$N%W%m%U%!%$%j%s%0$r9T$J$C$F$$$k>l9g$O!"%W%m%;%9$r=*N;$9$kA0(B
$B$KI,$:(B hardmeter_terminate() $B$b$7$/$O(B hardmeter_close() $B$r9T$C$F$/$@$5(B
$B$$!#L@<(E*$K%W%m%U%!%$%j%s%0$r=*N;$7$J$$$+$.$j!"B,DjBP>]$N%W%m%;%9$O<+(B
$B?H$,%W%m%U%!%$%j%s%0$5$l$F$$$k$3$H$rCN$k$3$H$,$G$-$^$;$s!#(B

* $B9b%l%Y%k(BAPI$B$N@bL@(B

** $B%W%m%U%!%$%j%s%0$N3+;O!&=*N;(B

$B9b%l%Y%k(BAPI$B%"%W%j%1!<%7%g%s$KAH$_9~$s$G!"<+%W%m%;%9$N>pJs$r4JC1$K:N<h(B
$B$9$k$?$a$N(B API $B$G$9!#%W%m%U%!%$%j%s%0$7$?$$%3!<%I$NA08e$r!"(B
hardmeter_start()$B!"(Bhardmeter_stop() $B$G0O$`$@$1$G%W%m%U%!%$%k%G!<%?$,:N(B
$B<h$G$-$^$9!#(B

$BNc(B:
    hardmeter_start("resource_name");
    .... $B%W%m%U%!%$%k$r9T$$$?$$%3!<%I(B .....
    hardmeter_stop();

$B$I$N$h$&$J%$%Y%s%H$r:N<h$9$k$+$O(B hardmeter_start() $B$N0z?t$G;XDj$9$k%j(B
$B%=!<%9L>$G;XDj$7$^$9!#%j%=!<%9L>$K$O%9%Z!<%9$H(B '.' $B0J30$NG$0U$NJ8;z$,(B
$B;HMQ$G$-$^$9!#(B

** $B%j%=!<%9%U%!%$%k$N=q<0(B

$B9b%l%Y%k(B API $B$G$O%5%s%W%j%s%0$NDj5A$O%[!<%`%G%#%l%/%H%j$N%j%=!<%9%U%!(B
$B%$%k(B($HOME/.hardmeterrc) $B$K=q$-$^$9!#%W%m%U%!%$%j%s%0$N@_Dj$O%W%m%0%i(B
$B%`$KKd$a9~$^$l$F$J$$$N$G!"%j%=!<%9%U%!%$%k$rJQ99$9$k$@$1$G:F%3%s%Q%$%k(B
$B$J$7$KMM!9%$%Y%s%H$NB,Dj$,9T$($^$9!#(B

$B%j%=!<%9%U%!%$%k$N=q<0$O!"(B

   $B%j%=!<%9L>(B.$B%Q%i%a!<%?L>(B   $B%Q%i%a!<%?$NCM(B

$B$H$J$C$F$$$^$9!#(Bresource name $B$H$$$&%j%=!<%9L>$G%W%m%U%!%$%j%s%0$r9T$&(B
$B>l9g$O!"(B$HOME/.hardmeterrc $B$r2<5-$N$h$&$K5-=R$7$^$9!#(B

   # sample events in user-mode when non-zero. default 0.
   resource_name.user           1
   # sample events in kernel-mode when non-zero. default 0.
   resource_name.kernel         0
   # specify event name.
   resource_name.event          l1_cache_miss
   # output file
   #      %Y - year (1970...)
   #      %y - year (00..99)
   #      %m - month (01..12)
   #      %d - day of month (01..31)
   #      %H - hour (00..23)
   #      %M - minute (00..59)
   #      %S - second (00..60)
   #      %P - process id
   resource_name.dumpfile /tmp/hardmeter.%y%m%d-%H%M%S.%P
   # max sampling count. default 2000, max 524270 for pebs.
   resource_name.count          200
   # sampling interval. default 10000.
   resource_name.interval 10000
