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

ASF GitHub Bot updated SPARK-59765:
-----------------------------------
    Labels: pull-request-available  (was: )

> Codegen size checks over empty TPC-DS tables measure stubs for broadcast joins
> ------------------------------------------------------------------------------
>
>                 Key: SPARK-59765
>                 URL: https://issues.apache.org/jira/browse/SPARK-59765
>             Project: Spark
>          Issue Type: Test
>          Components: SQL
>    Affects Versions: 5.0.0
>            Reporter: Max Gekk
>            Priority: Major
>              Labels: pull-request-available
>
> Two instruments measure the code whole-stage codegen generates for the TPC-DS 
> queries without running them: {{BenchmarkQueryTest.checkGeneratedCode}}, used 
> by {{TPCDSQuerySuite}} and its variants (see SPARK-59764), and 
> {{WholeStageCodegenSizeBenchmark}} (SPARK-57915), the instrument for the 
> SPARK-56908 umbrella. Both plan each query over empty TPC-DS tables with AQE 
> disabled, and call {{doCodeGen()}} on every {{WholeStageCodegenExec}}.
> With AQE disabled, {{BroadcastHashJoinExec.prepareBroadcast}} executes the 
> broadcast while generating code. Over an empty table the relation is 
> {{EmptyHashedRelation}}, and {{HashJoin}} then generates a one-line comment 
> in place of the join: "If HashedRelation is empty, hash inner join simply 
> returns nothing" (and the semi join equivalent), in which case the code of 
> every operator after the join in the stage is not generated either. For an 
> anti join it generates only the pass-through. {{BroadcastNestedLoopJoinExec}} 
> has a similar shortcut for an empty build side. So a stage with a broadcast 
> join is measured as a stub, and its method sizes and constant pools are 
> understated.
> How much, on master (4cfbd411966): with {{WholeStageCodegenSizeBenchmark}}'s 
> setup (injected SF100 statistics with CBO, AQE off, empty tables), the 
> generated code of 324 of the 2201 whole-stage stages of the 129 TPC-DS v1.4 
> and v2.7 queries contains the empty-relation stub, in 127 of the 129 queries. 
> Measured by planning each query as {{TPCDSQueryWithStatsSuite}} does, taking 
> {{codegenStringSeq(executedPlan)}}, and counting the stages whose source 
> contains "If HashedRelation is empty".
> In a fork close to master, generating those stages in full made 374 stages 
> larger, the largest by about 3.5KB of bytecode for one method. So the 
> benchmark's totals and the 8000-byte check both see less code than the 
> queries compile over real data.
> Proposed fix, for both: generate each stage's code from a copy of the stage 
> in which every {{BroadcastExchangeExec}} (including one under a 
> {{ReusedExchangeExec}}) reads a one-row {{LocalTableScanExec}} of non-null 
> default values. The joins then generate the code they generate for data, and 
> nothing else about the plan changes. Assert that no generated code still 
> contains the empty-relation comment, so the stub cannot come back unnoticed. 
> One approximation remains: a one-row build side makes every key unique, so a 
> join generates its unique-key form; a join whose real build side repeats keys 
> also has the loop over matches.
> Populating the tables with data would also work, but a fixed row is filtered 
> out by any literal predicate on the build side (for example {{d_year = 
> 2000}}), which leaves the relation empty again.



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

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to