/*
This file is part of demos for "Latch Mutex and beyond blog"
Andrey S. Nikolaev (Andrey.Nikolaev@rdtex.ru)
http://AndreyNikolaev.wordpress.com
Compute the latch statistics
For Oracle versions 11g:
@latch_stats_11g ADDRESS
*/
set verify off
select name from v$latch where addr='&1'
union all
select name from v$latch_children where addr='&1';
SET SERVEROUTPUT ON
set timing on
DECLARE
i number;
Samples number:= 300;
SampleFreq number:= 1 / 10; -- Hz;
Nw NUMBER;
laddr raw(8);
cursor lstat(laddr_ raw) is /* latch statistics */
select kslltnum LATCH#,kslltwgt GETS, kslltwff MISSES,kslltwsl SLEEPS,ksllthst0 SPIN_GETS,kslltwtt latch_wait_time, kslltcnm child#
from x$kslltr_children where kslltaddr=hextoraw(laddr_)
union all
select kslltnum LATCH#,kslltwgt GETS,kslltwff MISSES,kslltwsl SLEEPS,ksllthst0 SPIN_GETS,kslltwtt latch_wait_time, 0 child#
from x$kslltr_parent where kslltaddr=hextoraw(laddr_);
Lstat1 lstat%ROWTYPE;
Lstat2 lstat%ROWTYPE;
dgets number;
dmisses number;
rho number;
eta number;
lambda number;
kappa number;
W number;
sigma number;
error_ varchar2(100):='';
lname varchar2(100);
level_ number;
dtime number;
U number :=0;
ssleeps number;
S number;
params varchar2(2000):='';
BEGIN
laddr := HEXTORAW ('&1');
/* CPU count */
select value into Nw from v$parameter where name = 'cpu_count';
if Nw != 1 then
eta:= Nw/(Nw-1);
else
eta:=1;
Error_ := Error_||' Single CPU configuration ';
end if;
Nw := 0;
/* Beginning latch statistics */
dtime := DBMS_UTILITY.GET_TIME();
OPEN Lstat(laddr);
FETCH Lstat into Lstat1;
if Lstat%NOTFOUND then
raise_application_error(-20001,'No latch at 0x'||laddr);
end if;
CLOSE Lstat;
/* Sampling */
FOR i IN 1 .. Samples
LOOP
/* number of pocesses waiting for the latch */
for Sample in (SELECT count(decode(ksllawat,'00',null,1)) wat FROM x$ksupr
WHERE ksllawat=laddr)
LOOP
Nw := Nw + Sample.wat;
END LOOP;
/* Is latch busy */
for Hold in (select 1 hold from x$ksuprlat where ksuprlat=laddr)
loop
U:=U+1;
exit;
end loop;
DBMS_LOCK.sleep (SampleFreq);
END LOOP;
/* End latch statistics */
OPEN Lstat(laddr);
FETCH Lstat into Lstat2;
CLOSE Lstat;
dtime:=(DBMS_UTILITY.GET_TIME()-dtime)*0.01; /* delta time in seconds */
/* Compute derived statistics */
dgets := (lstat2.gets-lstat1.gets);
dmisses:= (lstat2.misses-lstat1.misses);
if(dgets>0)then rho := dmisses/dgets;
else
raise_application_error(-20002,'No gets activity for this latch');
end if;
Nw:=Nw/Samples;
U:=U/Samples;
lambda:=dgets/dtime;
W:= (lstat2.latch_wait_time-lstat1.latch_wait_time)/dtime*1.E-6; /* wait time in seconds */
select kslldnam,kslldlvl into lname,level_ from x$kslld where indx=lstat2.latch#;
/* S:=eta*rho/lambda; */
S:=U/lambda;
if(dmisses>0) then
kappa:=(lstat2.sleeps-lstat1.sleeps)/dmisses;
sigma:=(lstat2.spin_gets-lstat1.spin_gets)/dmisses;
else
error_ := Error_||' Delta MISSES='||dmisses;
kappa:=null;
sigma:=null;
end if;
if(kappa>0) then
ssleeps:=(kappa+sigma-1)/kappa;
else
error_ := Error_||' Sigma='||sigma;
ssleeps:=null;
end if;
if(length(Error_)>0 ) then
DBMS_OUTPUT.put_LINE (' Error: '||error_);
end if;
DBMS_OUTPUT.put_LINE (chr(10)||'Latch statistics for 0x'||laddr||' "'||lname||'" level#='||level_||' child#='||lstat2.child#);
DBMS_OUTPUT.put_LINE ('Requests rate: lambda=' || to_char(lambda,'999999.9')||' Hz');
DBMS_OUTPUT.put_LINE ('Miss /get: rho=' || to_char(rho,'9.999999'));
DBMS_OUTPUT.put_LINE ('Est. Utilization: eta*rho=' || to_char(eta*rho,'9.999999'));
DBMS_OUTPUT.put_LINE ('Sampled Utilization: U='||to_char(U,'9.999999'));
DBMS_OUTPUT.put_LINE ('Slps /Miss: kappa=' || to_char(kappa,'9.999999'));
DBMS_OUTPUT.put_LINE ('Wait_time/sec: W=' || to_char(W,'999.999999'));
DBMS_OUTPUT.put_LINE ('Sampled queue length L=' || to_char(Nw,'999.999999'));
DBMS_OUTPUT.put_LINE ('Spin_gets/miss: sigma=' || to_char(sigma,'9.999999'));
DBMS_OUTPUT.put_LINE (chr(10)||'Derived statistics:');
DBMS_OUTPUT.put_LINE ('Secondary sleeps ratio =' || to_char(ssleeps,'9.99EEEE'));
DBMS_OUTPUT.put_LINE ('Avg latch holding time =' || to_char(S*1000000,'999999.9')||' us');
DBMS_OUTPUT.put_LINE ('. sleeping time =' || to_char(W/lambda*1000000,'999999.9')||' us');
DBMS_OUTPUT.put_LINE ('. avg latch free wait =' || to_char(W/(kappa*rho*lambda)*1000000,'999999.9')||' us');
DBMS_OUTPUT.put_LINE ('. miss rate=' || to_char(rho*lambda,'999999.9')||' Hz');
DBMS_OUTPUT.put_LINE ('. waits rate =' || to_char(kappa*rho*lambda,'999999.9')||' Hz');
DBMS_OUTPUT.put_LINE ('. spin inefficiency k=' || to_char(kappa/(1+kappa*rho),'9.999999'));
/* latch parameters */
for Param in (select ksppinm,ksppstvl from x$ksppi x join x$ksppcv using (indx )
where ksppinm like '\_latch\_class%' ESCAPE '\' or ksppinm in
('_spin_count','_enable_reliable_latch_waits','_latch_miss_stat_sid','_ultrafast_latch_statistics')
order by ksppinm)
loop
params:=params||Param.ksppinm||'='||Param.ksppstvl||' ';
end loop;
DBMS_OUTPUT.put_LINE (chr(10) ||'Latch related parameters:'||chr(10) || params);
EXCEPTION
when others then
DBMS_OUTPUT.put_LINE (chr(10)||'Error raised:'||SQLERRM);
DBMS_OUTPUT.put_LINE (DBMS_UTILITY.FORMAT_CALL_STACK);
DBMS_OUTPUT.put_LINE ('----- '||chr(10)||'LADDR= 0x'||rawtohex(laddr)||' dtime='||dtime||' Nw= '||Nw||' U='||U);
DBMS_OUTPUT.put_LINE ('gets='||lstat2.gets||'-'||lstat1.gets||'='||dgets||' misses='||lstat2.misses||'-'||lstat1.misses||'='||dmisses);
DBMS_OUTPUT.put_LINE ('sleeps='||lstat2.sleeps||'-'||lstat1.sleeps||'='||(lstat2.sleeps-lstat1.sleeps)||
' spin_gets='||lstat2.spin_gets||'-'||lstat1.spin_gets||'='||(lstat2.spin_gets-lstat1.spin_gets));
DBMS_OUTPUT.put_LINE ('rho='||rho||' lambda='||lambda||' kappa= '||kappa||' sigma='||sigma);
END;
/
latch_stats_11g.sql
Leave a Comment »
No comments yet.
RSS feed for comments on this post. TrackBack URI