Skip to content

Commit ab1faec

Browse files
committed
Redo stats
1 parent 3513da2 commit ab1faec

File tree

4 files changed

+34
-29
lines changed

4 files changed

+34
-29
lines changed

Include/cpython/pystats.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ typedef struct _object_stats {
9898
typedef struct _gc_stats {
9999
uint64_t collections;
100100
uint64_t object_visits;
101-
uint64_t mark_visits;
102101
uint64_t objects_collected;
103-
uint64_t objects_marked;
102+
uint64_t objects_transitively_reachable;
103+
uint64_t objects_not_transitively_reachable;
104104
} GCStats;
105105

106106
typedef struct _uop_stats {

Python/gc.c

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,14 +1370,7 @@ static int
13701370
visit_add_to_container(PyObject *op, void *arg)
13711371
{
13721372
struct container_and_flag *cf = (struct container_and_flag *)arg;
1373-
#ifdef Py_STATS
1374-
if (cf->mark) {
1375-
GC_STAT_ADD(1, mark_visits, 1);
1376-
}
1377-
else {
1378-
OBJECT_STAT_INC(object_visits);
1379-
}
1380-
#endif
1373+
OBJECT_STAT_INC(object_visits);
13811374
int visited = cf->visited_space;
13821375
assert(visited == get_gc_state()->visited_space);
13831376
if (!_Py_IsImmortal(op) && _PyObject_IS_GC(op)) {
@@ -1482,7 +1475,7 @@ mark_all_reachable(PyGC_Head *reachable, PyGC_Head *visited, int visited_space)
14821475
return arg.size;
14831476
}
14841477

1485-
static int
1478+
static Py_ssize_t
14861479
mark_global_roots(PyInterpreterState *interp, PyGC_Head *visited, int visited_space)
14871480
{
14881481
PyGC_Head reachable;
@@ -1491,12 +1484,21 @@ mark_global_roots(PyInterpreterState *interp, PyGC_Head *visited, int visited_sp
14911484
objects_marked += move_to_reachable(interp->sysdict, &reachable, visited_space);
14921485
objects_marked += move_to_reachable(interp->builtins, &reachable, visited_space);
14931486
objects_marked += move_to_reachable(interp->dict, &reachable, visited_space);
1487+
struct types_state *types = &interp->types;
1488+
for (int i = 0; i < _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES; i++) {
1489+
objects_marked += move_to_reachable(types->builtins.initialized[i].tp_dict, &reachable, visited_space);
1490+
objects_marked += move_to_reachable(types->builtins.initialized[i].tp_subclasses, &reachable, visited_space);
1491+
}
1492+
for (int i = 0; i < _Py_MAX_MANAGED_STATIC_EXT_TYPES; i++) {
1493+
objects_marked += move_to_reachable(types->for_extensions.initialized[i].tp_dict, &reachable, visited_space);
1494+
objects_marked += move_to_reachable(types->for_extensions.initialized[i].tp_subclasses, &reachable, visited_space);
1495+
}
14941496
objects_marked += mark_all_reachable(&reachable, visited, visited_space);
14951497
assert(gc_list_is_empty(&reachable));
14961498
return objects_marked;
14971499
}
14981500

1499-
static int
1501+
static Py_ssize_t
15001502
mark_stacks(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, bool start)
15011503
{
15021504
PyGC_Head reachable;
@@ -1550,7 +1552,7 @@ mark_stacks(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, b
15501552
return objects_marked;
15511553
}
15521554

1553-
static void
1555+
static Py_ssize_t
15541556
mark_at_start(PyThreadState *tstate)
15551557
{
15561558
// TO DO -- Make this incremental
@@ -1560,12 +1562,8 @@ mark_at_start(PyThreadState *tstate)
15601562
Py_ssize_t objects_marked = mark_global_roots(tstate->interp, visited, gcstate->visited_space);
15611563
objects_marked += mark_stacks(tstate->interp, visited, gcstate->visited_space, true);
15621564
gcstate->work_to_do -= objects_marked;
1563-
#ifdef Py_STATS
1564-
if (_Py_stats) {
1565-
GC_STAT_ADD(1, objects_marked, objects_marked);
1566-
}
1567-
#endif
15681565
gcstate->phase = GC_PHASE_COLLECT;
1566+
return objects_marked;
15691567
}
15701568

15711569
static void
@@ -1575,7 +1573,9 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
15751573
GCState *gcstate = &tstate->interp->gc;
15761574
gcstate->work_to_do += gcstate->young.count;
15771575
if (gcstate->phase == GC_PHASE_MARK) {
1578-
mark_at_start(tstate);
1576+
Py_ssize_t objects_marked = mark_at_start(tstate);
1577+
GC_STAT_ADD(1, objects_transitively_reachable, objects_marked);
1578+
gcstate->work_to_do -= objects_marked;
15791579
return;
15801580
}
15811581
PyGC_Head *not_visited = &gcstate->old[gcstate->visited_space^1].head;
@@ -1586,7 +1586,9 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
15861586
if (scale_factor < 1) {
15871587
scale_factor = 1;
15881588
}
1589-
gcstate->work_to_do -= mark_stacks(tstate->interp, visited, gcstate->visited_space, false);
1589+
Py_ssize_t objects_marked = mark_stacks(tstate->interp, visited, gcstate->visited_space, false);
1590+
GC_STAT_ADD(1, objects_transitively_reachable, objects_marked);
1591+
gcstate->work_to_do -= objects_marked;
15901592
gc_list_set_space(&gcstate->young.head, gcstate->visited_space);
15911593
gc_list_merge(&gcstate->young.head, &increment);
15921594
gcstate->young.count = 0;
@@ -1603,6 +1605,7 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
16031605
gc_set_old_space(gc, gcstate->visited_space);
16041606
increment_size += expand_region_transitively_reachable(&increment, gc, gcstate);
16051607
}
1608+
GC_STAT_ADD(1, objects_not_transitively_reachable, increment_size);
16061609
gc_list_validate_space(&increment, gcstate->visited_space);
16071610
PyGC_Head survivors;
16081611
gc_list_init(&survivors);
@@ -1631,16 +1634,17 @@ gc_collect_full(PyThreadState *tstate,
16311634
PyGC_Head *young = &gcstate->young.head;
16321635
PyGC_Head *pending = &gcstate->old[gcstate->visited_space^1].head;
16331636
PyGC_Head *visited = &gcstate->old[gcstate->visited_space].head;
1634-
mark_global_roots(tstate->interp, visited, gcstate->visited_space);
1635-
mark_stacks(tstate->interp, visited, gcstate->visited_space, true);
16361637
/* merge all generations into pending */
16371638
gc_list_validate_space(young, 1-gcstate->visited_space);
16381639
gc_list_merge(young, pending);
16391640
gc_list_set_space(visited, 1-gcstate->visited_space);
16401641
gc_list_merge(visited, pending);
16411642
/* Mark reachable */
1642-
mark_global_roots(tstate->interp, visited, gcstate->visited_space);
1643-
mark_stacks(tstate->interp, visited, gcstate->visited_space, true);
1643+
Py_ssize_t reachable = mark_global_roots(tstate->interp, visited, gcstate->visited_space);
1644+
reachable += mark_stacks(tstate->interp, visited, gcstate->visited_space, true);
1645+
(void)reachable;
1646+
GC_STAT_ADD(2, objects_transitively_reachable, reachable);
1647+
GC_STAT_ADD(2, objects_not_transitively_reachable, gc_list_size(pending));
16441648
gcstate->young.count = 0;
16451649
gc_list_set_space(pending, gcstate->visited_space);
16461650
gc_collect_region(tstate, pending, visited,

Python/specialize.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,9 @@ print_gc_stats(FILE *out, GCStats *stats)
229229
{
230230
for (int i = 0; i < NUM_GENERATIONS; i++) {
231231
fprintf(out, "GC[%d] collections: %" PRIu64 "\n", i, stats[i].collections);
232-
fprintf(out, "GC[%d] marking visits: %" PRIu64 "\n", i, stats[i].mark_visits);
233232
fprintf(out, "GC[%d] object visits: %" PRIu64 "\n", i, stats[i].object_visits);
234-
fprintf(out, "GC[%d] objects marked: %" PRIu64 "\n", i, stats[i].objects_marked);
233+
fprintf(out, "GC[%d] objects reachable from roots: %" PRIu64 "\n", i, stats[i].objects_transitively_reachable);
234+
fprintf(out, "GC[%d] objects not reachable from roots: %" PRIu64 "\n", i, stats[i].objects_not_transitively_reachable);
235235
fprintf(out, "GC[%d] objects collected: %" PRIu64 "\n", i, stats[i].objects_collected);
236236
}
237237
}

Tools/scripts/summarize_stats.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,8 +1118,8 @@ def calc_gc_stats(stats: Stats) -> Rows:
11181118
Count(gen["collections"]),
11191119
Count(gen["objects collected"]),
11201120
Count(gen["object visits"]),
1121-
Count(gen["marking visits"]),
1122-
Count(gen["objects marked"]),
1121+
Count(gen["objects reachable from roots"]),
1122+
Count(gen["objects not reachable from roots"]),
11231123
)
11241124
for (i, gen) in enumerate(gc_stats)
11251125
]
@@ -1129,7 +1129,8 @@ def calc_gc_stats(stats: Stats) -> Rows:
11291129
"GC collections and effectiveness",
11301130
[
11311131
Table(
1132-
("Generation:", "Collections:", "Objects collected:", "Object visits:", "Marking visits:", "Objects marked:"),
1132+
("Generation:", "Collections:", "Objects collected:", "Object visits:",
1133+
"Reachable from roots:", "Not reachable from roots:"),
11331134
calc_gc_stats,
11341135
)
11351136
],

0 commit comments

Comments
 (0)