Posts Tagged ‘callstack’
Pure SQL version of ostakprof(from Tanel Poder)
Have you noticed following post from Tanel Poder? This is a very interesting and practical story even with the depth within it.
Here he introduces how you can do a simple but powerful function call profiling on the process without any serious 3rd party tool. ORADEBUG SHORT_STACK command is the core of the technique. His approach is to use VBscript(on the client-side) to parse the result of ORADEBUG SHORT_STACK.
I tried to implement the same functionality with 100% pure SQL which seems more portable and customizable to me. Following is the dirty example of it.
-------------------------------------------------------------------------------- -- @name: prof_callstack -- @author: dion cho -- @note: troubleshoot using oradebug callstack dump -- @usage: @prof_callstack -------------------------------------------------------------------------------- define __SID = &1 define __SLEEP = &2 define __SAMPLE = &3 col spid new_value v_spid select spid from v$process where addr = (select paddr from v$session where sid = &__SID); oradebug setospid &v_spid @make_callstack &__SLEEP &__SAMPLE @oradebug_callstack /* -- execute following command before doing profiling. drop table callstack_temp purge; create global temporary table callstack_temp(seq number, idx number, fname varchar2(20)); */ declare b_start boolean := false; b_first boolean := false; fname varchar2(20); ftype varchar2(10); seq number := 1; idx number := 1; begin for r in (select * from table(ukja.get_trace_file1(&__SID))) loop if instr(r.column_value, 'Call Stack Trace') > 0 then b_start := true; b_first := true; end if; if instr(r.column_value, 'End of Call Stack Trace') >0 then seq := seq+1; idx := 1; b_start := false; end if; if b_start = true and b_first = false then fname := rtrim(substr(r.column_value, 1, 20)); ftype := rtrim(substr(r.column_value, 22, 8)); if ftype like 'CALL%' or ftype = 'VIRTUAL' then dbms_output.put_line(fname); insert into callstack_temp values(seq, idx, fname); idx := idx + 1; end if; end if; if b_start = true then b_first := false; end if; end loop; end; / spool callstack_result.txt -- do some reporting col sample# new_value sample_count select count(distinct seq) as sample#, count(*) as call#, max(idx) as max_depth from callstack_temp ; -- unique callstack and hit count select count(*) as hit#, 100*(count(*)/&sample_count) as ratio, stack from ( select seq, ltrim(sys_connect_by_path(fname,'->'),',') stack from ( select seq, fname, row_number() over (partition by seq order by idx desc) rn, count(*) over (partition by seq) cnt from callstack_temp ) where level = cnt start with rn = 1 connect by prior seq = seq and prior rn = rn-1 ) group by stack order by 1 desc ; spool off @ed callstack_result.txt delete from callstack_temp;
Here I use ORADEBUG DUMP CALLSTACK 1 command to store the callstacks to the server-side tracefile.
Following is how to make Oracle automatically invokes ORADEBUG DUMP CALLSTACK 1 command multiple times.
set heading off
set timing off
set feedback off
set verify off
set serveroutput on size 100000
spool oradebug_callstack.sql
begin
for idx in 1 .. &2 loop
dbms_output.put_line('oradebug dump callstack 1');
dbms_output.put_line('exec dbms_lock.sleep(&1);');
end loop;
end;
/
spool off
set heading on
set timing on
set feedback on
set verify on
set serveroutput off
For simple test case, I make a query which consumes good minutes to be hard-parsed.
set heading off
set timing off
set feedback off
set serveroutput on size 100000
var v_sql clob;
begin
:v_sql := 'select count(*) from ';
for r in (select t1.table_name
from user_tables t1, user_tables t2 where rownum <= 500 and
t1.table_name not like '%$%') loop
:v_sql := :v_sql || r.table_name || ', ';
end loop;
:v_sql := :v_sql || ' dual where 1 = 0;';
end;
/
spool long_parse.sql
exec dbms_output.put_line(:v_sql);
spool off
set heading on
set timing on
set feedback on
set serveroutput off
While getting the session#1 invoke the long-parsing query, let me invoke the prof_callstack.sql as following.
-- session #1
UKJA@ukja102> @long_parse
COUNT(*)
----------
0
Elapsed: 00:03:06.53
-- session#2
connect /as sysdba
SYS@ukja10> @prof_callstack 140 0.01 100
Now I get the internal meaning of the long hard-parsing query like following.
SAMPLE# CALL# MAX_DEPTH
---------- ---------- ----------
100 4198 44
1 row selected.
Elapsed: 00:00:00.06
FNAME COUNT(*)
-------------------- ----------
_opiodr+1099 200
7C80B680 200
_apadrv+459 100
_kksLoadChild+5883 100
_kglpim+264 100
_kksParseCursor+143 100
_kkorrio+195 100
_ksdxfdmp+847 100
_ssthreadsrgruncall 100
_opimai_real+112 100
_apafdr+402 100
_kpooprx+232 100
_kksfbc+7232 100
_apakkoqb+151 100
_opidrv+819 100
_kglpin+1078 100
_kglobpn+1224 100
_kglobld+837 100
_rpiswu2+426 100
_kkoqbc+1689 100
_kkspsc0+2094 100
_kkslod+98 100
_sou2o+45 100
_opitca+1445 100
_ksdxcb+1481 100
_opiino+1087 100
_kpoal8+775 100
_opiosq0+1965 100
_apaqbd+383 100
00000000 100
_OracleOradebugThre 100
_ksedst_tracecb+55 100
_ttcpip+1273 100
_kkooqb+8292 100
_kxsGetRuntimeLock+ 100
__PGOSF359__kksFull 100
_opimai+92 100
_opitsk+1017 100
_OracleThreadStart@ 100
_apafjo+161 85
_apafjo+265 5
_apafjo+358 2
_apacjp+162 1
_apafbp+491 1
_apafjo+295 1
_apafbr+168 1
_apafbp+262 1
_apafbp+156 1
48 rows selected.
Elapsed: 00:00:00.14
SEQ IDX FNAME
---------- ---------- --------------------
1 42 7C80B680
1 41 _OracleThreadStart@
1 40 _opimai+92
1 39 _opimai_real+112
1 38 _sou2o+45
1 37 _opidrv+819
1 36 _opiodr+1099
1 35 _opiino+1087
1 34 _opitsk+1017
1 33 _ttcpip+1273
1 32 _opiodr+1099
1 31 _kpoal8+775
1 30 _kpooprx+232
1 29 _opiosq0+1965
1 28 _kksParseCursor+143
1 27 _kkspsc0+2094
1 26 _kksfbc+7232
1 25 _kxsGetRuntimeLock+
1 24 _kglpin+1078
1 23 _kglpim+264
1 22 _kglobpn+1224
1 21 _kglobld+837
1 20 _kkslod+98
1 19 _kksLoadChild+5883
1 18 _rpiswu2+426
1 17 __PGOSF359__kksFull
1 16 _opitca+1445
1 15 _apadrv+459
1 14 _apaqbd+383
1 13 _apakkoqb+151
1 12 _kkoqbc+1689
1 11 _kkooqb+8292
1 10 _kkorrio+195
1 9 _apafdr+402
1 8 _apafjo+161
1 7 00000000
1 6 7C80B680
1 5 _OracleOradebugThre
1 4 _ssthreadsrgruncall
1 3 _ksdxcb+1481
1 2 _ksdxfdmp+847
1 1 _ksedst_tracecb+55
42 rows selected.
Elapsed: 00:00:00.14
old 3: 100*(count(*)/&sample_count) as ratio,
new 3: 100*(count(*)/ 100) as ratio,
HIT# RATIO
---------- ----------
STACK
--------------------------------------------------------------------------------
85 85
->7C80B680->_OracleThreadStart@->_opimai+92->_opimai_real+112->_sou2o+45->_opidr
v+819->_opiodr+1099->_opiino+1087->_opitsk+1017->_ttcpip+1273->_opiodr+1099->_kp
oal8+775->_kpooprx+232->_opiosq0+1965->_kksParseCursor+143->_kkspsc0+2094->_kksf
bc+7232->_kxsGetRuntimeLock+->_kglpin+1078->_kglpim+264->_kglobpn+1224->_kglobld
+837->_kkslod+98->_kksLoadChild+5883->_rpiswu2+426->__PGOSF359__kksFull->_opitca
+1445->_apadrv+459->_apaqbd+383->_apakkoqb+151->_kkoqbc+1689->_kkooqb+8292->_kko
rrio+195->_apafdr+402->_apafjo+161->00000000->7C80B680->_OracleOradebugThre->_ss
threadsrgruncall->_ksdxcb+1481->_ksdxfdmp+847->_ksedst_tracecb+55
7 7
->7C80B680->_OracleThreadStart@->_opimai+92->_opimai_real+112->_sou2o+45->_opidr
v+819->_opiodr+1099->_opiino+1087->_opitsk+1017->_ttcpip+1273->_opiodr+1099->_kp
oal8+775->_kpooprx+232->_opiosq0+1965->_kksParseCursor+143->_kkspsc0+2094->_kksf
bc+7232->_kxsGetRuntimeLock+->_kglpin+1078->_kglpim+264->_kglobpn+1224->_kglobld
+837->_kkslod+98->_kksLoadChild+5883->_rpiswu2+426->__PGOSF359__kksFull->_opitca
+1445->_apadrv+459->_apaqbd+383->_apakkoqb+151->_kkoqbc+1689->_kkooqb+8292->_kko
rrio+195->_apafdr+402->00000000->7C80B680->_OracleOradebugThre->_ssthreadsrgrunc
all->_ksdxcb+1481->_ksdxfdmp+847->_ksedst_tracecb+55
2 2
->7C80B680->_OracleThreadStart@->_opimai+92->_opimai_real+112->_sou2o+45->_opidr
v+819->_opiodr+1099->_opiino+1087->_opitsk+1017->_ttcpip+1273->_opiodr+1099->_kp
oal8+775->_kpooprx+232->_opiosq0+1965->_kksParseCursor+143->_kkspsc0+2094->_kksf
bc+7232->_kxsGetRuntimeLock+->_kglpin+1078->_kglpim+264->_kglobpn+1224->_kglobld
+837->_kkslod+98->_kksLoadChild+5883->_rpiswu2+426->__PGOSF359__kksFull->_opitca
+1445->_apadrv+459->_apaqbd+383->_apakkoqb+151->_kkoqbc+1689->_kkooqb+8292->_kko
rrio+195->_apafdr+402->_apafjo+358->00000000->7C80B680->_OracleOradebugThre->_ss
threadsrgruncall->_ksdxcb+1481->_ksdxfdmp+847->_ksedst_tracecb+55
2 2
->7C80B680->_OracleThreadStart@->_opimai+92->_opimai_real+112->_sou2o+45->_opidr
v+819->_opiodr+1099->_opiino+1087->_opitsk+1017->_ttcpip+1273->_opiodr+1099->_kp
oal8+775->_kpooprx+232->_opiosq0+1965->_kksParseCursor+143->_kkspsc0+2094->_kksf
bc+7232->_kxsGetRuntimeLock+->_kglpin+1078->_kglpim+264->_kglobpn+1224->_kglobld
+837->_kkslod+98->_kksLoadChild+5883->_rpiswu2+426->__PGOSF359__kksFull->_opitca
+1445->_apadrv+459->_apaqbd+383->_apakkoqb+151->_kkoqbc+1689->_kkooqb+8292->_kko
rrio+195->_apafdr+402->_apafjo+265->00000000->7C80B680->_OracleOradebugThre->_ss
threadsrgruncall->_ksdxcb+1481->_ksdxfdmp+847->_ksedst_tracecb+55
1 1
->7C80B680->_OracleThreadStart@->_opimai+92->_opimai_real+112->_sou2o+45->_opidr
v+819->_opiodr+1099->_opiino+1087->_opitsk+1017->_ttcpip+1273->_opiodr+1099->_kp
oal8+775->_kpooprx+232->_opiosq0+1965->_kksParseCursor+143->_kkspsc0+2094->_kksf
bc+7232->_kxsGetRuntimeLock+->_kglpin+1078->_kglpim+264->_kglobpn+1224->_kglobld
+837->_kkslod+98->_kksLoadChild+5883->_rpiswu2+426->__PGOSF359__kksFull->_opitca
+1445->_apadrv+459->_apaqbd+383->_apakkoqb+151->_kkoqbc+1689->_kkooqb+8292->_kko
rrio+195->_apafdr+402->_apafjo+265->_apafbp+262->00000000->7C80B680->_OracleOrad
ebugThre->_ssthreadsrgruncall->_ksdxcb+1481->_ksdxfdmp+847->_ksedst_tracecb+55
1 1
->7C80B680->_OracleThreadStart@->_opimai+92->_opimai_real+112->_sou2o+45->_opidr
v+819->_opiodr+1099->_opiino+1087->_opitsk+1017->_ttcpip+1273->_opiodr+1099->_kp
oal8+775->_kpooprx+232->_opiosq0+1965->_kksParseCursor+143->_kkspsc0+2094->_kksf
bc+7232->_kxsGetRuntimeLock+->_kglpin+1078->_kglpim+264->_kglobpn+1224->_kglobld
+837->_kkslod+98->_kksLoadChild+5883->_rpiswu2+426->__PGOSF359__kksFull->_opitca
+1445->_apadrv+459->_apaqbd+383->_apakkoqb+151->_kkoqbc+1689->_kkooqb+8292->_kko
rrio+195->_apafdr+402->_apafjo+265->_apafbp+491->_apacjp+162->00000000->7C80B680
->_OracleOradebugThre->_ssthreadsrgruncall->_ksdxcb+1481->_ksdxfdmp+847->_ksedst
_tracecb+55
1 1
->7C80B680->_OracleThreadStart@->_opimai+92->_opimai_real+112->_sou2o+45->_opidr
v+819->_opiodr+1099->_opiino+1087->_opitsk+1017->_ttcpip+1273->_opiodr+1099->_kp
oal8+775->_kpooprx+232->_opiosq0+1965->_kksParseCursor+143->_kkspsc0+2094->_kksf
bc+7232->_kxsGetRuntimeLock+->_kglpin+1078->_kglpim+264->_kglobpn+1224->_kglobld
+837->_kkslod+98->_kksLoadChild+5883->_rpiswu2+426->__PGOSF359__kksFull->_opitca
+1445->_apadrv+459->_apaqbd+383->_apakkoqb+151->_kkoqbc+1689->_kkooqb+8292->_kko
rrio+195->_apafdr+402->_apafjo+265->_apafbp+156->_apafbr+168->00000000->7C80B680
->_OracleOradebugThre->_ssthreadsrgruncall->_ksdxcb+1481->_ksdxfdmp+847->_ksedst
_tracecb+55
1 1
->7C80B680->_OracleThreadStart@->_opimai+92->_opimai_real+112->_sou2o+45->_opidr
v+819->_opiodr+1099->_opiino+1087->_opitsk+1017->_ttcpip+1273->_opiodr+1099->_kp
oal8+775->_kpooprx+232->_opiosq0+1965->_kksParseCursor+143->_kkspsc0+2094->_kksf
bc+7232->_kxsGetRuntimeLock+->_kglpin+1078->_kglpim+264->_kglobpn+1224->_kglobld
+837->_kkslod+98->_kksLoadChild+5883->_rpiswu2+426->__PGOSF359__kksFull->_opitca
+1445->_apadrv+459->_apaqbd+383->_apakkoqb+151->_kkoqbc+1689->_kkooqb+8292->_kko
rrio+195->_apafdr+402->_apafjo+295->00000000->7C80B680->_OracleOradebugThre->_ss
threadsrgruncall->_ksdxcb+1481->_ksdxfdmp+847->_ksedst_tracecb+55
8 rows selected.
Elapsed: 00:00:06.95
Here you see that the most frequent functions to be called are “kko”, “kks”(compile) and “kgl”(library cache) related ones which strongly hints the possibility of the hard parse with many LCO being related.
Anyway, the insights given by Tanel Poder are always amazing and technically challenging.


