Make it explicit when operators start work before their stream is polled
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 25/100
- Tipo de issue
- Nueva funcionalidad
- Claridad
- Bastante claro
- Estado de actividad
- Activo
- Stack tecnológico
- rust
- Área
- backend, performance
Línea de trabajo
Read the discussion in this issue and the linked #27126 change, especially the cited comment, to understand how operators start work and how that affects query concurrency. The proposal asks for documentation, an option to defer eager starts until the first poll, and plan visibility; done means those behaviors and settings are agreed on and made explicit, with defaults preserving current behavior.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
#27126 changes CoalescePartitionsExec to start its inputs on the first poll instead of in execute(). I was surprised that CoalescePartitionsExec polls its children before its own stream is polled. With dynamic filters this can cost performance: the children start before the filters are ready and can’t use them (TPC-H q7/q21 with pushdown_filters).
At the same time, other queries rely on this behavior. With simulated I/O latency, TPC-DS q88 is 6.6× slower with the change in #27126, because the parts of the query no longer run concurrently.
My impression is that this behavior grew organically (see also this comment). This issue is meant to start a discussion on making it explicit when DataFusion works on several parts of a plan concurrently.
I think that CoalescePartitionsExec deciding whether the inner streams should be polled instantly grew organically (see also https://github.com/apache/datafusion/pull/27126#issuecomment-6690789008). This issue should start a discussion on whether we should make it more explicit when DataFusion works on multiple parts of the query plan concurrently.
A Note: operators that do this spawn tasks that decouple producing batches from the consumer polling the stream. If they spawn these tasks in execute() rather than on the first poll, I call this starting eagerly in this issue.
Some thoughts and findings:
- Suprising: Whether an operator starts eagerly differs between operators, and even between partition counts of the same operator. See table below. As a result,
CollectLeftandPartitionedhash joins can behave differently: the former usually has aCoalescePartitionsExecon the build side, the latter aRepartitionExec.
| Operator | Starts eagerly? |
|---|---|
CoalescePartitionsExec |
Yes with several input partitions; no with one |
SortPreservingMergeExec |
Yes with several input partitions (spawn_buffered); no with one |
BufferExec |
Yes |
RepartitionExec |
No: it decouples input from output, but spawns its tasks on the first poll |
- Not Configurable:
CoalescePartitionsExeccan’t be used without starting eagerly with multiple partitions. That limits reuse in downstream systems that rely heavily on dynamic filters. - Implicit: Telling from a plan which parts run concurrently requires knowing each operator’s implementation.
EvaluationType::Eageronly exists in code, isn’t shown inEXPLAIN, and covers both cases: “decouples input from output” (RepartitionExec) and “decouples input from output and starts in execute()” (CoalescePartitionsExec). - No CPU budget: This might be a different part of the conversation but I guess many users assume that the number of target partitions is approximately the maximum number of CPU cores pinned by a single query. Working on multiple concurrent parts of a query in parallel can use more cores. The fact that is implicit may makes it more difficult to estimate the CPU usage.
Whether starting eagerly pays off depends on available resources, filter selectivity, and storage latency and throughput. Downstream users are often in a better position to decide than DataFusion. The code change is usually small: spawn the tasks on the first poll instead of in execute().
Proposal
- State it. Every operator that starts eagerly documents this, and
EXPLAINshows it. - Make it configurable. Operators that start eagerly get a code-level option to start on the first poll instead, defaulting to today’s behavior. #27126 then becomes opt-in, and nothing regresses by default. After that, we can think of a better way of managing concurrency (e.g., let joins decide).
Both go together: once the setting exists, showing it in plans covers the first point. A code-level option may be enough for now; a session config can follow if needed.
I would also only expose the difference between starting tasks in execute() and the first poll in the plan properties once we have a use case for an optimization that relies on this information.
Out of scope
When each operator should start eagerly, for example pipeline breakers deciding based on pending dynamic filters, belongs in a separate issue. I hope to open a separate issue on that later.
- Lenguaje dominante
- Rust
- Estrellas
- 9.6k
- Forks
- 2.6k
- Merge medio
- 3 d 4 h
- PR fusionados (30 d)
- 345
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de apache/datafusion
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
apache/datafusion#27315 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
apache/datafusion#27094 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Substrait consumer doesn't recognise `shift_left` / `shift_right` from functions_arithmetic.yamlPosiblemente ocupada @jonasHanhan la tomó hace 9 días. Abiertobug
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
apache/datafusion#27059 ·
Los mantenedores suelen responder en 1 día
-
`ProjectionExprs::project_statistics` computes approximate `Statistics::total_byte_size` ignoring column statsPosiblemente ocupada @joseph-isaacs la tomó hace 10 días. Abiertobug
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
apache/datafusion#27050 ·
Los mantenedores suelen responder en 1 día
-
physical-plan: decoding an Unnest or Explain node with an unset field panicsPosiblemente ocupada @geoHeil la tomó hace 8 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
apache/datafusion#26999 · 1 comentario ·
Los mantenedores suelen responder en 1 día
Todos los issues de apache/datafusion
Issues similares
-
P3
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
HerringtonDarkholme/hd-lang#1770 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
jonathanong/no-mistakes#3332 ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
swc-project/swc-next-issues#310 ·
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
swc-project/swc-ai-issues#653 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
lbjlaq/Antigravity-Manager#3937 ·
Los mantenedores suelen responder en 1 día