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

Skip to content

Commit cc491cf

Browse files
committed
Enhance annotation parser with new tests and source line handling functions
1 parent 8105179 commit cc491cf

5 files changed

Lines changed: 930 additions & 9 deletions

File tree

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
-- Annotation Manager Volume Benchmark
2+
-- 1000 generated packages, cold cache per iteration
3+
4+
set serveroutput on size unlimited
5+
set timing off
6+
set feedback off
7+
8+
declare
9+
c_packages constant pls_integer := 1000;
10+
c_procs_per_pkg constant pls_integer := 20;
11+
c_contexts_per_pkg constant pls_integer := 4;
12+
c_pkg_prefix constant varchar2(20) := 'TST_GEN_PKG_';
13+
c_iterations constant pls_integer := 4;
14+
c_perf_threshold constant number := 0.80;
15+
16+
l_baseline_total_ms number := 0;
17+
l_new_total_ms number := 0;
18+
l_start timestamp;
19+
l_elapsed interval day to second;
20+
21+
-- Source holders
22+
l_source_lines dbms_preprocessor.source_lines_t;
23+
l_source_clob clob;
24+
l_result ut_annotations;
25+
26+
-- Correctness tracking
27+
l_missing_from_cache pls_integer := 0;
28+
l_count_mismatches pls_integer := 0;
29+
l_mismatch_detail varchar2(32767);
30+
31+
-- Cache check
32+
l_cursor sys_refcursor;
33+
l_annotated_obj ut_annotated_object;
34+
l_name varchar2(128);
35+
l_annotations ut_annotations;
36+
l_cache_count pls_integer := 0;
37+
38+
-- Per-package timing
39+
l_pkg_baseline_ms number;
40+
l_pkg_new_ms number;
41+
l_pkg varchar2(30);
42+
l_ratio number;
43+
44+
-- Expected annotation count — mirrors generator logic exactly
45+
function expected_annotation_count(
46+
a_pkg_number pls_integer,
47+
a_procs pls_integer,
48+
a_contexts pls_integer
49+
) return pls_integer is
50+
l_count pls_integer := 0;
51+
begin
52+
l_count := l_count + 2; -- %suite + %suitepath
53+
l_count := l_count + 2; -- %beforeall + %afterall
54+
l_count := l_count + 2; -- %beforeeach + %aftereach
55+
56+
-- package level conditional
57+
if mod(a_pkg_number, 3) = 0 then l_count := l_count + 1; end if; -- %displayname
58+
if mod(a_pkg_number, 5) = 0 then l_count := l_count + 1; end if; -- %rollback
59+
60+
-- contexts: each contributes %context + %endcontext
61+
l_count := l_count + (a_contexts * 2);
62+
63+
-- per procedure
64+
for i in 1 .. a_procs loop
65+
l_count := l_count + 1; -- %test
66+
if mod(i, 3) = 0 then l_count := l_count + 1; end if; -- %tags
67+
if mod(i, 6) = 0 then l_count := l_count + 1; end if; -- %throws
68+
if mod(i, 8) = 0 then l_count := l_count + 1; end if; -- %disabled
69+
if mod(i, 5) = 0 then l_count := l_count + 2; end if; -- %beforetest + %aftertest
70+
end loop;
71+
72+
return l_count;
73+
end expected_annotation_count;
74+
75+
begin
76+
dbms_output.put_line('Packages : ' || c_packages);
77+
dbms_output.put_line('Procs/pkg : ' || c_procs_per_pkg);
78+
dbms_output.put_line('Contexts/pkg: ' || c_contexts_per_pkg);
79+
dbms_output.put_line('Iterations : ' || c_iterations);
80+
dbms_output.put_line('Started : ' || to_char(systimestamp,'YYYY-MM-DD HH24:MI:SS.FF3'));
81+
82+
-- Phase 1: Performance benchmark (cold cache per package per iteration)
83+
dbms_output.put_line(chr(10) || '-- Phase 1: Performance --');
84+
dbms_output.put_line(
85+
rpad('package', 20) || ' | ' ||
86+
lpad('baseline_ms', 11) || ' | ' ||
87+
lpad('new_ms', 6) || ' | ' ||
88+
lpad('ratio', 5) || ' | ' ||
89+
'status'
90+
);
91+
dbms_output.put_line(rpad('-', 70, '-'));
92+
93+
for p in 1 .. c_packages loop
94+
l_pkg := c_pkg_prefix || lpad(p, 4, '0');
95+
96+
-- load source once per package
97+
l_source_lines := dbms_preprocessor.get_post_processed_source(
98+
object_type => 'PACKAGE',
99+
schema_name => user,
100+
object_name => l_pkg
101+
);
102+
103+
dbms_lob.createtemporary(l_source_clob, true);
104+
for i in 1 .. l_source_lines.count loop
105+
dbms_lob.writeappend(l_source_clob, length(l_source_lines(i)), l_source_lines(i));
106+
end loop;
107+
108+
-- baseline: clob version
109+
l_pkg_baseline_ms := 0;
110+
for iter in 1 .. c_iterations loop
111+
ut_annotation_manager.purge_cache(user, 'PACKAGE');
112+
l_start := systimestamp;
113+
l_result := ut_annotation_parser.parse_object_annotations(l_source_clob);
114+
l_elapsed := systimestamp - l_start;
115+
l_pkg_baseline_ms := l_pkg_baseline_ms +
116+
extract(second from l_elapsed) * 1000;
117+
end loop;
118+
l_pkg_baseline_ms := l_pkg_baseline_ms / c_iterations;
119+
120+
-- new: source_lines_t version
121+
l_pkg_new_ms := 0;
122+
for iter in 1 .. c_iterations loop
123+
ut_annotation_manager.purge_cache(user, 'PACKAGE');
124+
l_start := systimestamp;
125+
l_result := ut_annotation_parser.parse_object_annotations(l_source_lines);
126+
l_elapsed := systimestamp - l_start;
127+
l_pkg_new_ms := l_pkg_new_ms +
128+
extract(second from l_elapsed) * 1000;
129+
end loop;
130+
l_pkg_new_ms := l_pkg_new_ms / c_iterations;
131+
132+
-- accumulate
133+
l_baseline_total_ms := l_baseline_total_ms + l_pkg_baseline_ms;
134+
l_new_total_ms := l_new_total_ms + l_pkg_new_ms;
135+
136+
l_ratio := round(l_pkg_new_ms / nullif(l_pkg_baseline_ms, 0), 3);
137+
138+
-- print every 100 packages to avoid flooding output
139+
if mod(p, 100) = 0 or p = 1 then
140+
dbms_output.put_line(
141+
rpad(l_pkg, 20) || ' | ' ||
142+
lpad(round(l_pkg_baseline_ms, 3), 11) || ' | ' ||
143+
lpad(round(l_pkg_new_ms, 3), 6) || ' | ' ||
144+
lpad(l_ratio, 5) || ' | ' ||
145+
case when l_ratio <= c_perf_threshold
146+
then 'PASS (' || round((1-l_ratio)*100,1) || '% faster)'
147+
else 'SLOW (ratio=' || l_ratio || ')'
148+
end
149+
);
150+
end if;
151+
152+
dbms_lob.freetemporary(l_source_clob);
153+
end loop;
154+
155+
-- -------------------------------------------------------------------------
156+
-- Phase 1 summary
157+
-- -------------------------------------------------------------------------
158+
l_ratio := round(l_new_total_ms / nullif(l_baseline_total_ms, 0), 3);
159+
160+
dbms_output.put_line(rpad('-', 70, '-'));
161+
dbms_output.put_line('Baseline total ms : ' || round(l_baseline_total_ms, 3));
162+
dbms_output.put_line('New total ms : ' || round(l_new_total_ms, 3));
163+
dbms_output.put_line('Overall ratio : ' || l_ratio);
164+
dbms_output.put_line('Improvement : ' || round((1 - l_ratio) * 100, 1) || '%');
165+
166+
-- Phase 2: Cache presence check
167+
dbms_output.put_line(chr(10) || '-- Phase 2: Cache presence --');
168+
169+
ut_annotation_manager.purge_cache(user, 'PACKAGE');
170+
ut_annotation_manager.rebuild_annotation_cache(user, 'PACKAGE');
171+
172+
-- query cache tables directly to avoid validate_annotation_cache side effects
173+
open l_cursor for
174+
select ut_annotated_object(
175+
i.object_owner, i.object_name, i.object_type, i.parse_time,
176+
cast(
177+
collect(
178+
ut_annotation(
179+
c.annotation_position, c.annotation_name,
180+
c.annotation_text, c.subobject_name
181+
) order by c.annotation_position
182+
) as ut_annotations
183+
)
184+
)
185+
from ut_annotation_cache_info i
186+
join ut_annotation_cache c on i.cache_id = c.cache_id
187+
where i.object_owner = user
188+
and i.object_type = 'PACKAGE'
189+
and i.object_name like c_pkg_prefix || '%'
190+
group by i.object_owner, i.object_type, i.object_name, i.parse_time;
191+
192+
loop
193+
fetch l_cursor into l_annotated_obj;
194+
exit when l_cursor%notfound;
195+
l_cache_count := l_cache_count + 1;
196+
end loop;
197+
close l_cursor;
198+
199+
dbms_output.put_line('Expected in cache : ' || c_packages);
200+
dbms_output.put_line('Found in cache : ' || l_cache_count);
201+
dbms_output.put_line('Cache check : ' ||
202+
case when l_cache_count = c_packages
203+
then 'PASS — all ' || c_packages || ' packages found in cache'
204+
else 'FAIL — missing ' || (c_packages - l_cache_count) || ' packages from cache'
205+
end
206+
);
207+
208+
-- Phase 3: Annotation count correctness
209+
dbms_output.put_line(chr(10) || '-- Phase 3: Annotation count correctness --');
210+
211+
-- reopen same direct cache query for correctness check
212+
open l_cursor for
213+
select ut_annotated_object(
214+
i.object_owner, i.object_name, i.object_type, i.parse_time,
215+
cast(
216+
collect(
217+
ut_annotation(
218+
c.annotation_position, c.annotation_name,
219+
c.annotation_text, c.subobject_name
220+
) order by c.annotation_position
221+
) as ut_annotations
222+
)
223+
)
224+
from ut_annotation_cache_info i
225+
join ut_annotation_cache c on i.cache_id = c.cache_id
226+
where i.object_owner = user
227+
and i.object_type = 'PACKAGE'
228+
and i.object_name like c_pkg_prefix || '%'
229+
group by i.object_owner, i.object_type, i.object_name, i.parse_time;
230+
231+
loop
232+
fetch l_cursor into l_annotated_obj;
233+
exit when l_cursor%notfound;
234+
l_name := l_annotated_obj.object_name;
235+
l_annotations := l_annotated_obj.annotations;
236+
237+
declare
238+
l_pkg_number pls_integer;
239+
l_expected pls_integer;
240+
begin
241+
l_pkg_number := to_number(substr(l_name, length(c_pkg_prefix) + 1));
242+
l_expected := expected_annotation_count(
243+
l_pkg_number,
244+
c_procs_per_pkg,
245+
c_contexts_per_pkg
246+
);
247+
248+
if l_annotations.count != l_expected then
249+
l_count_mismatches := l_count_mismatches + 1;
250+
if l_count_mismatches <= 10 then
251+
l_mismatch_detail := l_mismatch_detail || chr(10) ||
252+
' ' || l_name ||
253+
': expected=' || l_expected ||
254+
' actual=' || l_annotations.count;
255+
end if;
256+
end if;
257+
end;
258+
end loop;
259+
close l_cursor;
260+
261+
dbms_output.put_line('Packages checked : ' || c_packages);
262+
dbms_output.put_line('Count mismatches : ' || l_count_mismatches);
263+
if l_count_mismatches > 0 then
264+
dbms_output.put_line('Mismatch detail (first 10):' || l_mismatch_detail);
265+
end if;
266+
dbms_output.put_line('Count check : ' ||
267+
case when l_count_mismatches = 0
268+
then 'PASS — all annotation counts match expected'
269+
else 'FAIL — ' || l_count_mismatches || ' packages have wrong annotation count'
270+
end
271+
);
272+
273+
dbms_output.put_line(chr(10) || '=================================================');
274+
dbms_output.put_line('FINAL RESULTS');
275+
dbms_output.put_line('=================================================');
276+
dbms_output.put_line('Performance : ' ||
277+
case when l_ratio <= c_perf_threshold then 'PASS' else 'FAIL' end);
278+
dbms_output.put_line('Cache : ' ||
279+
case when l_cache_count = c_packages then 'PASS' else 'FAIL' end);
280+
dbms_output.put_line('Counts : ' ||
281+
case when l_count_mismatches = 0 then 'PASS' else 'FAIL' end);
282+
dbms_output.put_line('Overall : ' ||
283+
case when l_ratio <= c_perf_threshold
284+
and l_cache_count = c_packages
285+
and l_count_mismatches = 0
286+
then 'PASS'
287+
else 'FAIL'
288+
end
289+
);
290+
dbms_output.put_line('Finished : ' ||
291+
to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS.FF3'));
292+
dbms_output.put_line('=================================================');
293+
294+
-- cleanup
295+
ut_annotation_manager.purge_cache(user, 'PACKAGE');
296+
297+
end;
298+
/

0 commit comments

Comments
 (0)