• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Statistics on Python performance.
2 //
3 // API:
4 //
5 // - _Py_INCREF_STAT_INC() and _Py_DECREF_STAT_INC() used by Py_INCREF()
6 //   and Py_DECREF().
7 // - _Py_stats variable
8 //
9 // Functions of the sys module:
10 //
11 // - sys._stats_on()
12 // - sys._stats_off()
13 // - sys._stats_clear()
14 // - sys._stats_dump()
15 //
16 // Python must be built with ./configure --enable-pystats to define the
17 // Py_STATS macro.
18 //
19 // Define _PY_INTERPRETER macro to increment interpreter_increfs and
20 // interpreter_decrefs. Otherwise, increment increfs and decrefs.
21 
22 #ifndef Py_CPYTHON_PYSTATS_H
23 #  error "this header file must not be included directly"
24 #endif
25 
26 #define PYSTATS_MAX_UOP_ID 512
27 
28 #define SPECIALIZATION_FAILURE_KINDS 36
29 
30 /* Stats for determining who is calling PyEval_EvalFrame */
31 #define EVAL_CALL_TOTAL 0
32 #define EVAL_CALL_VECTOR 1
33 #define EVAL_CALL_GENERATOR 2
34 #define EVAL_CALL_LEGACY 3
35 #define EVAL_CALL_FUNCTION_VECTORCALL 4
36 #define EVAL_CALL_BUILD_CLASS 5
37 #define EVAL_CALL_SLOT 6
38 #define EVAL_CALL_FUNCTION_EX 7
39 #define EVAL_CALL_API 8
40 #define EVAL_CALL_METHOD 9
41 
42 #define EVAL_CALL_KINDS 10
43 
44 typedef struct _specialization_stats {
45     uint64_t success;
46     uint64_t failure;
47     uint64_t hit;
48     uint64_t deferred;
49     uint64_t miss;
50     uint64_t deopt;
51     uint64_t failure_kinds[SPECIALIZATION_FAILURE_KINDS];
52 } SpecializationStats;
53 
54 typedef struct _opcode_stats {
55     SpecializationStats specialization;
56     uint64_t execution_count;
57     uint64_t pair_count[256];
58 } OpcodeStats;
59 
60 typedef struct _call_stats {
61     uint64_t inlined_py_calls;
62     uint64_t pyeval_calls;
63     uint64_t frames_pushed;
64     uint64_t frame_objects_created;
65     uint64_t eval_calls[EVAL_CALL_KINDS];
66 } CallStats;
67 
68 typedef struct _object_stats {
69     uint64_t increfs;
70     uint64_t decrefs;
71     uint64_t interpreter_increfs;
72     uint64_t interpreter_decrefs;
73     uint64_t allocations;
74     uint64_t allocations512;
75     uint64_t allocations4k;
76     uint64_t allocations_big;
77     uint64_t frees;
78     uint64_t to_freelist;
79     uint64_t from_freelist;
80     uint64_t inline_values;
81     uint64_t dict_materialized_on_request;
82     uint64_t dict_materialized_new_key;
83     uint64_t dict_materialized_too_big;
84     uint64_t dict_materialized_str_subclass;
85     uint64_t type_cache_hits;
86     uint64_t type_cache_misses;
87     uint64_t type_cache_dunder_hits;
88     uint64_t type_cache_dunder_misses;
89     uint64_t type_cache_collisions;
90     /* Temporary value used during GC */
91     uint64_t object_visits;
92 } ObjectStats;
93 
94 typedef struct _gc_stats {
95     uint64_t collections;
96     uint64_t object_visits;
97     uint64_t objects_collected;
98 } GCStats;
99 
100 typedef struct _uop_stats {
101     uint64_t execution_count;
102     uint64_t miss;
103     uint64_t pair_count[PYSTATS_MAX_UOP_ID + 1];
104 } UOpStats;
105 
106 #define _Py_UOP_HIST_SIZE 32
107 
108 typedef struct _optimization_stats {
109     uint64_t attempts;
110     uint64_t traces_created;
111     uint64_t traces_executed;
112     uint64_t uops_executed;
113     uint64_t trace_stack_overflow;
114     uint64_t trace_stack_underflow;
115     uint64_t trace_too_long;
116     uint64_t trace_too_short;
117     uint64_t inner_loop;
118     uint64_t recursive_call;
119     uint64_t low_confidence;
120     uint64_t executors_invalidated;
121     UOpStats opcode[PYSTATS_MAX_UOP_ID + 1];
122     uint64_t unsupported_opcode[256];
123     uint64_t trace_length_hist[_Py_UOP_HIST_SIZE];
124     uint64_t trace_run_length_hist[_Py_UOP_HIST_SIZE];
125     uint64_t optimized_trace_length_hist[_Py_UOP_HIST_SIZE];
126     uint64_t optimizer_attempts;
127     uint64_t optimizer_successes;
128     uint64_t optimizer_failure_reason_no_memory;
129     uint64_t remove_globals_builtins_changed;
130     uint64_t remove_globals_incorrect_keys;
131     uint64_t error_in_opcode[PYSTATS_MAX_UOP_ID + 1];
132 } OptimizationStats;
133 
134 typedef struct _rare_event_stats {
135     /* Setting an object's class, obj.__class__ = ... */
136     uint64_t set_class;
137     /* Setting the bases of a class, cls.__bases__ = ... */
138     uint64_t set_bases;
139     /* Setting the PEP 523 frame eval function, _PyInterpreterState_SetFrameEvalFunc() */
140     uint64_t set_eval_frame_func;
141     /* Modifying the builtins,  __builtins__.__dict__[var] = ... */
142     uint64_t builtin_dict;
143     /* Modifying a function, e.g. func.__defaults__ = ..., etc. */
144     uint64_t func_modification;
145     /* Modifying a dict that is being watched */
146     uint64_t watched_dict_modification;
147     uint64_t watched_globals_modification;
148 } RareEventStats;
149 
150 typedef struct _stats {
151     OpcodeStats opcode_stats[256];
152     CallStats call_stats;
153     ObjectStats object_stats;
154     OptimizationStats optimization_stats;
155     RareEventStats rare_event_stats;
156     GCStats *gc_stats;
157 } PyStats;
158 
159 
160 // Export for shared extensions like 'math'
161 PyAPI_DATA(PyStats*) _Py_stats;
162 
163 #ifdef _PY_INTERPRETER
164 #  define _Py_INCREF_STAT_INC() do { if (_Py_stats) _Py_stats->object_stats.interpreter_increfs++; } while (0)
165 #  define _Py_DECREF_STAT_INC() do { if (_Py_stats) _Py_stats->object_stats.interpreter_decrefs++; } while (0)
166 #else
167 #  define _Py_INCREF_STAT_INC() do { if (_Py_stats) _Py_stats->object_stats.increfs++; } while (0)
168 #  define _Py_DECREF_STAT_INC() do { if (_Py_stats) _Py_stats->object_stats.decrefs++; } while (0)
169 #endif
170