bpo-37729: gc: write stats at once (GH-15050)
gc used several PySys_WriteStderr() calls to write stats. It caused stats mixed up when stderr is shared by multiple processes like this: gc: collecting generation 2... gc: objects in each generation: 0 0gc: collecting generation 2... gc: objects in each generation: 0 0 126077 126077 gc: objects in permanent generation: 0 gc: objects in permanent generation: 0 gc: done, 112575 unreachable, 0 uncollectablegc: done, 112575 unreachable, 0 uncollectable, 0.2223s elapsed , 0.2344s elapsed
This commit is contained in:
parent
4b3e975923
commit
bf8162c8c4
|
@ -962,6 +962,25 @@ clear_freelists(void)
|
||||||
(void)PyContext_ClearFreeList();
|
(void)PyContext_ClearFreeList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show stats for objects in each gennerations.
|
||||||
|
static void
|
||||||
|
show_stats_each_generations(struct _gc_runtime_state *state)
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_GENERATIONS && pos < sizeof(buf); i++) {
|
||||||
|
pos += PyOS_snprintf(buf+pos, sizeof(buf)-pos,
|
||||||
|
" %"PY_FORMAT_SIZE_T"d",
|
||||||
|
gc_list_size(GEN_HEAD(state, i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
PySys_FormatStderr(
|
||||||
|
"gc: objects in each generation:%s\n"
|
||||||
|
"gc: objects in permanent generation: %zd\n",
|
||||||
|
buf, gc_list_size(&state->permanent_generation.head));
|
||||||
|
}
|
||||||
|
|
||||||
/* This is the main function. Read this to understand how the
|
/* This is the main function. Read this to understand how the
|
||||||
* collection process works. */
|
* collection process works. */
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
|
@ -979,17 +998,9 @@ collect(struct _gc_runtime_state *state, int generation,
|
||||||
_PyTime_t t1 = 0; /* initialize to prevent a compiler warning */
|
_PyTime_t t1 = 0; /* initialize to prevent a compiler warning */
|
||||||
|
|
||||||
if (state->debug & DEBUG_STATS) {
|
if (state->debug & DEBUG_STATS) {
|
||||||
PySys_WriteStderr("gc: collecting generation %d...\n",
|
PySys_WriteStderr("gc: collecting generation %d...\n", generation);
|
||||||
generation);
|
show_stats_each_generations(state);
|
||||||
PySys_WriteStderr("gc: objects in each generation:");
|
|
||||||
for (i = 0; i < NUM_GENERATIONS; i++)
|
|
||||||
PySys_FormatStderr(" %zd",
|
|
||||||
gc_list_size(GEN_HEAD(state, i)));
|
|
||||||
PySys_WriteStderr("\ngc: objects in permanent generation: %zd",
|
|
||||||
gc_list_size(&state->permanent_generation.head));
|
|
||||||
t1 = _PyTime_GetMonotonicClock();
|
t1 = _PyTime_GetMonotonicClock();
|
||||||
|
|
||||||
PySys_WriteStderr("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyDTrace_GC_START_ENABLED())
|
if (PyDTrace_GC_START_ENABLED())
|
||||||
|
@ -1103,16 +1114,10 @@ collect(struct _gc_runtime_state *state, int generation,
|
||||||
debug_cycle("uncollectable", FROM_GC(gc));
|
debug_cycle("uncollectable", FROM_GC(gc));
|
||||||
}
|
}
|
||||||
if (state->debug & DEBUG_STATS) {
|
if (state->debug & DEBUG_STATS) {
|
||||||
_PyTime_t t2 = _PyTime_GetMonotonicClock();
|
double d = _PyTime_AsSecondsDouble(_PyTime_GetMonotonicClock() - t1);
|
||||||
|
PySys_FormatStderr(
|
||||||
if (m == 0 && n == 0)
|
"gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n",
|
||||||
PySys_WriteStderr("gc: done");
|
n+m, n, d);
|
||||||
else
|
|
||||||
PySys_FormatStderr(
|
|
||||||
"gc: done, %zd unreachable, %zd uncollectable",
|
|
||||||
n+m, n);
|
|
||||||
PySys_WriteStderr(", %.4fs elapsed\n",
|
|
||||||
_PyTime_AsSecondsDouble(t2 - t1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Append instances in the uncollectable set to a Python
|
/* Append instances in the uncollectable set to a Python
|
||||||
|
|
Loading…
Reference in New Issue