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