Spenserrrr commented on code in PR #59246:
URL: https://github.com/apache/spark/pull/59246#discussion_r4252023581


##########
python/pyspark/eval_handlers/_pandas.py:
##########
@@ -66,6 +68,21 @@ def __init__(
         self._return_schema = StructType(
             [StructField("_%d" % i, rt) for i, (_, _, _, rt) in 
enumerate(udfs)]
         )
+        self._input_timer: ContextManager[None] = nullcontext()
+        self._udf_timer: ContextManager[None] = nullcontext()
+        self._output_timer: ContextManager[None] = nullcontext()
+
+    def set_worker_metrics(self, metrics: "WorkerMetrics") -> None:
+        super().set_worker_metrics(metrics)
+        # Bind scopes once per task; each batch reuses them without creating 
new timers.
+        # These phases run on the main thread even when a reader thread 
prefetches input.
+        # The callback timer includes profiling work when a profiler wraps the 
UDF.
+        self._input_timer = metrics.measure("pythonInputConversionTime")
+        self._udf_timer = metrics.measure("pythonUDFExecutionTime")
+        self._output_timer = metrics.measure("pythonOutputConversionTime")
+        # Advertise timing support even when the task has no input batches.
+        metrics.set("pythonNumTimingReports", 1)
+        metrics.set("pythonNumTimedBatches", 0)

Review Comment:
   Agreed. The handler-local metric collection was removed; the shared 
`WorkerMetrics` collector is reset once per task in the worker, and modern 
Arrow UDF phase timing is collected there. Resolving this older placement 
thread.



##########
python/pyspark/eval_handlers/_pandas.py:
##########
@@ -75,22 +92,24 @@ def run(self, split_index: int, data: 
"Iterator[pa.RecordBatch]") -> "Iterator[p
             num_rows = input_batch.num_rows
 
             # Input: Arrow -> pandas Series (struct columns become DataFrames).
-            pandas_columns = ArrowToPandasConversion.to_pandas(
-                input_batch,
-                timezone=runner_conf.timezone,
-                struct_in_pandas="dict",
-                ndarray_as_list=False,
-                prefer_int_ext_dtype=runner_conf.prefer_int_ext_dtype,
-                df_for_struct=True,
-            )
+            with self._input_timer:
+                pandas_columns = ArrowToPandasConversion.to_pandas(
+                    input_batch,
+                    timezone=runner_conf.timezone,
+                    struct_in_pandas="dict",
+                    ndarray_as_list=False,
+                    prefer_int_ext_dtype=runner_conf.prefer_int_ext_dtype,
+                    df_for_struct=True,
+                )
 
             # Process: evaluate each UDF column-wise on pandas Series.
             results = []
             for udf_func, args_offsets, kwargs_offsets, return_type in 
self._udfs:
-                result = udf_func(
-                    *[pandas_columns[o] for o in args_offsets],
-                    **{k: pandas_columns[v] for k, v in 
kwargs_offsets.items()},
-                )
+                # Argument selection and return validation are outside the 
callback timer.
+                args = [pandas_columns[o] for o in args_offsets]
+                kwargs = {k: pandas_columns[v] for k, v in 
kwargs_offsets.items()}

Review Comment:
   Agreed that UDF argument preparation belongs to input time. In the current 
Arrow path, `rows` is built before `udf_start_ns`, so that work is counted as 
input preparation. Arrow read/write are separate intervals, and inter-UDF loop 
transitions are left out, so the three in-loop phases are not defined to sum to 
the full worker wall time. Resolving this older handler-scope thread.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to