Skip to content

[improvement](topn) Use strict bounds for single-key TopN runtime filters - #69776

Open
jacktengg wants to merge 1 commit into
apache:masterfrom
jacktengg:arm-perf
Open

jacktengg wants to merge 1 commit into
apache:masterfrom
jacktengg:arm-perf

Conversation

@jacktengg

@jacktengg jacktengg commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #xxx

Related PR: #xxx

Problem Summary:

TopN runtime filters retain rows equal to the current boundary. For Heap TopN
with one actual sort key, these rows cannot improve the result after the heap
has retained LIMIT + OFFSET candidates.

Select LT or GT bounds in BE for a Heap TopN with one sort key. Keep LE or GE
bounds for multiple sort keys. Apply the selected mode to storage predicates,
column expressions, raw values, dictionary evaluation, and external predicate
conversion. Preserve NULL ordering and support scan preparation before source
initialization.

Source detection preserves existing bounds. Recursive rebuild resets bounds before the next execution.
Clear the bounds and nested storage predicates when a recursive fragment is
rebuilt, because the new heap has no candidates to support the old bound.

Require null propagation when FE pushes a TopN filter through the left side of
a right or full outer join. Otherwise, removing a matching boundary row can
create a NULL-extended row whose expression value sorts before the boundary.
For example, COALESCE(a.k, -1) can produce -1 after the filter removes a.k = 10.

Release note

Heap TopN runtime filters with one sort key can discard rows equal to the
boundary. Multiple sort keys retain inclusive bounds.

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • No need to test or manual test. Explain why:
      • This is a refactor/code format and no logic has been changed.
      • Previous test can cover this change.
      • No code files have been changed.
      • Other reason
  • Behavior changed:

    • No.
    • Yes.
  • Does this need documentation?

    • No.
    • Yes.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

@jacktengg
jacktengg requested a review from morrySnow as a code owner October 28, 2026 12:49
@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@jacktengg

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed all 20 changed files at d6b4f79. No actionable newly introduced defects were verified. The review converged after 1 round: both complete-review scopes and the additional risk-focused scope returned NO_NEW_VALUABLE_FINDINGS, and every initial risk received an evidence-backed disposition. There are no existing inline findings to carry forward. No additional user focus was supplied.

Critical checkpoint conclusions:

  • Goal and evidence: the changes implement stricter eligible single-key TopN bounds, preserve shared predicates during static key normalization, and refresh unread page ranges. Added FE, BE and regression tests cover the central behavior; they were inspected, not executed. The reported performance improvement was not independently measured.
  • Scope and reuse: the implementation stays within that filtering path and reuses comparison predicates, descriptor transport, RowRanges and existing Zone Map APIs.
  • Concurrency and locks: runtime-bound publication uses RuntimePredicate's lock; SharedPredicate pairs its version and immutable nested predicate under its own lock. Snapshots retain the comparison after unlocking, so page metadata reads do not hold the publication lock. No new reverse lock acquisition was found; cursor/progress state is iterator-local.
  • Lifecycle and memory: shared clones retain the live predicate, snapshots own their old bound, and the old roaring cursor is destroyed before bitmap replacement. Heap and storage producers retain enough candidates before publishing; recursive target recreation was traced. No new static initialization dependency or ownership cycle was identified.
  • Configuration: no new configuration item or dynamic-update obligation is introduced.
  • Compatibility: no storage-format change is introduced. Absent strictness flags retain inclusive behavior on new BE; old BE ignores the optional field.
  • Thrift IDs: the full touched TTopnFilterDesc was compared with current branch-3.1, 4.0, 4.1 and 4.2 definitions. Fields 1-4 retain their meanings, and field 5 is unused there and optional with a false default. The inspected branch refs match live GitHub refs.
  • Parallel paths: reviewed heap and storage TopN producers, parallel heaps, expression/column/raw/dictionary evaluation, index paths, and forward/reverse scans. Unsupported Zone Map adapters conservatively retain full ranges; schema gating remains in place.
  • Conditional checks: direct-scan/single-key/SlotRef eligibility preserves the retained-candidate argument; multi-key and intervening operators remain inclusive. Refresh intersects existing restrictions and excludes consumed rows before rebuilding; the first update and subsequent throttle have explicit behavior.
  • Test coverage: inspected eligibility and missing-flag tests, strict scalar/binary/dictionary/null comparisons, key-range preservation, late bounds, both scan directions, partial-page restarts, holes, threshold, EOF and snapshot concurrency. The added fixtures are not exhaustive across all types and adapters; reachable implementation paths were reviewed statically.
  • Expected results: all 28 new regression output sections were checked against the generated data and SQL ordering/offset through static calculation. Queries have explicit ordering. Whether output files were generated by the prescribed harness cannot be proved from the checkout.
  • Observability: existing raw-row/page counters and Zone Map timers, together with runtime-range filtered-row accounting, expose the changed behavior. No additional logging requirement was identified.
  • Transactions and persistence: no transaction, EditLog, replay or persistent metadata path changes; visible-version and delete-bitmap rules are unchanged. Range refresh preserves existing row restrictions.
  • Writes and crash behavior: no data-write or commit path is modified. New metadata-read errors propagate through Status; no new write atomicity obligation arises.
  • FE-to-BE propagation: both Coordinator and ThriftPlansBuilder use the updated TopnFilter serializer, and RuntimePredicate consumes the optional flag. Comparison function/opcode selection is consistent across the changed evaluators.
  • Performance: the unchanged-version path avoids range work, later updates are throttled by raw rows, and immutable snapshots move metadata work outside the producer lock. A refresh copies the remaining bitmap and examines page metadata; no benchmark or latency conclusion is claimed.
  • Other issues and remaining questions: no unresolved candidate or uncovered required static-review scope remains. Builds, tests, sanitizers, runtime behavior, mixed-version execution and binary compatibility artifacts were not exercised under this static-only contract.

Review converged after 1 round(s).

@jacktengg

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor

Cloud UT Coverage Report

Increment line coverage 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.65% (2101/2741)
Line Coverage 65.98% (38769/58759)
Region Coverage 53.74% (36396/67729)
Branch Coverage 57.19% (11844/20710)

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 28514 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit d6b4f794c9b0edd937f3f243491ef9fa4d15f9d7, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17387	5130	5058	5058
q2	2126	317	252	252
q3	10193	1403	822	822
q4	4676	464	335	335
q5	7455	804	525	525
q6	186	182	150	150
q7	749	797	608	608
q8	9277	1322	1029	1029
q9	5535	4225	4195	4195
q10	6838	1294	1036	1036
q11	436	238	232	232
q12	642	400	276	276
q13	18103	3572	3060	3060
q14	275	271	246	246
q15	q16	727	704	662	662
q17	1194	755	583	583
q18	7063	6425	6108	6108
q19	1113	954	584	584
q20	381	343	227	227
q21	5264	2337	2261	2261
q22	349	293	265	265
Total cold run time: 99969 ms
Total hot run time: 28514 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5609	5608	5596	5596
q2	679	562	533	533
q3	5224	5364	4946	4946
q4	1994	2154	1562	1562
q5	5268	5154	5731	5154
q6	265	205	161	161
q7	2275	2023	1853	1853
q8	3074	2671	2716	2671
q9	8170	8012	7956	7956
q10	3722	3883	3247	3247
q11	609	453	428	428
q12	708	724	546	546
q13	3525	3815	3328	3328
q14	315	315	298	298
q15	q16	697	700	654	654
q17	8371	7023	6903	6903
q18	13015	12227	12866	12227
q19	927	853	841	841
q20	2146	2155	1910	1910
q21	5584	4592	4729	4592
q22	487	454	425	425
Total cold run time: 72664 ms
Total hot run time: 65831 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 151297 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit d6b4f794c9b0edd937f3f243491ef9fa4d15f9d7, data reload: false

query5	4315	590	451	451
query6	428	207	190	190
query7	4816	451	230	230
query8	317	175	157	157
query9	8799	3234	3234	3234
query10	475	319	257	257
query11	5983	3852	3589	3589
query12	160	93	86	86
query13	1256	438	348	348
query14	6097	3941	3591	3591
query14_1	3437	3420	3437	3420
query15	203	198	184	184
query16	949	433	438	433
query17	881	643	527	527
query18	2428	433	315	315
query19	208	178	136	136
query20	84	84	83	83
query21	222	127	111	111
query22	13021	12937	12798	12798
query23	13489	12865	12454	12454
query23_1	12610	12546	12511	12511
query24	7327	845	472	472
query24_1	492	511	492	492
query25	530	436	363	363
query26	1264	260	141	141
query27	2776	441	274	274
query28	4645	2061	2074	2061
query29	1585	610	450	450
query30	294	221	187	187
query31	1009	932	817	817
query32	134	97	95	95
query33	530	303	242	242
query34	971	864	514	514
query35	746	753	639	639
query36	813	839	749	749
query37	131	93	79	79
query38	1775	1739	1653	1653
query39	802	798	748	748
query39_1	738	739	737	737
query40	218	123	95	95
query41	73	66	68	66
query42	91	94	87	87
query43	349	356	312	312
query44	1360	720	731	720
query45	183	176	166	166
query46	838	975	570	570
query47	2981	3026	2675	2675
query48	300	305	238	238
query49	586	391	282	282
query50	689	276	213	213
query51	10779	10344	10235	10235
query52	81	80	69	69
query53	185	203	157	157
query54	245	190	201	190
query55	76	73	62	62
query56	231	211	215	211
query57	1676	1600	1527	1527
query58	306	265	254	254
query59	2177	2168	2001	2001
query60	300	238	230	230
query61	151	151	151	151
query62	381	331	282	282
query63	189	159	166	159
query64	2734	956	768	768
query65	3335	3267	3257	3257
query66	1795	444	305	305
query67	20169	20297	20009	20009
query68	2968	1006	622	622
query69	389	284	240	240
query70	823	782	764	764
query71	300	239	219	219
query72	2728	2581	2544	2544
query73	536	528	298	298
query74	4620	4530	4367	4367
query75	2355	2286	1932	1932
query76	2288	1003	597	597
query77	339	373	270	270
query78	9744	9688	9134	9134
query79	1027	865	525	525
query80	1243	420	363	363
query81	585	308	271	271
query82	606	136	107	107
query83	295	201	191	191
query84	306	124	101	101
query85	881	422	369	369
query86	400	241	232	232
query87	2022	1911	1814	1814
query88	3832	2774	2739	2739
query89	330	278	243	243
query90	1932	167	165	165
query91	161	153	125	125
query92	100	90	88	88
query93	1029	1016	584	584
query94	632	317	271	271
query95	582	391	294	294
query96	680	494	237	237
query97	2433	2441	2351	2351
query98	161	156	146	146
query99	772	758	638	638
Total cold run time: 236045 ms
Total hot run time: 151297 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 25.2 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit d6b4f794c9b0edd937f3f243491ef9fa4d15f9d7, data reload: false

query1	0.01	0.01	0.00
query2	0.14	0.08	0.08
query3	0.35	0.12	0.12
query4	1.61	0.13	0.13
query5	0.26	0.25	0.25
query6	1.15	0.65	0.65
query7	0.04	0.01	0.01
query8	0.09	0.07	0.07
query9	0.44	0.35	0.35
query10	0.54	0.63	0.59
query11	0.31	0.19	0.17
query12	0.31	0.18	0.18
query13	0.56	0.53	0.53
query14	0.95	0.94	0.96
query15	0.66	0.58	0.59
query16	0.37	0.37	0.35
query17	1.06	1.00	0.99
query18	0.29	0.28	0.28
query19	1.96	1.89	1.80
query20	0.02	0.01	0.02
query21	15.39	0.35	0.31
query22	4.92	0.13	0.12
query23	15.86	0.49	0.29
query24	2.15	0.52	0.39
query25	0.17	0.11	0.10
query26	0.76	0.27	0.21
query27	0.11	0.10	0.09
query28	3.41	0.83	0.40
query29	12.63	4.38	3.43
query30	0.35	0.17	0.15
query31	2.75	0.58	0.33
query32	3.26	0.58	0.49
query33	2.94	2.95	2.97
query34	15.89	4.07	3.45
query35	3.40	3.39	3.38
query36	0.58	0.53	0.50
query37	0.12	0.09	0.09
query38	0.06	0.06	0.06
query39	0.06	0.06	0.06
query40	0.20	0.17	0.15
query41	0.11	0.05	0.05
query42	0.06	0.06	0.06
query43	0.07	0.06	0.06
Total cold run time: 96.37 s
Total hot run time: 25.2 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 53.57% (15/28) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 67.18% (32472/48335)
Line Coverage 52.03% (343753/660683)
Region Coverage 47.45% (279309/588620)
Branch Coverage 49.15% (131801/268168)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 53.57% (15/28) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.51% (36304/46840)
Line Coverage 62.73% (410021/653654)
Region Coverage 59.18% (347101/586492)
Branch Coverage 60.10% (160780/267516)

@jacktengg
jacktengg force-pushed the arm-perf branch 3 times, most recently from ab9d4ce to 80e954f Compare October 30, 2026 08:58
@jacktengg

Copy link
Copy Markdown
Contributor Author

/review

@jacktengg

Copy link
Copy Markdown
Contributor Author

run buildall

@github-actions

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: Selected model is at capacity. Please try a different model.
Workflow run: https://github.com/apache/doris/actions/runs/41031372612

Please inspect the workflow logs and rerun the review after the underlying issue is resolved.

@hello-stephen

Copy link
Copy Markdown
Contributor

Cloud UT Coverage Report

Increment line coverage 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.65% (2101/2741)
Line Coverage 65.99% (38783/58772)
Region Coverage 53.70% (36378/67743)
Branch Coverage 57.24% (11861/20722)

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 50.00% (3/6) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.08 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 79365b13e4cf08a4e214af22634a48e7c91462d2, data reload: false

query1	0.01	0.00	0.01
query2	0.10	0.05	0.05
query3	0.26	0.10	0.09
query4	1.61	0.10	0.10
query5	0.24	0.24	0.24
query6	1.17	0.68	0.66
query7	0.04	0.01	0.00
query8	0.06	0.04	0.04
query9	0.40	0.34	0.35
query10	0.57	0.60	0.57
query11	0.20	0.14	0.14
query12	0.19	0.15	0.15
query13	0.50	0.50	0.49
query14	1.04	1.00	1.02
query15	0.63	0.63	0.61
query16	0.34	0.35	0.36
query17	1.12	1.17	1.15
query18	0.21	0.18	0.20
query19	2.08	1.99	1.97
query20	0.02	0.02	0.01
query21	15.48	0.19	0.14
query22	4.91	0.06	0.06
query23	16.27	0.32	0.12
query24	1.05	0.25	0.18
query25	0.09	0.06	0.05
query26	0.72	0.22	0.16
query27	0.04	0.03	0.04
query28	3.67	0.81	0.36
query29	12.47	4.10	3.25
query30	0.28	0.13	0.10
query31	2.77	0.54	0.32
query32	3.23	0.61	0.50
query33	3.12	3.28	3.21
query34	15.32	4.02	3.37
query35	3.33	3.32	3.31
query36	0.54	0.47	0.42
query37	0.10	0.06	0.06
query38	0.05	0.04	0.04
query39	0.04	0.04	0.03
query40	0.17	0.14	0.14
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 94.61 s
Total hot run time: 24.08 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage `` 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 61.54% (24/39) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.70% (35901/46205)
Line Coverage 63.01% (403543/640484)
Region Coverage 59.55% (341197/573005)
Branch Coverage 60.73% (158104/260357)

jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Nov 3, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#69776

Problem Summary:

A TopN filter on the null-generating side of an outer join can remove
matching rows and create new NULL-extended rows. ORDER BY COALESCE(a.k,-1)
after a right join can then return -1 when every original a.k is 10.
Recursive fragment rebuilds also create empty TopN heaps but reuse the
query-level bounds. Those bounds can reject new input before the new heap
retains any candidates, which can terminate recursion prematurely.

Reuse the Join runtime filter's null-propagation proof to check TopN
pushdown through null-generating sides of hash and nested-loop joins.
Reset only rebuilt TopN sources after old tasks drain and before new tasks
are submitted. Clear scalar and storage bounds and reset predicate versions
so the first new bound takes effect promptly. Preserve boundary sharing
among parallel instances within one execution.

### Release note

Fix incorrect TopN results for outer joins with NULL-converting sort
expressions and recursive CTEs containing TopN runtime filters.

### Check List (For Author)

- Test: ASAN BE/FE build; 61 BE unit tests; 61 FE unit tests;
  6 regression suites; 5 filter-off/on result pairs; manual reproduction
  on the prior build; plan checks; clang-format v16; header hygiene;
  FE Checkstyle; clang-tidy
- Behavior changed: Yes. Block unsafe outer-join filter pushdown and reset
  TopN bounds at recursive execution boundaries to preserve correct results
- Does this need documentation: No
jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Nov 3, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#69776

Problem Summary:

TopN runtime filters retain rows equal to the current boundary. For Heap TopN
with one actual sort key, these rows cannot improve the result after the heap
has retained LIMIT + OFFSET candidates.

Select LT or GT bounds in BE for a Heap TopN with one sort key. Keep LE or GE
bounds for multiple sort keys. Apply the selected mode to storage predicates,
column expressions, raw values, dictionary evaluation, and external predicate
conversion. Preserve NULL ordering and support scan preparation before source
initialization.

Keep published bounds during parallel initialization within one execution.
Clear the bounds and storage predicate versions when a recursive fragment is
rebuilt, because the new heap has no candidates to support the old bound.

Require null propagation when FE pushes a TopN filter through the left side of
a right or full outer join. Otherwise, removing a matching boundary row can
create a NULL-extended row whose expression value sorts before the boundary.
For example, COALESCE(a.k, -1) can produce -1 after the filter removes a.k = 10.

### Release note

Heap TopN runtime filters with one sort key can discard rows equal to the
boundary. Multiple sort keys retain inclusive bounds.

### Check List (For Author)

- Test: Manual checks of commit boundaries, dependencies, generated-result
  preservation, whitespace, clang-format v16, and header hygiene. Include BE
  and FE unit tests, strict-bound and safety regression suites, and strict-bound
  scan-key cases. Builds and tests were not rerun for this commit split.
- Behavior changed: Yes. Single-key Heap TopN uses strict runtime bounds, and
  FE blocks unsafe filter pushdown through null-generating outer join inputs.
- Does this need documentation: No
jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Nov 3, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#69776

Problem Summary:

TopN runtime filters retain rows equal to the current boundary. For Heap TopN
with one actual sort key, these rows cannot improve the result after the heap
has retained LIMIT + OFFSET candidates.

Select LT or GT bounds in BE for a Heap TopN with one sort key. Keep LE or GE
bounds for multiple sort keys. Apply the selected mode to storage predicates,
column expressions, raw values, dictionary evaluation, and external predicate
conversion. Preserve NULL ordering and support scan preparation before source
initialization.

Keep published bounds during parallel initialization within one execution.
Clear the bounds and nested storage predicates when a recursive fragment is
rebuilt, because the new heap has no candidates to support the old bound.

Require null propagation when FE pushes a TopN filter through the left side of
a right or full outer join. Otherwise, removing a matching boundary row can
create a NULL-extended row whose expression value sorts before the boundary.
For example, COALESCE(a.k, -1) can produce -1 after the filter removes a.k = 10.

### Release note

Heap TopN runtime filters with one sort key can discard rows equal to the
boundary. Multiple sort keys retain inclusive bounds.

### Check List (For Author)

- Test: Manual verification of removed page-range changes, preserved strict-bound
  changes and generated regression results, dependency references, and whitespace
  excluding generated-result EOF separators. Conflict resolutions pass
  clang-format v16 and BE header hygiene. Includes BE and FE unit tests and
  strict-bound and safety regression suites. Builds and tests were not rerun
  after rebasing.
- Behavior changed: Yes. Single-key Heap TopN uses strict runtime bounds, and
  FE blocks unsafe filter pushdown through null-generating outer join inputs.
- Does this need documentation: No
@jacktengg jacktengg changed the title [improvement](topn) Improve TopN runtime filtering and scan range pruning [improvement](topn) Use strict bounds for single-key TopN runtime filters Nov 3, 2026
jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Nov 3, 2026
Issue Number: None

Related PR: apache#69776

Problem Summary:
TopN runtime filters retain rows equal to the current boundary. Once a Heap
TopN has retained LIMIT + OFFSET candidates, equal boundary values cannot
improve a single-key result. Multiple sort keys still need inclusive bounds.

Choose strict bounds in FE from the actual SortNode algorithm and final
ordering expressions. Serialize this final decision in the optional
TTopnFilterDesc.use_strict field. Both FE dispatch paths share toThrift(),
after runtime-predicate algorithm selection where applicable. Plans omitting
this decision or explicitly setting it to false retain inclusive bounds.

BE constructs an immutable comparison mode from the descriptor and prepares
one comparison function. Apply LT/GT or LE/GE consistently to storage
predicates, column expressions, raw values, dictionary evaluation and external
predicate conversion. Preserve NULL ordering and scan preparation before
source initialization.

Keep published bounds across parallel source initialization. Clear scalar
and nested storage bounds when a recursive fragment is rebuilt, because the
new heap has no candidates supporting the previous execution's boundary.

Require null propagation when FE pushes a TopN filter through the left side
of a right or full outer join. Otherwise, filtering a matching row can create
a NULL-extended row with a better expression value: COALESCE(a.k, -1) becomes
-1 after removing a.k = 10. Legacy FE plans remain inclusive on upgraded BEs.

Thrift field 6 is optional and defaults to false. Its ID and the existing
field meanings were checked against branch-3.1, branch-4.0, branch-4.1,
branch-4.2 and master.

Single-key Heap TopN runtime filters can discard rows equal to the boundary.
Multiple keys and legacy plans without the FE's final decision keep inclusive
bounds. Unsafe filter pushdown through null-generating outer joins is blocked.

- Test: Unit tests: run-fe-ut.sh --run
  org.apache.doris.nereids.postprocess.TopNRuntimeFilterTest (12 passed),
  including forced heap/topn/full algorithms, one/multiple keys and redundant
  order-key removal. run-be-ut.sh --run with RuntimePredicateTest.*,
  SortOperatorTest.*, HeapSorterTest.* and FragmentMgrCrossClusterCancelTest.*
  (30 passed). FE Checkstyle, clang-format v16 on modified C++ files, BE header
  hygiene, modified-line clang-tidy and cross-branch Thrift audit passed.
  Missing and explicit-false planner decisions both retain boundary rows in
  ascending and descending scans. Mixed-version cluster regression was not run.
- Behavior changed: Yes. FE decides strict bounds for safe single-key Heap
  TopN plans; other plans remain inclusive. Recursive executions clear stale
  bounds and unsafe outer-join filter targets are rejected.
- Does this need documentation: No
@jacktengg
jacktengg force-pushed the arm-perf branch 2 times, most recently from 0a7ad95 to 60cc311 Compare November 3, 2026 08:57
jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Nov 3, 2026
Issue Number: None

Related PR: apache#69776

Problem Summary:
TopN runtime filters retain rows equal to the current boundary. Once a Heap
TopN has retained LIMIT + OFFSET candidates, equal boundary values cannot
improve a single-key result. Multiple sort keys still need inclusive bounds.

Choose strict bounds in FE from the actual SortNode algorithm and final
ordering expressions. Serialize this final decision in the optional
TTopnFilterDesc.use_strict field. Both FE dispatch paths share toThrift(),
after runtime-predicate algorithm selection where applicable. Plans omitting
this decision or explicitly setting it to false retain inclusive bounds.

BE constructs an immutable comparison mode from the descriptor and prepares
one comparison function. Apply LT/GT or LE/GE consistently to storage
predicates, column expressions, raw values, dictionary evaluation and external
predicate conversion. Preserve NULL ordering and scan preparation before
source initialization.

Keep published bounds across parallel source initialization. Clear scalar
and nested storage bounds when a recursive fragment is rebuilt, because the
new heap has no candidates supporting the previous execution's boundary.

Require null propagation when FE pushes a TopN filter through the left side
of a right or full outer join. Otherwise, filtering a matching row can create
a NULL-extended row with a better expression value: COALESCE(a.k, -1) becomes
-1 after removing a.k = 10. Legacy FE plans remain inclusive on upgraded BEs.

Thrift field 6 is optional and defaults to false. Its ID and the existing
field meanings were checked against branch-3.1, branch-4.0, branch-4.1,
branch-4.2 and master.

Single-key Heap TopN runtime filters can discard rows equal to the boundary.
Multiple keys and legacy plans without the FE's final decision keep inclusive
bounds. Unsafe filter pushdown through null-generating outer joins is blocked.

- Test: Unit tests: run-fe-ut.sh --run
  org.apache.doris.nereids.postprocess.TopNRuntimeFilterTest (12 passed),
  including forced heap/topn/full algorithms, one/multiple keys and redundant
  order-key removal. run-be-ut.sh --run with RuntimePredicateTest.*,
  SortOperatorTest.*, HeapSorterTest.* and FragmentMgrCrossClusterCancelTest.*
  (30 passed). FE Checkstyle, clang-format v16 on modified C++ files, BE header
  hygiene, modified-line clang-tidy and cross-branch Thrift audit passed.
  Missing and explicit-false planner decisions both retain boundary rows in
  ascending and descending scans. Mixed-version cluster regression was not run.
- Behavior changed: Yes. FE decides strict bounds for safe single-key Heap
  TopN plans; other plans remain inclusive. Recursive executions clear stale
  bounds and unsafe outer-join filter targets are rejected.
- Does this need documentation: No
jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Nov 4, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#69776

Problem Summary:
TopN runtime filters retain rows equal to the current boundary. Once a Heap
TopN has retained LIMIT + OFFSET candidates, equal boundary values cannot
improve a single-key result. Multiple sort keys still need inclusive bounds.

Choose strict bounds in FE from the actual SortNode algorithm and final
ordering expressions. Serialize this decision in optional field 5,
TTopnFilterDesc.use_strict. Both FE dispatch paths share toThrift() after
runtime-predicate algorithm selection. Missing or false decisions retain
inclusive bounds, including legacy FE plans on upgraded BEs.

BE constructs an immutable comparison mode and applies LT/GT or LE/GE
consistently to storage predicates, column expressions, raw values,
dictionary evaluation and external predicate conversion. Preserve NULL
ordering and scan preparation before source initialization.

Keep bounds across parallel source initialization. Clear scalar and nested
storage bounds when a recursive fragment is rebuilt, because a new heap has
no candidates supporting the previous execution's boundary.

Require null propagation when pushing a TopN filter through the left side
of a right or full outer join. Stop pushdown at AssertNumRows: an early
UNION sibling bound can otherwise remove a scalar subquery's last input,
causing AssertNumRows to synthesize a NULL that wins a NULLS FIRST TopN.
Preserve filters on safe sibling branches and TopNs inside the assertion.

Stop pushdown at hash aggregation as well. A bound from a UNION sibling can
empty a scalar SUM input and synthesize NULL, or discard the remaining rows
of an already-started group and emit a partial aggregate result. Such a row
can survive a boundary tie in the source heap. Keep independent TopN filters
inside the aggregate and on safe UNION siblings.

Validate join output semantics using the original probe expression before
any equality substitution. Reject probe-side filtering through RIGHT ANTI
(hash and nested-loop, including constant probes), and marked RIGHT SEMI.
Otherwise pruning a match can create an unmatched right row or change a
retained mark. For RIGHT/FULL outer joins require an original left-side,
NULL-propagating expression: replacing a right equality key with a left key
would preserve rank while changing the output payload. Preserve separately
safe inner, left-preserving and unmarked right-semi paths. Require at least
one original left input slot: nonfolded slot-free expressions such as
CAST(sleep(0) AS INT) do not become NULL on an unmatched right output.

Reject fully substituted scan probes containing volatile expressions using
the shared recursive containsVolatileExpression contract. Scan predicates
and source projections have separate function states: strict filtering of
IF(rand(3) < 0.5, 0, 1) can shift the projection sequence and lose its minimum.
The final target-registration guard covers nested expressions, aliases,
UNION mappings, joins and declared volatile UDFs, while retaining safe
sibling filters and deterministic/query-stable expressions.

### Release note

Single-key Heap TopN runtime filters can discard rows equal to the boundary.
Multiple sort keys and legacy plans retain inclusive bounds. Prevent unsafe
pushdown through null-generating outer joins, scalar row-count assertions,
and aggregation; prevent probe filtering from creating or changing right-side
join outputs; disable unsafe runtime filtering of volatile ordering expressions;
clear stale boundaries between recursive executions.

### Check List (For Author)

- Test: Unit Test: ./run-fe-ut.sh --run
  org.apache.doris.nereids.postprocess.TopNRuntimeFilterTest (17 passed).
  Both aggregate barrier tests fail before this correction and pass afterward.
  Coverage includes scalar/grouped SUM, 16 ordering/NULL-placement/inner-TopN
  combinations, serialized safe UNION targets, COUNT/DISTINCT/HAVING/join
  plans, and the previously added AssertNumRows cases. Join coverage includes
  144 join-type/algorithm/probe/order combinations (including nonfolded
  SLEEP(0)) and four commuted hash RIGHT_SEMI mark plans. Another 40
  expression plans cover nested/slot-bearing RAND and UUID, standalone
  volatile sources, deterministic controls and safe serialized UNION targets.
  FE Checkstyle passed with zero violations. Added regression EXPLAIN checks
  for aggregate barriers; these were not run on a live cluster. No BE rebuild
  or live-cluster regression run was performed for this FE-only correction.
- Behavior changed: Yes. Safe single-key Heap TopNs use strict bounds;
  unsafe outer/anti/marked-join, AssertNumRows, aggregate and volatile
  expression targets are rejected; recursive executions clear stale bounds.
- Does this need documentation: No
@jacktengg

Copy link
Copy Markdown
Contributor Author

Local pipeline review — ✅ PASS

schema: doris-repo-review/v1
status: PASS
pr: apache/doris#69776
commit: 0312f2e60fc86d30bae2c5ddbe890538a4085087
base: a35707da74f8df0d6502df95feaf734dd9d20d9d
reviewed_at: 2026-11-04T21:46+08:00
reviewer: jacktengg
model: gpt-6-astra
effort: xhigh
findings: {blocker: 0, major: 0, minor: 0, nit: 0}
rounds: 1
converged: true

Notes for maintainers

  • Scope excludes the separately tracked Repeat/GROUPING SETS issue, which remains unfixed; existing BKD discussion_r4432112388 is deduplicated, not declared safe.
  • Complete21-file/17-checkpoint review; prior original-side ownership and volatile reevaluation blockers are closed at this head.
  • Saved author FE artifacts show17 passing tests; no BE rebuild or live-cluster regression execution was performed in this review.

Reviewed locally with the doris-repo-review pipeline. Repository policy may accept this receipt for the matching commit; it is not a human Apache approval.

jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Nov 4, 2026
### What problem does this PR solve?

Issue Number: None

Related PR: apache#69776

Problem Summary:
TopN runtime filters retain rows equal to the current boundary. Once a Heap
TopN has retained LIMIT + OFFSET candidates, equal boundary values cannot
improve a single-key result. Multiple sort keys still need inclusive bounds.

Choose the comparison mode in BE from each source's actual TSortNode
algorithm and final ordering expressions. Inspect the request's fragment
plans while creating QueryContext, before publishing it to other fragments.
Keep the mode immutable so a scan prepared before its source uses the same
comparison as the storage predicate. An absent source plan or sort algorithm
retains inclusive comparisons. Remove the unpublished use_strict Thrift
field and the corresponding FE decision; reuse the existing sort metadata.

Apply LT/GT or LE/GE consistently to storage predicates, column expressions,
raw values, dictionary evaluation and external predicate conversion, while
preserving NULL ordering. Keep bounds across parallel source initialization.
Clear scalar and nested storage bounds when a recursive fragment is rebuilt,
because the new heap has no candidates supporting the previous boundary.

Keep FE pushdown safety checks. Stop at aggregation and AssertNumRows:
filtering their input can synthesize NULL rows or change an aggregate result.
Reject probe filtering through RIGHT ANTI and marked RIGHT SEMI joins, where
removing a match can create or change a right-side output. Validate original
probe slots before equality substitution; RIGHT/FULL outer joins require an
original left-side, NULL-propagating expression and NULLS LAST. Slot-free
expressions cannot satisfy this condition. Reject fully substituted probes
containing volatile expressions, whose independent scan/projection function
states can otherwise produce incorrect results. Preserve safe sibling and
inner TopN filters.

### Release note

Single-key Heap TopN runtime filters can discard rows equal to the boundary.
Multiple sort keys retain inclusive bounds. Prevent unsafe pushdown through
aggregation, scalar assertions, outer/anti/marked joins and volatile ordering
expressions; clear stale boundaries between recursive executions.

### Check List (For Author)

- Test: Unit Test and build: ./build.sh --be -j24 (ASAN) passed.
  ./run-fe-ut.sh --run org.apache.doris.nereids.postprocess.TopNRuntimeFilterTest
  passed all 17 tests. ./run-be-ut.sh passed 36 distinct targeted tests across
  RuntimePredicateTest, SortOperatorTest, recursive fragment rebuild,
  Parquet TopN and Iceberg TopN; all 5 SortOperatorTest tests passed again
  after test-helper refactoring. Coverage includes actual algorithms,
  single/multiple ordering keys, absent source/algorithm, multiple source IDs,
  scan-before-source preparation, comparison paths and bound reset/preservation.
  FE Checkstyle, clang-format 16, build hygiene and clang-tidy passed for
  the changed code. No live-cluster regression run was performed.
- Behavior changed: Yes. Safe single-key Heap TopNs use strict bounds;
  unsafe pushdown targets are rejected and recursive executions clear bounds.
- Does this need documentation: No
@jacktengg

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed at exact PR head cf7c0db (base 19dfb87). I inspected all 22 paths in the authoritative changed-file list and diff, including strict TopN comparison propagation, fragment metadata selection, recursive rebuild bound reset, scanner/index evaluation, FE pushdown through projects/unions/joins/aggregates/asserts/CTEs/windows, serialization, and the added BE/FE/regression coverage. The three assigned review scopes all returned NO_NEW_VALUABLE_FINDINGS, and the main risk items were independently dismissed with evidence. The existing inline P2 thread 4432112388 was revalidated as unchanged legacy context; it is not a new finding and no P0/P1 existing blocking comment applies. The user provided no additional focus points. This was a static-only review: no builds, tests, source edits, or runtime validation were performed.

Review converged after 1 round(s).

@jacktengg

Copy link
Copy Markdown
Contributor Author

run buildall

### What problem does this PR solve?

Issue Number: None

Related PR: apache#69776

Problem Summary:
TopN runtime filters retain rows equal to the current boundary. Once a Heap
TopN has retained LIMIT + OFFSET candidates, equal boundary values cannot
improve a single-key result. Multiple sort keys still need inclusive bounds.

Choose the comparison mode in BE from each source's actual TSortNode
algorithm and final ordering expressions. Inspect the request's fragment
plans while creating QueryContext, before publishing it to other fragments.
Keep the mode immutable so a scan prepared before its source uses the same
comparison as the storage predicate. An absent source plan or sort algorithm
retains inclusive comparisons. Remove the unpublished use_strict Thrift
field and the corresponding FE decision; reuse the existing sort metadata.

Apply LT/GT or LE/GE consistently to storage predicates, column expressions,
raw values, dictionary evaluation and external predicate conversion, while
preserving NULL ordering. Source detection preserves any existing bound.
Clear scalar and nested storage bounds when a recursive fragment is rebuilt,
because the new heap has no candidates supporting the previous boundary.

Keep FE pushdown safety checks. Stop at aggregation and AssertNumRows:
filtering their input can synthesize NULL rows or change an aggregate result.
Reject probe filtering through RIGHT ANTI and marked RIGHT SEMI joins, where
removing a match can create or change a right-side output. Validate original
probe slots before equality substitution; RIGHT/FULL outer joins require an
original left-side, NULL-propagating expression and NULLS LAST. Slot-free
expressions cannot satisfy this condition. Reject fully substituted probes
containing volatile expressions, whose independent scan/projection function
states can otherwise produce incorrect results. Preserve safe sibling and
inner TopN filters.

### Release note

Single-key Heap TopN runtime filters can discard rows equal to the boundary.
Multiple sort keys retain inclusive bounds. Prevent unsafe pushdown through
aggregation, scalar assertions, outer/anti/marked joins and volatile ordering
expressions; clear stale boundaries between recursive executions.

### Check List (For Author)

- Test: Unit Test and build: ./build.sh --be -j24 (ASAN) passed.
  ./run-fe-ut.sh --run org.apache.doris.nereids.postprocess.TopNRuntimeFilterTest
  passed all 17 tests. ./run-be-ut.sh passed 36 distinct targeted tests across
  RuntimePredicateTest, SortOperatorTest, recursive fragment rebuild,
  Parquet TopN and Iceberg TopN; all 5 SortOperatorTest tests passed again
  after test-helper refactoring. Coverage includes actual algorithms,
  single/multiple ordering keys, absent source/algorithm, multiple source IDs,
  scan-before-source preparation, comparison paths and bound reset/preservation.
  After the lifecycle-comment correction, all 27 selected RuntimePredicate,
  SortOperator and recursive-rebuild tests passed again.
  FE Checkstyle, clang-format 16, build hygiene and clang-tidy passed for
  the changed code. No live-cluster regression run was performed.
- Behavior changed: Yes. Safe single-key Heap TopNs use strict bounds;
  unsafe pushdown targets are rejected and recursive executions clear bounds.
- Does this need documentation: No
@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 28767 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit cf7c0db3e9acb106e9f54cecc088b56536211048, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17572	5149	5121	5121
q2	2149	311	242	242
q3	10255	1398	810	810
q4	4682	464	336	336
q5	7423	823	525	525
q6	187	187	155	155
q7	750	793	595	595
q8	9260	1355	1054	1054
q9	5477	4203	4189	4189
q10	6825	1291	1057	1057
q11	436	245	224	224
q12	639	398	275	275
q13	18093	3692	3064	3064
q14	278	270	247	247
q15	q16	742	726	670	670
q17	1219	761	572	572
q18	7131	6201	6118	6118
q19	1113	968	581	581
q20	384	338	224	224
q21	5620	2497	2437	2437
q22	391	338	271	271
Total cold run time: 100626 ms
Total hot run time: 28767 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5982	5993	6075	5993
q2	706	604	570	570
q3	5656	5825	5338	5338
q4	2009	2131	1556	1556
q5	5859	6065	5599	5599
q6	234	185	148	148
q7	2329	2046	1766	1766
q8	3032	2645	2653	2645
q9	7949	7448	7503	7448
q10	3665	3610	3120	3120
q11	584	399	373	373
q12	675	677	503	503
q13	3288	3629	3059	3059
q14	284	282	266	266
q15	q16	667	687	626	626
q17	7737	7044	6878	6878
q18	12955	12205	12931	12205
q19	887	840	774	774
q20	2148	2116	1898	1898
q21	5636	4575	4669	4575
q22	490	457	401	401
Total cold run time: 72772 ms
Total hot run time: 65741 ms

@jacktengg

Copy link
Copy Markdown
Contributor Author

Local pipeline review — ✅ PASS

schema: doris-repo-review/v1
status: PASS
pr: apache/doris#69776
commit: 2ba41429d5b5e9ea2f34c68ead3d6abfd2f72bbf
base: 19dfb8711ae3dbb8f56cc945f5dc7af20a844607
reviewed_at: 2026-11-05T01:36+08:00
reviewer: jacktengg
model: gpt-6-astra
effort: xhigh
findings: {blocker: 0, major: 0, minor: 0, nit: 0}
rounds: 1
converged: true

Notes for maintainers

  • Reviewed all 22 changed files. Final head changes only the two lifecycle comments since the complete review at cf7c0db. The source-initialization finding is fixed.
  • Verified saved results for 27 tests after the fix. This review ran no build or test. Live regression, strict external-file integration and full SIMD-lane execution remain unverified here.
  • Scope is matched FE+BE deployment. The separately tracked Repeat/GROUPING SETS issue and existing BKD discussion r4432112388 remain excluded.

Reviewed locally with the doris-repo-review pipeline. Repository policy may accept this receipt for the matching commit; it is not a human Apache approval.

@jacktengg

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 153080 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit cf7c0db3e9acb106e9f54cecc088b56536211048, data reload: false

query5	4343	527	405	405
query6	451	232	209	209
query7	4804	448	241	241
query8	337	189	172	172
query9	8819	3243	3217	3217
query10	467	315	285	285
query11	5917	3851	3575	3575
query12	153	97	92	92
query13	1277	471	353	353
query14	6193	3933	3705	3705
query14_1	3449	3514	3431	3431
query15	229	210	185	185
query16	974	453	430	430
query17	904	710	612	612
query18	2444	449	356	356
query19	222	184	153	153
query20	91	89	87	87
query21	223	133	112	112
query22	12953	13003	12759	12759
query23	13559	12865	12510	12510
query23_1	12585	12536	12408	12408
query24	7405	840	495	495
query24_1	515	500	512	500
query25	588	482	431	431
query26	1272	276	150	150
query27	2739	451	290	290
query28	4595	2053	2061	2053
query29	1642	662	501	501
query30	315	223	190	190
query31	1022	943	825	825
query32	157	104	103	103
query33	541	331	266	266
query34	921	865	511	511
query35	754	767	662	662
query36	814	807	732	732
query37	134	103	107	103
query38	1765	1754	1664	1664
query39	803	802	757	757
query39_1	741	735	742	735
query40	245	126	108	108
query41	91	88	78	78
query42	90	87	84	84
query43	353	362	320	320
query44	1316	717	726	717
query45	203	182	173	173
query46	836	967	579	579
query47	2568	2732	2720	2720
query48	318	336	239	239
query49	641	410	310	310
query50	698	292	213	213
query51	10728	10655	10534	10534
query52	83	85	72	72
query53	198	215	158	158
query54	255	218	192	192
query55	74	69	69	69
query56	264	238	236	236
query57	1694	1640	1597	1597
query58	299	279	278	278
query59	2134	2189	2025	2025
query60	296	261	244	244
query61	187	184	183	183
query62	403	348	308	308
query63	193	160	167	160
query64	2964	1234	996	996
query65	3327	3300	3257	3257
query66	1833	462	349	349
query67	20266	20304	19854	19854
query68	2956	1013	647	647
query69	390	303	278	278
query70	878	796	781	781
query71	314	249	226	226
query72	2901	2860	2531	2531
query73	534	535	302	302
query74	4632	4517	4365	4365
query75	2392	2297	1929	1929
query76	2325	1008	590	590
query77	347	384	294	294
query78	9795	9671	9148	9148
query79	1021	848	545	545
query80	1192	492	390	390
query81	610	327	285	285
query82	587	136	107	107
query83	314	210	204	204
query84	325	130	118	118
query85	970	538	486	486
query86	394	241	235	235
query87	2000	1973	1815	1815
query88	3928	2854	2832	2832
query89	341	291	248	248
query90	1935	175	169	169
query91	191	180	152	152
query92	107	98	97	97
query93	1094	1019	580	580
query94	578	333	285	285
query95	595	416	318	318
query96	682	498	241	241
query97	2439	2415	2325	2325
query98	165	157	149	149
query99	801	770	681	681
Total cold run time: 237219 ms
Total hot run time: 153080 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.15 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit cf7c0db3e9acb106e9f54cecc088b56536211048, data reload: false

query1	0.01	0.01	0.01
query2	0.09	0.05	0.05
query3	0.27	0.09	0.09
query4	1.60	0.10	0.11
query5	0.23	0.24	0.23
query6	1.17	0.68	0.66
query7	0.04	0.01	0.01
query8	0.06	0.03	0.04
query9	0.41	0.33	0.34
query10	0.58	0.59	0.58
query11	0.19	0.15	0.14
query12	0.19	0.14	0.15
query13	0.49	0.49	0.49
query14	1.04	1.01	1.00
query15	0.63	0.61	0.61
query16	0.35	0.35	0.35
query17	1.16	1.12	1.12
query18	0.14	0.14	0.14
query19	2.06	2.00	1.96
query20	0.02	0.01	0.01
query21	15.53	0.21	0.13
query22	4.88	0.05	0.06
query23	16.28	0.32	0.12
query24	3.00	0.48	0.45
query25	0.11	0.05	0.06
query26	1.56	0.22	0.15
query27	0.05	0.05	0.04
query28	3.90	0.77	0.36
query29	12.46	4.08	3.21
query30	0.29	0.13	0.10
query31	2.78	0.55	0.33
query32	3.22	0.60	0.50
query33	3.24	3.26	3.12
query34	15.31	4.00	3.37
query35	3.31	3.35	3.34
query36	0.56	0.43	0.44
query37	0.09	0.06	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.17	0.15	0.14
query41	0.09	0.03	0.03
query42	0.03	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 97.72 s
Total hot run time: 24.15 s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants