[ 
https://issues.apache.org/jira/browse/CALCITE-7805?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Frank Chen updated CALCITE-7805:
--------------------------------
    Description: 
CALCITE-7782 and [PR #5263|https://github.com/apache/calcite/pull/5263] 
eliminated quadratic operand-list copying while validating large ARRAY and MAP 
constructors. That correction allows a 1,000,000-element string ARRAY to 
complete instead of running for more than 20 minutes.

After that correction, validation is linear, but planning still creates many 
temporary objects for every string literal. In the benchmark below, planning a 
1,000,000-element string IN expression allocates approximately 15.4 GB during 
one operation and takes approximately 7.8 seconds.

The allocation values below are cumulative allocation during one planning 
operation, not retained memory or peak heap usage.

h2. Reproducer

Apache Druid exposes the remaining allocation through a large string IN 
predicate:

{code:sql}
SELECT string1
FROM foo
WHERE string1 IN ('1', '2', ..., '1000000')
{code}

Druid rewrites the predicate to an expression containing a string ARRAY:

{code}
SCALAR_IN_ARRAY(string1, ARRAY['1', '2', ..., '1000000'])
{code}

The benchmark is {{InPlanningBenchmark.queryStringInSqlPlanOnly}}.

Parameters:
* {{inSubQueryThreshold = 2147483647}}
* {{rowsPerSegment = 500000}}
* 2 JMH forks
* 2 one-second warmup iterations per fork
* 5 one-second measurement iterations per fork
* GC profiler enabled
* Temurin 25.0.4.1

The Calcite baseline is commit {{38413ece6}}, which includes the merged 
CALCITE-7782 change.

h2. Proposed delivery

The implementation is split into five independently reviewable sub-tasks:

# [CALCITE-7806|https://issues.apache.org/jira/browse/CALCITE-7806] - Avoid 
resolving generated CAST calls during ARRAY validation.
# [CALCITE-7807|https://issues.apache.org/jira/browse/CALCITE-7807] - Reuse 
unchanged SQL types during least-restrictive inference.
# [CALCITE-7808|https://issues.apache.org/jira/browse/CALCITE-7808] - Cache 
recently created and decorated SQL types.
# [CALCITE-7809|https://issues.apache.org/jira/browse/CALCITE-7809] - Avoid 
copying unchanged SQL and Rex operands.
# [CALCITE-7810|https://issues.apache.org/jira/browse/CALCITE-7810] - Write Rex 
string literal digests directly.

Each sub-task links its corresponding pull request and can be reviewed and 
tested independently.

h2. Combined benchmark

When changes are stacked together, the benchmark shows about 70% allocation 
saving.

|| String literals || CALCITE-7782 baseline || All proposed changes || 
Allocation saved ||
| 100,000 | 1.522 GB/op | 0.445 GB/op | 1.077 GB/op (70.8%) |
| 1,000,000 | 15.418 GB/op | 4.556 GB/op | 10.862 GB/op (70.5%) |


For each change, the separated benchmark data is attached in their descriptions

  was:
CALCITE-7782 and [PR #5263|https://github.com/apache/calcite/pull/5263] 
eliminated quadratic operand-list copying while validating large ARRAY and MAP 
constructors. That correction allows a 1,000,000-element string ARRAY to 
complete instead of running for more than 20 minutes.

After that correction, validation is linear, but planning still creates many 
temporary objects for every string literal. In the benchmark below, planning a 
1,000,000-element string IN expression allocates approximately 15.4 GB during 
one operation and takes approximately 7.8 seconds.

The allocation values below are cumulative allocation during one planning 
operation, not retained memory or peak heap usage.

h2. Reproducer

Apache Druid exposes the remaining allocation through a large string IN 
predicate:

{code:sql}
SELECT string1
FROM foo
WHERE string1 IN ('1', '2', ..., '1000000')
{code}

Druid rewrites the predicate to an expression containing a string ARRAY:

{code}
SCALAR_IN_ARRAY(string1, ARRAY['1', '2', ..., '1000000'])
{code}

The benchmark is {{InPlanningBenchmark.queryStringInSqlPlanOnly}}.

Parameters:
* {{inSubQueryThreshold = 2147483647}}
* {{rowsPerSegment = 500000}}
* 2 JMH forks
* 2 one-second warmup iterations per fork
* 5 one-second measurement iterations per fork
* GC profiler enabled
* Temurin 25.0.4.1

The Calcite baseline is commit {{38413ece6}}, which includes the merged 
CALCITE-7782 change.

h2. Remaining allocation sources

h2. Proposed delivery

The implementation is split into five independently reviewable sub-tasks:

# [CALCITE-7806|https://issues.apache.org/jira/browse/CALCITE-7806] - Avoid 
resolving generated CAST calls during ARRAY validation.
# [CALCITE-7807|https://issues.apache.org/jira/browse/CALCITE-7807] - Reuse 
unchanged SQL types during least-restrictive inference.
# [CALCITE-7808|https://issues.apache.org/jira/browse/CALCITE-7808] - Cache 
recently created and decorated SQL types.
# [CALCITE-7809|https://issues.apache.org/jira/browse/CALCITE-7809] - Avoid 
copying unchanged SQL and Rex operands.
# [CALCITE-7810|https://issues.apache.org/jira/browse/CALCITE-7810] - Write Rex 
string literal digests directly.

Each sub-task links its corresponding pull request and can be reviewed and 
tested independently.

h2. Combined benchmark

When changes are stacked together, the benchmark shows about 70% allocation 
saving.

|| String literals || CALCITE-7782 baseline || All proposed changes || 
Allocation saved ||
| 100,000 | 1.522 GB/op | 0.445 GB/op | 1.077 GB/op (70.8%) |
| 1,000,000 | 15.418 GB/op | 4.556 GB/op | 10.862 GB/op (70.5%) |


For each change, the separated benchmark data is attached in their descriptions


> Reduce temporary object allocation when validating large string ARRAYs to 
> lower GC pressure
> -------------------------------------------------------------------------------------------
>
>                 Key: CALCITE-7805
>                 URL: https://issues.apache.org/jira/browse/CALCITE-7805
>             Project: Calcite
>          Issue Type: Improvement
>          Components: core
>    Affects Versions: 1.42.0
>            Reporter: Frank Chen
>            Priority: Major
>              Labels: pull-request-available
>
> CALCITE-7782 and [PR #5263|https://github.com/apache/calcite/pull/5263] 
> eliminated quadratic operand-list copying while validating large ARRAY and 
> MAP constructors. That correction allows a 1,000,000-element string ARRAY to 
> complete instead of running for more than 20 minutes.
> After that correction, validation is linear, but planning still creates many 
> temporary objects for every string literal. In the benchmark below, planning 
> a 1,000,000-element string IN expression allocates approximately 15.4 GB 
> during one operation and takes approximately 7.8 seconds.
> The allocation values below are cumulative allocation during one planning 
> operation, not retained memory or peak heap usage.
> h2. Reproducer
> Apache Druid exposes the remaining allocation through a large string IN 
> predicate:
> {code:sql}
> SELECT string1
> FROM foo
> WHERE string1 IN ('1', '2', ..., '1000000')
> {code}
> Druid rewrites the predicate to an expression containing a string ARRAY:
> {code}
> SCALAR_IN_ARRAY(string1, ARRAY['1', '2', ..., '1000000'])
> {code}
> The benchmark is {{InPlanningBenchmark.queryStringInSqlPlanOnly}}.
> Parameters:
> * {{inSubQueryThreshold = 2147483647}}
> * {{rowsPerSegment = 500000}}
> * 2 JMH forks
> * 2 one-second warmup iterations per fork
> * 5 one-second measurement iterations per fork
> * GC profiler enabled
> * Temurin 25.0.4.1
> The Calcite baseline is commit {{38413ece6}}, which includes the merged 
> CALCITE-7782 change.
> h2. Proposed delivery
> The implementation is split into five independently reviewable sub-tasks:
> # [CALCITE-7806|https://issues.apache.org/jira/browse/CALCITE-7806] - Avoid 
> resolving generated CAST calls during ARRAY validation.
> # [CALCITE-7807|https://issues.apache.org/jira/browse/CALCITE-7807] - Reuse 
> unchanged SQL types during least-restrictive inference.
> # [CALCITE-7808|https://issues.apache.org/jira/browse/CALCITE-7808] - Cache 
> recently created and decorated SQL types.
> # [CALCITE-7809|https://issues.apache.org/jira/browse/CALCITE-7809] - Avoid 
> copying unchanged SQL and Rex operands.
> # [CALCITE-7810|https://issues.apache.org/jira/browse/CALCITE-7810] - Write 
> Rex string literal digests directly.
> Each sub-task links its corresponding pull request and can be reviewed and 
> tested independently.
> h2. Combined benchmark
> When changes are stacked together, the benchmark shows about 70% allocation 
> saving.
> || String literals || CALCITE-7782 baseline || All proposed changes || 
> Allocation saved ||
> | 100,000 | 1.522 GB/op | 0.445 GB/op | 1.077 GB/op (70.8%) |
> | 1,000,000 | 15.418 GB/op | 4.556 GB/op | 10.862 GB/op (70.5%) |
> For each change, the separated benchmark data is attached in their 
> descriptions



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to