Skip to content
73 changes: 70 additions & 3 deletions python/docs/source/development/debugging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,14 @@ Python/Pandas UDF
~~~~~~~~~~~~~~~~~

PySpark provides remote `memory_profiler <https://github.com/pythonprofilers/memory_profiler>`_ for
Python/Pandas UDFs, which can be enabled by setting ``spark.python.profile.memory`` configuration to ``true``. That
can be used on editors with line numbers such as Jupyter notebooks. An example on a Jupyter notebook is as shown below.
Python/Pandas UDFs

SparkContext-based
^^^^^^^^^^^^^^^^^^

SparkContext-based memory profiler can be enabled by setting ``spark.python.profile.memory`` configuration to ``true``.
That can be used on editors with line numbers such as Jupyter notebooks. An example on a Jupyter notebook is as shown
below.

.. code-block:: bash

Expand Down Expand Up @@ -268,6 +274,31 @@ The UDF IDs can be seen in the query plan, for example, ``add1(...)#2L`` in ``Ar

This feature is not supported with registered UDFs or UDFs with iterators as inputs/outputs.

SparkSession-based
^^^^^^^^^^^^^^^^^^

SparkSession-based memory profiler can be enabled by setting the `Runtime SQL configuration <https://spark.apache.org/docs/latest/configuration.html#runtime-sql-configuration>`_
``spark.sql.pyspark.udf.profiler`` to ``memory``. That can be used on editors with line numbers such as Jupyter notebooks.
The above example is modified to use the SparkSession-based memory profiler as shown below.

.. code-block:: python

from pyspark.sql.functions import pandas_udf
df = spark.range(10)

@pandas_udf("long")
def add1(x):
return x + 1

spark.conf.set("spark.sql.pyspark.udf.profiler", "memory")

added = df.select(add1("id"))
added.show()
spark.profile.show(type="memory")

The result profile is the same as that profiled by the SparkContext-based memory profiler. The UDF IDs can also be seen in the query plan.

This feature is supported on both Spark Connect and non-Spark-Connect, including registered UDFs.

Identifying Hot Loops (Python Profilers)
----------------------------------------
Expand Down Expand Up @@ -341,7 +372,12 @@ Python/Pandas UDF
~~~~~~~~~~~~~~~~~

To use this on Python/Pandas UDFs, PySpark provides remote `Python Profilers <https://docs.python.org/3/library/profile.html>`_ for
Python/Pandas UDFs, which can be enabled by setting ``spark.python.profile`` configuration to ``true``.
Python/Pandas UDFs.

SparkContext-based

@HyukjinKwon HyukjinKwon Feb 29, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just remove this, and just add one additional section called runtime profiler

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @ueshin do you have other thoughts?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about put the new doc to the first place?

  • Identifying Hot Loops (Python Profilers)
    • Driver Side
      ...
    • Executor Side
      • Python/Pandas UDF
        Show the new profiler usage
      • Legacy (for RDD or non-Spark Connect)
        Put the current doc here

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe there are many existing users of SparkContext-based profilers. Shall we keep it in the debugging guide until SparkSession-based profilers gain more adoption and positive feedbacks? I'll adjust the order to show SparkSession-based profilers first as @ueshin suggested. What do you think @HyukjinKwon?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will remove "legacy" profilers for readability and clarity and start preparing migration guide.

^^^^^^^^^^^^^^^^^^

SparkContext-based performance profiler can be enabled by setting ``spark.python.profile`` configuration to ``true``.

.. code-block:: bash

Expand Down Expand Up @@ -393,6 +429,37 @@ The UDF IDs can be seen in the query plan, for example, ``add1(...)#2L`` in ``Ar

This feature is not supported with registered UDFs.

SparkSession-based
^^^^^^^^^^^^^^^^^^

SparkSession-based performance profiler can be enabled by setting the `Runtime SQL configuration <https://spark.apache.org/docs/latest/configuration.html#runtime-sql-configuration>`_
``spark.sql.pyspark.udf.profiler`` to ``perf``. The above example is modified to use the SparkSession-based performance profiler as shown below.

.. code-block:: python

>>> from pyspark.sql.functions import pandas_udf
>>> df = spark.range(10)
>>> @pandas_udf("long")
... def add1(x):
... return x + 1
...
>>> added = df.select(add1("id"))

>>> spark.conf.set("spark.sql.pyspark.udf.profiler", "perf")
>>> added.show()
+--------+
|add1(id)|
+--------+
...
+--------+

>>> spark.profile.show(type="perf")
...

The result profile is the same as that profiled by the SparkContext-based memory profiler. The UDF IDs can also be seen in the query plan.

This feature is supported on both Spark Connect and non-Spark-Connect, including registered UDFs.

Common Exceptions / Errors
--------------------------

Expand Down