microsoft / debugpy

An implementation of the Debug Adapter Protocol for Python
https://pypi.org/project/debugpy/
Other
1.83k stars 136 forks source link

Python 3.12 runs much slower than Python 3.11 #1496

Closed cvzi closed 3 weeks ago

cvzi commented 9 months ago

Environment data

Actual behavior

Importing the emoji module (v2.10.0) with debugging enabled takes a long time with Python 3.12 compared to Python 3.11.

When running from VS Code with the default debug configuration via F5, the import takes 4 minutes on Python 3.12 but only 50ms on Python 3.11

The emoji module contains a large Python file, here. I suspect the slow debugging has something to do with this file.

Expected behavior

Similar run times in Python 3.11 and Python 3.12

Steps to reproduce:

  1. Install emoji module: pip install emoji==2.10.0
  2. Create a test file in VS Code that imports the emoji module:

    import time
    start = time.time()
    
    import emoji
    
    end = time.time()
    print("import time", end - start)
  3. Set VS Code to Python 3.12
  4. Run in VS Code by pressing F5
int19h commented 8 months ago

I suspect it's the large dict literal specifically that is the issue there. It sounds like in 3.12 it is reporting a debugger "line" event (which the debugger then has to process to check for breakpoints etc) for every subexpression in the literal, whereas before it was treated as a single atomic statement?

If so, then this is to be expected - settrace-based Python debugging is inherently slow (~20x overhead per line of pure Python code, such as here). However, we're working on debugpy v2 utilizing the new sys.monitoring API in Python 3.12 for near-zero-overhead debugging; that should address this issue. And I think we should add this import as one of the test cases for that.

lsmith77 commented 8 months ago

@int19h it sounds like this will take a bit until it is ready. is there any quick fix/work-around for this? it also appears to affect spacy.

bersbersbers commented 7 months ago

I think the original issue has been fixed by emoji v2.10.1. For anyone working on this, here's another example:

bug.py:

import timeit
print(timeit.timeit("import colorcet", number=1))

Then run:

pip install colorcet debugpy
python bug.py
python -m debugpy --listen 5678 bug.py

For me, this prints

0.23384420000002137
0.01s - Debugger warning: It seems that frozen modules are being used, which may
0.00s - make the debugger miss breakpoints. Please pass -Xfrozen_modules=off
0.00s - to python to disable frozen modules.
0.00s - Note: Debugging will proceed. Set PYDEVD_DISABLE_FILE_VALIDATION=1 to disable this validation.
15.49023370000009

Python 3.11 takes ~0.03s vs. 0.05s, so even without the debugger, Python 3.11 seems to be an order of magnitude faster. But the difference is much more striking with the debugger.

Implementation is at https://github.com/holoviz/colorcet/blob/main/colorcet/__init__.py. I also opened https://github.com/holoviz/colorcet/issues/121.

cvzi commented 7 months ago

Yes it was "solved" in emoji module by compressing the dict literal into a single line, previously the dict was spread over ~87k lines

cvzi commented 5 months ago

FYI for anyone considering this solution, unfortunately compressing the dict into a single line has created a new problem for us, it causes coverage report on Python 3.12 to use excessive amounts of memory (in our case more than 20 GB).

bersbersbers commented 4 months ago

causes coverage report on Python 3.12 to use excessive amounts of memory

For the record, this issue (https://github.com/nedbat/coveragepy/issues/1785) should be gone with Python 3.12.4 thanks to https://github.com/python/cpython/issues/119118, so the practicality of one-line workarounds should be improved. That is relevant since the original issue continues to exist in Python 3.12.4 (long runtime importing large dicts with debugger attached)

Denelbe commented 1 month ago

I have a similar problem with module python-opcua. The simple following script in vscode debugger runs in 2.7 seconds using Python 3.11.2 but 68 seconds with Python 3.12.5.

from opcua import Server 
server = Server()

OS Linux (Debian 12) VsCode 1.92.2 Python Debugger 2024.10.0

snmishra commented 1 month ago

I've moved to pydevd. debugpy is unusable in Python 3.12, and I didn't want to go back to Python 3.11

rchiodo commented 1 month ago

Debugpy actually uses pydevd under the covers, but hasn't yet updated to pydevd's latest which has support for 3.12.

laipz8200 commented 1 month ago

I am currently debugging the repository langgenius/dify and am encountering a similar issue with the latest version, where the project takes an unusually long time to start (approximately 5 minutes) on my M1 Pro machine.

I would like to understand the underlying cause of this delay and request guidance on how to resolve it.

Environment Details:

Thank you for your assistance!

Feel free to let me know if you would like any additional information.

rchiodo commented 1 month ago

I would like to understand the underlying cause of this delay and request guidance on how to resolve it.

Sorry there's nothing you can do. We need to finish moving to the new 3.12 sys.monitoring support.

rteitge commented 1 month ago

Is there an approximate timetable for when we can start developing with vscode and devcontainer again? Since we are dependent on 3.12, vscode and devcontainer with the delays are unfortunately completely useless at the moment. That is not efficient working.

rchiodo commented 1 month ago

All I can say is porting the Pydevd changes for 3.12 to debugpy are in progress. Can't say how long it will take though.

rchiodo commented 1 month ago

This item: https://github.com/microsoft/debugpy/issues/1640

rchiodo commented 4 weeks ago

I'm pretty confident the pydev port will fix the performance issue.

Here's the difference for me between the two with the colorcet example:

With sys.monitoring

PS C:\Users\rchiodo\source\testing\test_pylance>  c:; cd 'c:\Users\rchiodo\source\testing\test_pylance'; & 'c:\Users\rchiodo\source\testing\test_pylance\.venv312\Scripts\python.exe' 'C:\Users\rchiodo\source\repos\debugpy\src\debugpy\adapter/../..\debugpy\launcher' '63855' '--' 'C:\Users\rchiodo\source\testing\test_pylance\test_slowdebugger.py' 
1.5255662000272423

With sys.trace

PS C:\Users\rchiodo\source\testing\test_pylance> ^C
PS C:\Users\rchiodo\source\testing\test_pylance> 
PS C:\Users\rchiodo\source\testing\test_pylance>  c:; cd 'c:\Users\rchiodo\source\testing\test_pylance'; & 'c:\Users\rchiodo\source\testing\test_pylance\.venv312\Scripts\python.exe' 'c:\Users\rchiodo\.vscode\extensions\ms-python.debugpy-2024.11.2024082901-win32-x64\bundled\libs\debugpy\adapter/../..\debugpy\launcher' '63993' '--' 'C:\Users\rchiodo\source\testing\test_pylance\test_slowdebugger.py' 
18.01146870001685
rchiodo commented 3 weeks ago

Reopening, hasn't shipped yet.

rchiodo commented 3 weeks ago

This issue should be fixed in the latest build of debugpy. It should ship with VS code in a future version of the Python Debugger Extension or you can install your own debugpy from pypi

bersbersbers commented 3 weeks ago

Wow. 1.8.6 goes from 24s to 4s launching my app with debugger attached. Great work!

I see this has made its way into https://github.com/microsoft/vscode-python-debugger already via https://github.com/microsoft/vscode-python-debugger/commit/afd0d2bbb634e51064806daa013fef5895d6c52e.

Until that is released, this is how I was able to update the bundled debugpy in vscode-python-debugger:

pip install "debugpy>=1.8.6" --upgrade --target "%USERPROFILE%\.vscode\extensions\ms-python.debugpy-2024.10.0-win32-x64\bundled\libs"