In the interests of good science, and I wanted to chat about it at next week's Office Hours, I wanted to repeat this test.
I had a little difficulty working out how I got the metrics, I think APEX debugging has changed a little since I ran the test. Instead I considered looking at v$sqlarea to assess performance.
Turns out I quickly found the relevant queries using the following SQL, which a case statement to help me identify the difference between rows each time
select case when sql_text like 'begin declare begin wwv_flow_plugin_api.%' then 'API' when sql_text like 'begin declare function x return varchar2 is begin return null; %' then 'call dynamic' when sql_text like 'begin declare FUNCTION enkitec_sparkline_render%' then 'parse dynamic' when module = 'SQL Developer' then ' me' end which ,executions ,loads ,parse_calls ,disk_reads ,buffer_gets ,user_io_wait_time ,plsql_exec_time ,rows_processed ,cpu_time ,elapsed_time ,physical_read_requests ,physical_read_bytes ,lockeD_total ,pinned_total ,sql_text from v$sqlarea where sql_text like '%sparkline%' order by whichWhen APEX invoked the code using an API call, it looked like
begin declare begin wwv_flow_plugin_api.g_dynamic_action_render_result := apx_plug_sparkline.render (p_dynamic_action => wwv_flow_plugin_api.g_dynamic_action,p_plugin => wwv_flow_plugin_api.g_plugin );end; end;
When APEX needed to parse the entire function, it looked like
begin declare FUNCTION enkitec_sparkline_render ( p_dynamic_action IN APEX_PLUGIN.T_DYNAMIC_ACTION, p_plugin IN APEX_PLUGIN.T_PLUGIN ) RETURN APEX_PLUGIN.T_DYNAMIC_ACTION_RENDER_RESULT IS
To do this test, all I needed to do was paste the PL/SQL back into the source attribute; I didn’t bother changing what was invoked in the callback fields.
After 50 page refreshes each in dev – parsing the code was at least twice as slow, based on CPU time.
I suspect the 'call dynamic' was the builder validating the code.
Basic glimpse |
In an environment with more activity, I was able to compare the standard API call with a few hundred that included parsing the code.
Click/tap to embiggen |
If I take 141312 CPU time, divide by 301, then multiply by 17778, I get parsing around 1.8x the amount time as using the API.
The same goes for elapsed time, while the PLSQL Execution time remains the same.
Plus there’s disk reads, an obscene amount of buffer gets, considering the execution ratio.
I tried a second plugin (nested reports), and while the CPU ratio seemed the same, the physical reads were over twice as high.
Remembering this is just placing the code in the box – I haven’t even referenced it.
Too many words and numbers? How about a graph.
If this seems a fair reason to reduce the amount of interpreted code you have…
Twice the work, for nothing. |
... then how does this make you feel?
What's a buffer, and why do we want to get it? |
It seems by removing the code from the source attribute of the plugin, we measurably reduce the amount of work the database does. Imagine if we reduce our PL/SQL usage throughout the application?
So I conclude
- Use bind variables
- Put your code in packages
No comments:
Post a Comment