Skip to content

Speculate string functions such as upper in NullShortCircuit by adding them to is_cheap #7587

Open

Description

@tlfua

What is the problem the feature request solves?

#7456 evaluates an operand of an ANSI arithmetic expression or concat only for the rows that Spark evaluates it for, when the operand could fail on the rows Spark skips. To decide whether to evaluate such an operand over the whole batch anyway and fall back to the selected rows only if that fails, NullShortCircuit asks is_cheap (native/spark-expr/src/conditional_funcs/null_short_circuit.rs) whether the operand costs about as little over the whole batch as over the selected rows.

is_cheap only accepts columns, literals, integer and floating point +, -, * (including checked_add, checked_sub and checked_mul) and widening casts. cannot_fail does not know any function, so in concat(q, upper(s)) the upper(s) argument is masked, and since is_cheap treats upper as costly it is evaluated over the whole batch only when at least half the rows need it, and on the selected rows otherwise, even where speculating would be faster. The concat_upper shape in native/spark-expr/benches/null_short_circuit.rs measures this case.

Raised in review: #7456 (review)

Describe the potential solution

Benchmark concat_upper and similar string shapes (lower, trim, substring) with every row selected, a few rows selected, and in between, comparing speculating over the whole batch against evaluating only the selected rows. Add to is_cheap the functions for which speculating is never much slower, with the benchmark numbers in the PR, as the doc comment of is_cheap asks ("The list holds what has been measured, and can grow").

Additional context

is_cheap only affects performance. Whether an operand is masked at all is decided by cannot_fail in native/spark-expr/src/conditional_funcs/case_when.rs, so a change to is_cheap cannot change results.

Willingness to contribute

I can contribute a fix for this bug independently

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions