Repository navigation
Incremental GC causes a significant slowdown for Sphinx #124567
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or errorperformancePerformance or resource usagePerformance or resource usage3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixes
on Sep 26, 2024 I think I wanted to investigate it in sphinx-doc/sphinx#12181 but then I didn't have the motivation nor the time... (and we wanted to avoid keeping opened issues for too long). The root cause was the memory usage for docutils that increased a lot so this might be the reason why we are also seeing those slowdowns.
Reacted by Alex Waygood and Kerim KabirovI think I wanted to investigate it in sphinx-doc/sphinx#12181 but then I didn't have the motivation nor the time... (and we wanted to avoid keeping opened issues for too long).
Yes, @AA-Turner mentioned as much in #118891 (comment). This seems like the kind of issue that could cause slowdowns for other workloads as well as Sphinx, however. (But I'll defer to our performance and GC experts on if there are obvious ways to mitigate it.)
Prompted by @ned-deily, I reran my PGO-optimized timings using
--with-lto=full --enable-optimizationsbuilds rather than simply--with-lto --enable-optimizationsbuilds. (Since I'm benchmarking using a Mac, this could have been relevant.) The timings onv3.13.0a1andmainusing this build configuration were essentially identical to the ones I reported above, however.Reacted by Carol Willing and Vasily Ryabov@AlexWaygood Let's rerun after #124538 lands.
Could be cool to make the sphinx build a pyperformance benchmark (I think there might be a docutils pyperf benchmark, wonder if that saw a regression)
Reacted by Carol Willing@willingc I think that's unlikely to make a difference; that issue is related to capsules and probably doesn't interact with the regression we're seeing here.
@hauntsaninja there is a docutils benchmark, https://github.com/python/pyperformance/tree/main/pyperformance/data-files/benchmarks/bm_docutils. Looks like it builds a bunch of RST files, though not CPython's own docs. According to Michael that benchmark didn't show a regression, so it would be interesting to figure out what's different about the CPython docs relative to that benchmark.
Reacted by Alex Waygood and Carol WillingAccording to Michael that benchmark didn't show a regression
There is a bit of a regression actually, at least in the memory usage as reported by faster-cpython/ideas#668 (roughly a 20% increase of memory). I don't think that's all there is to actually make Sphinx slower.
Thanks Alex for the excellent write-up. A note for reproduction, in my local tests the slowdown could be reproduced just in the parsing step, so you can use
'dummy'instead of'html'in the reproduction script to save time (as no HTML files are produced).library/typing.rstInterestingly I found that when building just that document, timings were broadly the same. However when building everything, 3.13.0a5 was consistently 1.6x faster than 3.13.0a6 (using the built optimised releases from https://www.python.org/downloads/ for Windows, 64 bit).
Could be cool to make the sphinx build a pyperformance benchmark
When I added the Docutils benchmark, Michael Droettboom requested that I/O variables (reading & writing files) be removed as it adds too much noise. There isn't a good way to avoid I/O in Sphinx, unlike with Docutils, unfortunatley. I would be keen to add Sphinx to the benchmark suite.
Looks like it builds a bunch of RST files
Docutils' documentation, we can't use Python's as the Python documentation uses Sphinx-only extensions.
A
Reacted by Alex Waygood21 remaining items
Do we also need to check how the Sphinx benchmark looks with a PGO-optimized release build relative to 3.13? (The CI doctest job uses a debug build.)
I agree, for completeness we should confirm that the slowdown has gone from release builds (it was always much more pronounced in debug builds).
A
Reacted by Alex WaygoodDo we also need to check how the Sphinx benchmark looks with a PGO-optimized release build relative to 3.13?
On PGO builds on our benchmarking hardware, the Sphinx benchmark is now not significantly different than 3.13.0 and about 2% faster than main prior to #126502 being merged.
Reacted by Itamar Oren and Hugo van KemenadeReacted by Alex Waygood and Hugo van KemenadePerformance is also now unchanged for me locally relative to Python 3.13 (or maybe slightly better!) using the script I posted in #118891 (comment):
main(built using--enable-optimisations --with-lto=full): 37.22s- 3.13: 38.15s
Closing as completed. Thanks everybody who helped investigate, and thanks @markshannon for fixing! 🥳
Reacted by Hugo van KemenadeReacted by Hugo van Kemenade, Adam Turner and Carol WillingReacted by Hugo van Kemenade and Carol Willing- moved this from Todo to Done in Release and Deferred blockers 🚫
on Nov 18, 2024 - moved this from Done to In Progress in Release and Deferred blockers 🚫
on Nov 19, 2024 And closing again 🙂
Reacted by Alex Waygood and Hugo van KemenadeReacted by Alex Waygood- moved this from In Progress to Done in Release and Deferred blockers 🚫
on Nov 19, 2024
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDone
Bug report
A significant performance regression in Sphinx caused by changes in CPython 3.13
Here is a script that does the following things:
Doc/library/typing.rstwith simply"foo"The script
Using a PGO-optimized build with LTO enabled, the script reports that there is a significant performance regression in Sphinx's parsing and building of
library/typing.rstbetweenv3.13.0a1and 909c6f7:v13.0a1the script reports a Sphinx build time of between 1.27s and 1.29s (I ran the script several times)A similar regression is reported in this (much slower) variation of the script that builds the entire set of CPython's documentation rather than just
library/typing.rst.More comprehensive variation of the script
The PGO-optimized timings for building the entire CPython documentation is as follows:
v3.13.0a1: 45.5sThis indicates a 38% performance regression for building the entire set of CPython's documentation.
Cause of the performance regression
This performance regression was initially discovered in #118891: in our own CI, we use a fresh build of CPython in our Doctest CI workflow (since otherwise, we wouldn't be testing the tip of the
mainbranch), and it was observed that the CI job was taking significantly longer on the3.13branch than the3.12branch. In the context of our CI, the performance regression is even worse, because of the fact that our Doctest CI workflow uses a debug build rather than a PGO-optimized build, and the regression is even more pronounced in a Debug build.Using a debug build, I used the first script posted above to bisect the performance regression to commit 1530932 (below), which seemed to cause a performance regression of around 300% in a debug build
Performance was then significantly improved by commit e28477f (below), but it's unfortunately still the case that Sphinx is far slower on Python 3.13 than on Python 3.12:
See #118891 (comment) for more details on the bisection results.
Profiling by @nascheme in #118891 (comment) and #118891 (comment) also confirms that Sphinx spends a significant amount of time in the GC, so it seems very likely that the changes to introduce an incremental GC in Python 3.13 is the cause of this performance regression.
Cc. @markshannon for expertise on the new incremental GC, and cc. @hugovk / @AA-Turner for Sphinx expertise.
CPython versions tested on:
3.12, 3.13, CPython main branch
Operating systems tested on:
macOS
Linked PRs