-
Notifications
You must be signed in to change notification settings - Fork 29.3k
[SPARK-57787][CONNECT] Reuse a persistent local Spark Connect server for faster local startup #56907
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SPARK-57787][CONNECT] Reuse a persistent local Spark Connect server for faster local startup #56907
Changes from all commits
21f2182
29003cd
d7704b6
6d91df0
0bf267a
8c3b1ec
918a1a4
3edade1
e80e3bd
5178f3f
fddf420
1ca6efc
49625bb
68e10d0
6487b36
685d595
4d52ca9
d4b6dc9
afbbb80
c6afb99
dd99fe7
9bafb1c
5f1f97b
fdc4239
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -277,6 +277,72 @@ The connection may also be programmatically created using _SparkSession#builder_ | |
| </div> | ||
| </div> | ||
|
|
||
| ## Faster local iteration with a persistent Connect server | ||
|
|
||
| When you develop or test locally with | ||
|
|
||
| ```python | ||
| from pyspark.sql import SparkSession | ||
| spark = SparkSession.builder.remote("local[*]").getOrCreate() | ||
| ``` | ||
|
|
||
| PySpark boots a fresh in-process Spark Connect server that lives only as long as that Python | ||
| process. Every `python script.py` invocation (or every new test worker process) therefore re-pays | ||
| the one-time startup cost -- JVM warmup, `SparkContext` construction, and Connect server boot -- | ||
| which can take a few seconds and makes a quick edit/run loop feel slow. | ||
|
|
||
| To amortize that cost across runs, start one persistent local Spark Connect server and point | ||
| every run at it: | ||
|
|
||
| ```bash | ||
| # Start once; it stays up across runs. (--master is optional; it defaults to local[*].) | ||
| $SPARK_HOME/sbin/start-connect-server.sh --master "local[*]" | ||
|
ericm-db marked this conversation as resolved.
|
||
|
|
||
| # Every run reconnects instead of booting a new server. | ||
| python -c 'from pyspark.sql import SparkSession; SparkSession.builder.remote("sc://localhost:15002").getOrCreate()' | ||
|
|
||
| # Stop it when you are done. | ||
| $SPARK_HOME/sbin/stop-connect-server.sh | ||
| ``` | ||
|
|
||
| Alternatively, on POSIX systems PySpark can manage this persistent server for you. With | ||
| `SPARK_LOCAL_CONNECT_REUSE=1` set (or `spark.local.connect.reuse=true` on the builder), | ||
| `SparkSession.builder.remote("local[*]").getOrCreate()` starts a persistent server through | ||
| `sbin/start-connect-server.sh` on the first run and reconnects to it on later runs, so scripts | ||
| keep the plain `local[*]` URL: | ||
|
|
||
| ```bash | ||
| export SPARK_LOCAL_CONNECT_REUSE=1 | ||
|
|
||
| # The first run starts the server; later runs reconnect to it. | ||
| python -c 'from pyspark.sql import SparkSession; SparkSession.builder.remote("local[*]").getOrCreate()' | ||
|
|
||
| # Stop the managed server when you are done. | ||
| python -m pyspark.sql.connect.local_server --stop | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just curious: Since we are already pointing the user to the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, if PySpark starts a persistent Connect server via
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not really a second stack, the managed server is a normal
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only by pointing the script at the managed locations (
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, OK thanks for explaining. I'm thinking ahead to a world where users can run something like I feel like that would be ideal, but that might also mean that the discovery mechanism would need to live in Scala, not here. I'm not sure. Perhaps that can be a future change. I just want to call this out here and now in case it makes sense to explicitly label the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense. Marked this as experimental in the docs and the module docstring - specifically the |
||
| ``` | ||
|
|
||
| The managed server is an ordinary `spark-daemon.sh` daemon, but it runs with a per-user pid | ||
| directory and ident string so it cannot collide with a server you started by hand -- which also | ||
| means a plain `sbin/stop-connect-server.sh` does not find it. The `--stop` command signals the | ||
| recorded server and cleans up the discovery file; killing the server's pid directly also works, | ||
| and the next run notices the dead server and starts a fresh one. | ||
|
|
||
| This managed-server workflow is experimental. The `--stop` command and the discovery file | ||
| location and format may change in a future release, for example if local server management is | ||
| folded into a unified `spark connect` CLI. | ||
|
|
||
| The connection details (host, port, auth token, pid, Spark version) are recorded in a discovery | ||
| file in a private per-user directory; set `SPARK_LOCAL_CONNECT_DISCOVERY` to override its | ||
| location. A run reconnects only to a server whose Spark version matches. After upgrading Spark, | ||
| the server from the previous version cannot be reused and the next run fails with an error asking | ||
| you to stop it; run the `--stop` command above and rerun to start a fresh server. | ||
|
|
||
| Each run connects as its own Connect session, so session-local state -- temp views, runtime SQL | ||
| configurations, and session artifacts -- is fresh on every run and never leaks between runs. State | ||
| backed by the shared `SparkContext` (the persistent catalog/warehouse, global temp views, and | ||
| cached datasets) *is* shared across runs, so namespace per-run databases or clear that state | ||
| yourself if your runs must be fully isolated. | ||
|
|
||
| ## Use Spark Connect in standalone applications | ||
|
|
||
| <div class="codetabs"> | ||
|
|
@@ -371,7 +437,7 @@ one may implement their own class extending `ClassFinder` for customized search | |
| </div> | ||
|
|
||
| For more information on application development with Spark Connect as well as extending Spark Connect | ||
| with custom functionality, see [Application Development with Spark Connect](app-dev-spark-connect.html). | ||
| with custom functionality, see [Application Development with Spark Connect](app-dev-spark-connect.html). | ||
| # Client application authentication | ||
|
|
||
| While Spark Connect does not have built-in authentication, it is designed to | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.