Skip to content

Commit a3cfb7e

Browse files
committed
Split stats zeroing into separate functions.
This is a bit more efficient, with the downside of a bit extra code. For _PyStats_Clear(), we don't need to do the merging operation. I think the code is a bit more clear this way.
1 parent 0e09267 commit a3cfb7e

File tree

1 file changed

+36
-15
lines changed

1 file changed

+36
-15
lines changed

Python/pystats.c

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -530,9 +530,16 @@ merge_gc_stats_array(GCStats *dest, const GCStats *src)
530530
}
531531
}
532532

533+
void
534+
stats_zero_thread(_PyThreadStateImpl *tstate)
535+
{
536+
// Zero the thread local stat counters
537+
memset(tstate->pystats_struct, 0, sizeof(PyStats));
538+
}
539+
533540
// merge stats for a single thread into the global structure
534541
void
535-
stats_merge_thread(_PyThreadStateImpl *tstate, bool zero)
542+
stats_merge_thread(_PyThreadStateImpl *tstate)
536543
{
537544
PyStats *src = tstate->pystats_struct;
538545
PyStats *dest = ((PyThreadState *)tstate)->interp->pystats_struct;
@@ -549,11 +556,6 @@ stats_merge_thread(_PyThreadStateImpl *tstate, bool zero)
549556
merge_ft_stats(&dest->ft_stats, &src->ft_stats);
550557
merge_rare_event_stats(&dest->rare_event_stats, &src->rare_event_stats);
551558
merge_gc_stats_array(dest->gc_stats, src->gc_stats);
552-
553-
if (zero) {
554-
// Zero the source stat counters
555-
memset(src, 0, sizeof(PyStats));
556-
}
557559
}
558560
#endif // Py_GIL_DISABLED
559561

@@ -602,10 +604,9 @@ stats_toggle_on_off(PyThreadState *tstate, int on)
602604
return 0;
603605
}
604606

605-
// merge stats for all threads into the per-interpreter structure
606-
// if 'zero' is true then the per-interpreter stats are zeroed after merging
607+
// zero stats for all threads and for the interpreter
607608
static void
608-
stats_merge_all(bool zero)
609+
stats_zero_all(void)
609610
{
610611
PyThreadState *tstate = _PyThreadState_GET();
611612
if (tstate == NULL) {
@@ -618,12 +619,32 @@ stats_merge_all(bool zero)
618619
_PyEval_StopTheWorld(interp);
619620
#ifdef Py_GIL_DISABLED
620621
_Py_FOR_EACH_TSTATE_UNLOCKED(interp, ts) {
621-
stats_merge_thread((_PyThreadStateImpl *)ts, true);
622+
stats_zero_thread((_PyThreadStateImpl *)ts);
622623
}
623624
#endif
624-
if (zero) {
625-
memset(interp->pystats_struct, 0, sizeof(PyStats));
625+
memset(interp->pystats_struct, 0, sizeof(PyStats));
626+
_PyEval_StartTheWorld(interp);
627+
}
628+
629+
// merge stats for all threads into the per-interpreter structure
630+
static void
631+
stats_merge_all(void)
632+
{
633+
PyThreadState *tstate = _PyThreadState_GET();
634+
if (tstate == NULL) {
635+
return;
636+
}
637+
if (FT_ATOMIC_LOAD_PTR_RELAXED(tstate->interp->pystats_struct) == NULL) {
638+
return;
626639
}
640+
PyInterpreterState *interp = tstate->interp;
641+
_PyEval_StopTheWorld(interp);
642+
#ifdef Py_GIL_DISABLED
643+
_Py_FOR_EACH_TSTATE_UNLOCKED(interp, ts) {
644+
stats_merge_thread((_PyThreadStateImpl *)ts);
645+
stats_zero_thread((_PyThreadStateImpl *)ts);
646+
}
647+
#endif
627648
_PyEval_StartTheWorld(interp);
628649
}
629650

@@ -644,7 +665,7 @@ _Py_StatsOff(void)
644665
void
645666
_Py_StatsClear(void)
646667
{
647-
stats_merge_all(true);
668+
stats_zero_all();
648669
}
649670

650671
static int
@@ -663,7 +684,7 @@ int
663684
_Py_PrintSpecializationStats(int to_file)
664685
{
665686
assert(to_file);
666-
stats_merge_all(false);
687+
stats_merge_all();
667688
PyThreadState *tstate = _PyThreadState_GET();
668689
STATS_LOCK(tstate->interp);
669690
PyStats *stats = tstate->interp->pystats_struct;
@@ -761,7 +782,7 @@ _PyStats_ThreadFini(_PyThreadStateImpl *tstate)
761782
{
762783
#ifdef Py_GIL_DISABLED
763784
STATS_LOCK(((PyThreadState *)tstate)->interp);
764-
stats_merge_thread(tstate, false);
785+
stats_merge_thread(tstate);
765786
STATS_UNLOCK(((PyThreadState *)tstate)->interp);
766787
PyMem_RawFree(tstate->pystats_struct);
767788
#endif

0 commit comments

Comments
 (0)