Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8b01a39

Browse files
authored
Merge pull request #1249 from utPLSQL/feature/framework_performance
Feature/framework performance
2 parents 7597905 + 6c0b6e6 commit 8b01a39

16 files changed

+244
-15
lines changed

source/api/ut.pkb

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,15 @@ create or replace package body ut is
222222
raise_if_packages_invalidated();
223223
raise no_data_found;
224224
end if;
225-
g_result_lines := ut_utils.clob_to_table(l_clob, ut_utils.gc_max_storage_varchar2_len);
226-
g_result_line_no := g_result_lines.first;
225+
if l_clob is not null and l_clob != empty_clob() then
226+
if length(l_clob) > ut_utils.gc_max_storage_varchar2_len then
227+
g_result_lines := ut_utils.clob_to_table(l_clob, ut_utils.gc_max_storage_varchar2_len);
228+
else
229+
g_result_lines := ut_varchar2_list(l_clob);
230+
end if;
231+
g_result_line_no := g_result_lines.first;
232+
end if;
227233
end if;
228-
229234
if g_result_line_no is not null then
230235
l_result := g_result_lines(g_result_line_no);
231236
g_result_line_no := g_result_lines.next(g_result_line_no);
@@ -273,6 +278,7 @@ create or replace package body ut is
273278
);
274279
if l_reporter is of (ut_output_reporter_base) then
275280
l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor();
281+
g_result_lines := ut_varchar2_list();
276282
loop
277283
pipe row( get_report_outputs( l_results ) );
278284
end loop;
@@ -320,6 +326,7 @@ create or replace package body ut is
320326
);
321327
if l_reporter is of (ut_output_reporter_base) then
322328
l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor();
329+
g_result_lines := ut_varchar2_list();
323330
loop
324331
pipe row( get_report_outputs( l_results ) );
325332
end loop;
@@ -368,6 +375,7 @@ create or replace package body ut is
368375
);
369376
if l_reporter is of (ut_output_reporter_base) then
370377
l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor();
378+
g_result_lines := ut_varchar2_list();
371379
loop
372380
pipe row( get_report_outputs( l_results ) );
373381
end loop;
@@ -416,6 +424,7 @@ create or replace package body ut is
416424
);
417425
if l_reporter is of (ut_output_reporter_base) then
418426
l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor();
427+
g_result_lines := ut_varchar2_list();
419428
loop
420429
pipe row( get_report_outputs( l_results ) );
421430
end loop;
@@ -464,6 +473,7 @@ create or replace package body ut is
464473
);
465474
if l_reporter is of (ut_output_reporter_base) then
466475
l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor();
476+
g_result_lines := ut_varchar2_list();
467477
loop
468478
pipe row( get_report_outputs( l_results ) );
469479
end loop;
@@ -512,6 +522,7 @@ create or replace package body ut is
512522
);
513523
if l_reporter is of (ut_output_reporter_base) then
514524
l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor();
525+
g_result_lines := ut_varchar2_list();
515526
loop
516527
pipe row( get_report_outputs( l_results ) );
517528
end loop;
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
create or replace type body ut_output_bulk_buffer is
2+
/*
3+
utPLSQL - Version 3
4+
Copyright 2016 - 2023 utPLSQL Project
5+
6+
Licensed under the Apache License, Version 2.0 (the "License"):
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
constructor function ut_output_bulk_buffer(self in out nocopy ut_output_bulk_buffer, a_output_id raw := null) return self as result is
20+
begin
21+
self.init(a_output_id, $$plsql_unit);
22+
return;
23+
end;
24+
25+
overriding member procedure send_line(self in out nocopy ut_output_bulk_buffer, a_text varchar2, a_item_type varchar2 := null) is
26+
pragma autonomous_transaction;
27+
begin
28+
if a_text is not null or a_item_type is not null then
29+
if length(a_text) > ut_utils.gc_max_storage_varchar2_len then
30+
self.send_lines(
31+
ut_utils.convert_collection(
32+
ut_utils.clob_to_table(a_text, ut_utils.gc_max_storage_varchar2_len)
33+
),
34+
a_item_type
35+
);
36+
else
37+
self.last_write_message_id := self.last_write_message_id + 1;
38+
insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type)
39+
values (self.output_id, self.last_write_message_id, a_text, a_item_type);
40+
end if;
41+
commit;
42+
end if;
43+
end;
44+
45+
overriding member procedure send_lines(self in out nocopy ut_output_bulk_buffer, a_text_list ut_varchar2_rows, a_item_type varchar2 := null) is
46+
pragma autonomous_transaction;
47+
begin
48+
insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type)
49+
select /*+ no_parallel */ self.output_id, self.last_write_message_id + rownum, t.column_value, a_item_type
50+
from table(a_text_list) t
51+
where t.column_value is not null or a_item_type is not null;
52+
self.last_write_message_id := self.last_write_message_id + sql%rowcount;
53+
commit;
54+
end;
55+
56+
overriding member procedure send_clob(self in out nocopy ut_output_bulk_buffer, a_text clob, a_item_type varchar2 := null) is
57+
pragma autonomous_transaction;
58+
begin
59+
if a_text is not null and a_text != empty_clob() or a_item_type is not null then
60+
if length(a_text) > ut_utils.gc_max_storage_varchar2_len then
61+
self.send_lines(
62+
ut_utils.convert_collection(
63+
ut_utils.clob_to_table(a_text, ut_utils.gc_max_storage_varchar2_len)
64+
),
65+
a_item_type
66+
);
67+
else
68+
self.last_write_message_id := self.last_write_message_id + 1;
69+
insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type)
70+
values (self.output_id, self.last_write_message_id, a_text, a_item_type);
71+
end if;
72+
commit;
73+
end if;
74+
end;
75+
76+
overriding member procedure lines_to_dbms_output(self in ut_output_bulk_buffer, a_initial_timeout number := null, a_timeout_sec number := null) is
77+
l_data sys_refcursor;
78+
l_text ut_varchar2_rows;
79+
l_item_type ut_varchar2_rows;
80+
begin
81+
l_data := self.get_lines_cursor(a_initial_timeout, a_timeout_sec);
82+
loop
83+
fetch l_data bulk collect into l_text, l_item_type limit 10000;
84+
for idx in 1 .. l_text.count loop
85+
dbms_output.put_line(l_text(idx));
86+
end loop;
87+
exit when l_data%notfound;
88+
end loop;
89+
close l_data;
90+
self.remove_buffer_info();
91+
end;
92+
93+
overriding member function get_lines_cursor(a_initial_timeout number := null, a_timeout_sec number := null) return sys_refcursor is
94+
lc_init_wait_sec constant number := coalesce(a_initial_timeout, 10 );
95+
l_already_waited_sec number(10,2) := 0;
96+
l_sleep_time number(2,1);
97+
l_exists integer;
98+
l_finished boolean := false;
99+
l_data_produced boolean := false;
100+
l_producer_active boolean := false;
101+
l_producer_started boolean := false;
102+
l_producer_finished boolean := false;
103+
l_results sys_refcursor;
104+
begin
105+
106+
while not l_finished loop
107+
108+
if not l_data_produced then
109+
select /*+ no_parallel */ count(1) into l_exists
110+
from ut_output_buffer_tmp o
111+
where o.output_id = self.output_id and rownum = 1;
112+
l_data_produced := (l_exists = 1);
113+
end if;
114+
115+
l_sleep_time := case when l_already_waited_sec >= 1 then 0.5 else 0.1 end;
116+
l_producer_active := (self.get_lock_status() <> 0);
117+
l_producer_started := (l_producer_active or l_data_produced ) or l_producer_started;
118+
l_producer_finished := (l_producer_started and not l_producer_active) or l_producer_finished;
119+
l_finished :=
120+
self.timeout_producer_not_finished(l_producer_finished, l_already_waited_sec, a_timeout_sec)
121+
or self.timeout_producer_not_started(l_producer_started, l_already_waited_sec, lc_init_wait_sec)
122+
or l_producer_finished;
123+
124+
dbms_lock.sleep(l_sleep_time);
125+
l_already_waited_sec := l_already_waited_sec + l_sleep_time;
126+
end loop;
127+
128+
open l_results for
129+
select /*+ no_parallel */ o.text, o.item_type
130+
from ut_output_buffer_tmp o
131+
where o.output_id = self.output_id
132+
and o.text is not null
133+
order by o.output_id, o.message_id;
134+
135+
return l_results;
136+
137+
end;
138+
139+
/* Important note.
140+
This function code is almost duplicated between two types for performance reasons.
141+
The pipe row clause is much faster on VARCHAR2 then it is on clob.
142+
That is the key reason for two implementations.
143+
*/
144+
overriding member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined is
145+
l_data sys_refcursor;
146+
l_text ut_varchar2_rows;
147+
l_item_type ut_varchar2_rows;
148+
begin
149+
l_data := self.get_lines_cursor(a_initial_timeout, a_timeout_sec);
150+
loop
151+
fetch l_data bulk collect into l_text, l_item_type limit 10000;
152+
for idx in 1 .. l_text.count loop
153+
pipe row( ut_output_data_row(l_text(idx), l_item_type(idx)) );
154+
end loop;
155+
exit when l_data%notfound;
156+
end loop;
157+
close l_data;
158+
self.remove_buffer_info();
159+
return;
160+
end;
161+
162+
end;
163+
/
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
create or replace type ut_output_bulk_buffer under ut_output_buffer_base (
2+
/*
3+
utPLSQL - Version 3
4+
Copyright 2016 - 2023 utPLSQL Project
5+
6+
Licensed under the Apache License, Version 2.0 (the "License"):
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
constructor function ut_output_bulk_buffer(self in out nocopy ut_output_bulk_buffer, a_output_id raw := null) return self as result,
20+
overriding member procedure send_line(self in out nocopy ut_output_bulk_buffer, a_text varchar2, a_item_type varchar2 := null),
21+
overriding member procedure send_lines(self in out nocopy ut_output_bulk_buffer, a_text_list ut_varchar2_rows, a_item_type varchar2 := null),
22+
overriding member procedure send_clob(self in out nocopy ut_output_bulk_buffer, a_text clob, a_item_type varchar2 := null),
23+
overriding member procedure lines_to_dbms_output(self in ut_output_bulk_buffer, a_initial_timeout number := null, a_timeout_sec number := null),
24+
overriding member function get_lines_cursor(a_initial_timeout number := null, a_timeout_sec number := null) return sys_refcursor,
25+
overriding member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined
26+
) not final
27+
/

source/core/output_buffers/ut_output_table_buffer.tpb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,16 @@ create or replace type body ut_output_table_buffer is
7575

7676
overriding member procedure lines_to_dbms_output(self in ut_output_table_buffer, a_initial_timeout number := null, a_timeout_sec number := null) is
7777
l_data sys_refcursor;
78-
l_text varchar2(32767);
79-
l_item_type varchar2(32767);
78+
l_text ut_varchar2_rows;
79+
l_item_type ut_varchar2_rows;
8080
begin
8181
l_data := self.get_lines_cursor(a_initial_timeout, a_timeout_sec);
8282
loop
83-
fetch l_data into l_text, l_item_type;
83+
fetch l_data bulk collect into l_text, l_item_type limit 10000;
84+
for idx in 1 .. l_text.count loop
85+
dbms_output.put_line(l_text(idx));
86+
end loop;
8487
exit when l_data%notfound;
85-
dbms_output.put_line(l_text);
8688
end loop;
8789
close l_data;
8890
end;

source/core/ut_utils.pkb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,7 @@ create or replace package body ut_utils is
570570
end loop;
571571
exit when l_lines_data%notfound;
572572
end loop;
573+
close l_lines_data;
573574
execute immediate 'truncate table ut_dbms_output_cache';
574575
commit;
575576
end;

source/install.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ create or replace context &&ut3_owner._info using &&ut3_owner..ut_session_contex
120120
@@install_component.sql 'core/output_buffers/ut_output_table_buffer.tpb'
121121
@@install_component.sql 'core/output_buffers/ut_output_clob_table_buffer.tps'
122122
@@install_component.sql 'core/output_buffers/ut_output_clob_table_buffer.tpb'
123+
@@install_component.sql 'core/output_buffers/ut_output_bulk_buffer.tps'
124+
@@install_component.sql 'core/output_buffers/ut_output_bulk_buffer.tpb'
123125

124126
@@install_component.sql 'core/types/ut_output_reporter_base.tps'
125127

source/reporters/ut_coverage_cobertura_reporter.tpb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ create or replace type body ut_coverage_cobertura_reporter is
2020
self in out nocopy ut_coverage_cobertura_reporter
2121
) return self as result is
2222
begin
23-
self.init($$plsql_unit);
23+
self.init($$plsql_unit,ut_output_bulk_buffer());
2424
return;
2525
end;
2626

source/reporters/ut_coverage_html_reporter.tpb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ create or replace type body ut_coverage_html_reporter is
2222
a_html_report_assets_path varchar2 := null
2323
) return self as result is
2424
begin
25-
self.init($$plsql_unit);
25+
self.init($$plsql_unit,ut_output_bulk_buffer());
2626
self.project_name := a_project_name;
2727
assets_path := nvl(a_html_report_assets_path, ut_coverage_report_html_helper.get_default_html_assets_path());
2828
return;

source/reporters/ut_coverage_sonar_reporter.tpb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ create or replace type body ut_coverage_sonar_reporter is
2020
self in out nocopy ut_coverage_sonar_reporter
2121
) return self as result is
2222
begin
23-
self.init($$plsql_unit);
23+
self.init($$plsql_unit,ut_output_bulk_buffer());
2424
return;
2525
end;
2626

@@ -84,6 +84,12 @@ create or replace type body ut_coverage_sonar_reporter is
8484
end;
8585

8686
begin
87+
-- execute immediate 'alter session set statistics_level=all';
88+
-- dbms_hprof.start_profiling(
89+
-- location => 'PLSHPROF_DIR'
90+
-- , filename => 'profiler_utPLSQL_run_on_'||$$plsql_unit||'_'||rawtohex(self.id)||'.txt'
91+
-- );
92+
--
8793
ut_coverage.coverage_stop();
8894

8995
self.print_text_lines(
@@ -92,6 +98,7 @@ create or replace type body ut_coverage_sonar_reporter is
9298
a_run
9399
)
94100
);
101+
-- dbms_hprof.stop_profiling;
95102
end;
96103

97104
overriding member function get_description return varchar2 as

source/reporters/ut_coveralls_reporter.tpb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ create or replace type body ut_coveralls_reporter is
2020
self in out nocopy ut_coveralls_reporter
2121
) return self as result is
2222
begin
23-
self.init($$plsql_unit);
23+
self.init($$plsql_unit,ut_output_bulk_buffer());
2424
return;
2525
end;
2626

0 commit comments

Comments
 (0)