-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
bpo-36389: Add gc.enable_object_debugger() #12480
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
Conversation
|
Thanks @csabella, I applied your suggestions. I rebased my PR to edit fix the commit message. |
|
Second version of my change. The object debugger now longer calls _PyXXX_CheckConsistency() functions, but rather reuse tp_traverse mecanism and only implements the most consistency checks: The documentation now explains which checks are implemented and says explicitly that the debugger is written to find bugs in C extensions. It now also mentions that the debugger rely on the debug hooks on memory allocators and shortly explains how to enable them. |
|
Small update: rebase on top of new better _PyObject_IsFreed() implementation, and fix where gc_check_object_debugger() is called in Modules/gcmodule.c. |
New "object debugger" which checks frequently if all Python objects tracked by the garbage collector are consistent: gc.enable_object_debugger() and gc.disable_object_debugger(). * Py_FatalError() and _PyObject_AssertFailed() now disable the GC object debugger to prevent reentrant calls. * Fix _PyObject_Dump() for ob_type=NULL
Disable debugger in PyObject_GC_Del() and _PyObject_GC_Resize(): the debugger is just too slow.
|
New rebase. I added multiple thresholds to get to reduce the performance overhead. I compared the number of _PyGC_ObjectDebuggerGeneration(0) calls using gc.enable_object_debugger(5, 10, 10) vs collect(0) calls using gc.set_threshold(5, 10, 10): _PyGC_ObjectDebuggerGeneration(0) is called 10x more times. My raw stats: Ah, and _PyGC_ObjectDebuggerGeneration(2) is called 52x more than than collect(2)... |
| { | ||
| struct _gc_object_debugger *debugger = &_PyRuntime.gc.object_debugger; | ||
| debugger->enabled = 0; | ||
| for (int i=0; i < NUM_GENERATIONS; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| for (int i=0; i < NUM_GENERATIONS; i++) { | |
| for (int i = 0; i < NUM_GENERATIONS; i++) { |
| GC_OBJECT_ASSERT(op, type != NULL); | ||
| GC_OBJECT_ASSERT(op, !_PyObject_IsFreed((PyObject *)type)); | ||
|
|
||
| #undef ASSERT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is ASSERT?
|
|
||
|
|
||
| /*[clinic input] | ||
| gc.enable_object_debugger as gc_py_enable_object_debugger -> NoneType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would not use -> NoneType. It does not add clarity. Actually return Py_None without increfing looks suspicious. It is clearer to use Py_RETURN_NONE.
|
|
||
| This debugger aims to debug bugs in C extensions. | ||
|
|
||
| .. function:: enable_object_debugger(threshold) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The signature does not match implementation.
| int threshold; /* collection threshold */ | ||
| int count; /* count of allocations or collections of younger | ||
| generations */ | ||
| } generations[NUM_GENERATIONS]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I have not found where multiple generations are used?
|
Abandoned for reasons explained at: https://bugs.python.org/issue36389#msg347497 |
New "object debugger" which checks frequently if all Python object tracked
by the garbage collector are consistent: gc.enable_object_debugger()
and gc.disable_object_debugger().
now exposed in the internal API. _PyDict_CheckConsistency()
parameter type becomes PyObject*.
https://bugs.python.org/issue36389