mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Add more stats for freelist use and allocations. (GH-92211)
This commit is contained in:
		
							parent
							
								
									e8d7661ff2
								
							
						
					
					
						commit
						836b17c9c3
					
				
					 9 changed files with 43 additions and 0 deletions
				
			
		|  | @ -292,7 +292,12 @@ typedef struct _call_stats { | |||
| 
 | ||||
| typedef struct _object_stats { | ||||
|     uint64_t allocations; | ||||
|     uint64_t allocations512; | ||||
|     uint64_t allocations4k; | ||||
|     uint64_t allocations_big; | ||||
|     uint64_t frees; | ||||
|     uint64_t to_freelist; | ||||
|     uint64_t from_freelist; | ||||
|     uint64_t new_values; | ||||
|     uint64_t dict_materialized_on_request; | ||||
|     uint64_t dict_materialized_new_key; | ||||
|  | @ -313,6 +318,8 @@ extern PyStats _py_stats; | |||
| #define OPCODE_EXE_INC(opname) _py_stats.opcode_stats[opname].execution_count++ | ||||
| #define CALL_STAT_INC(name) _py_stats.call_stats.name++ | ||||
| #define OBJECT_STAT_INC(name) _py_stats.object_stats.name++ | ||||
| #define OBJECT_STAT_INC_COND(name, cond) \ | ||||
|     do { if (cond) _py_stats.object_stats.name++; } while (0) | ||||
| 
 | ||||
| extern void _Py_PrintSpecializationStats(int to_file); | ||||
| 
 | ||||
|  | @ -325,6 +332,7 @@ PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void); | |||
| #define OPCODE_EXE_INC(opname) ((void)0) | ||||
| #define CALL_STAT_INC(name) ((void)0) | ||||
| #define OBJECT_STAT_INC(name) ((void)0) | ||||
| #define OBJECT_STAT_INC_COND(name, cond) ((void)0) | ||||
| #endif  // !Py_STATS
 | ||||
| 
 | ||||
| // Cache values are only valid in memory, so use native endianness.
 | ||||
|  |  | |||
|  | @ -624,6 +624,7 @@ new_keys_object(uint8_t log2_size, bool unicode) | |||
| #endif | ||||
|     if (log2_size == PyDict_LOG_MINSIZE && unicode && state->keys_numfree > 0) { | ||||
|         dk = state->keys_free_list[--state->keys_numfree]; | ||||
|         OBJECT_STAT_INC(from_freelist); | ||||
|     } | ||||
|     else | ||||
| #endif | ||||
|  | @ -681,6 +682,7 @@ free_keys_object(PyDictKeysObject *keys) | |||
|             && state->keys_numfree < PyDict_MAXFREELIST | ||||
|             && DK_IS_UNICODE(keys)) { | ||||
|         state->keys_free_list[state->keys_numfree++] = keys; | ||||
|         OBJECT_STAT_INC(to_freelist); | ||||
|         return; | ||||
|     } | ||||
| #endif | ||||
|  | @ -726,6 +728,7 @@ new_dict(PyDictKeysObject *keys, PyDictValues *values, Py_ssize_t used, int free | |||
|         mp = state->free_list[--state->numfree]; | ||||
|         assert (mp != NULL); | ||||
|         assert (Py_IS_TYPE(mp, &PyDict_Type)); | ||||
|         OBJECT_STAT_INC(from_freelist); | ||||
|         _Py_NewReference((PyObject *)mp); | ||||
|     } | ||||
|     else | ||||
|  | @ -1544,6 +1547,7 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode) | |||
|                     state->keys_numfree < PyDict_MAXFREELIST) | ||||
|             { | ||||
|                 state->keys_free_list[state->keys_numfree++] = oldkeys; | ||||
|                 OBJECT_STAT_INC(to_freelist); | ||||
|             } | ||||
|             else | ||||
| #endif | ||||
|  | @ -2381,6 +2385,7 @@ dict_dealloc(PyDictObject *mp) | |||
| #endif | ||||
|     if (state->numfree < PyDict_MAXFREELIST && Py_IS_TYPE(mp, &PyDict_Type)) { | ||||
|         state->free_list[state->numfree++] = mp; | ||||
|         OBJECT_STAT_INC(to_freelist); | ||||
|     } | ||||
|     else | ||||
| #endif | ||||
|  |  | |||
|  | @ -141,6 +141,7 @@ PyFloat_FromDouble(double fval) | |||
| #endif | ||||
|         state->free_list = (PyFloatObject *) Py_TYPE(op); | ||||
|         state->numfree--; | ||||
|         OBJECT_STAT_INC(from_freelist); | ||||
|     } | ||||
|     else | ||||
| #endif | ||||
|  | @ -256,6 +257,7 @@ _PyFloat_ExactDealloc(PyObject *obj) | |||
|     state->numfree++; | ||||
|     Py_SET_TYPE(op, (PyTypeObject *)state->free_list); | ||||
|     state->free_list = op; | ||||
|     OBJECT_STAT_INC(to_freelist); | ||||
| #else | ||||
|     PyObject_Free(op); | ||||
| #endif | ||||
|  |  | |||
|  | @ -1942,6 +1942,7 @@ async_gen_wrapped_val_dealloc(_PyAsyncGenWrappedValue *o) | |||
|     if (state->value_numfree < _PyAsyncGen_MAXFREELIST) { | ||||
|         assert(_PyAsyncGenWrappedValue_CheckExact(o)); | ||||
|         state->value_freelist[state->value_numfree++] = o; | ||||
|         OBJECT_STAT_INC(to_freelist); | ||||
|     } | ||||
|     else | ||||
| #endif | ||||
|  | @ -2018,6 +2019,7 @@ _PyAsyncGenValueWrapperNew(PyObject *val) | |||
|     if (state->value_numfree) { | ||||
|         state->value_numfree--; | ||||
|         o = state->value_freelist[state->value_numfree]; | ||||
|         OBJECT_STAT_INC(from_freelist); | ||||
|         assert(_PyAsyncGenWrappedValue_CheckExact(o)); | ||||
|         _Py_NewReference((PyObject*)o); | ||||
|     } | ||||
|  |  | |||
|  | @ -158,6 +158,7 @@ PyList_New(Py_ssize_t size) | |||
|     if (PyList_MAXFREELIST && state->numfree) { | ||||
|         state->numfree--; | ||||
|         op = state->free_list[state->numfree]; | ||||
|         OBJECT_STAT_INC(from_freelist); | ||||
|         _Py_NewReference((PyObject *)op); | ||||
|     } | ||||
|     else | ||||
|  | @ -353,6 +354,7 @@ list_dealloc(PyListObject *op) | |||
| #endif | ||||
|     if (state->numfree < PyList_MAXFREELIST && PyList_CheckExact(op)) { | ||||
|         state->free_list[state->numfree++] = op; | ||||
|         OBJECT_STAT_INC(to_freelist); | ||||
|     } | ||||
|     else | ||||
| #endif | ||||
|  |  | |||
|  | @ -616,6 +616,10 @@ PyMem_Malloc(size_t size) | |||
|     /* see PyMem_RawMalloc() */ | ||||
|     if (size > (size_t)PY_SSIZE_T_MAX) | ||||
|         return NULL; | ||||
|     OBJECT_STAT_INC_COND(allocations512, size < 512); | ||||
|     OBJECT_STAT_INC_COND(allocations4k, size >= 512 && size < 4094); | ||||
|     OBJECT_STAT_INC_COND(allocations_big, size >= 4094); | ||||
|     OBJECT_STAT_INC(allocations); | ||||
|     return _PyMem.malloc(_PyMem.ctx, size); | ||||
| } | ||||
| 
 | ||||
|  | @ -625,6 +629,10 @@ PyMem_Calloc(size_t nelem, size_t elsize) | |||
|     /* see PyMem_RawMalloc() */ | ||||
|     if (elsize != 0 && nelem > (size_t)PY_SSIZE_T_MAX / elsize) | ||||
|         return NULL; | ||||
|     OBJECT_STAT_INC_COND(allocations512, elsize < 512); | ||||
|     OBJECT_STAT_INC_COND(allocations4k, elsize >= 512 && elsize < 4094); | ||||
|     OBJECT_STAT_INC_COND(allocations_big, elsize >= 4094); | ||||
|     OBJECT_STAT_INC(allocations); | ||||
|     return _PyMem.calloc(_PyMem.ctx, nelem, elsize); | ||||
| } | ||||
| 
 | ||||
|  | @ -640,6 +648,7 @@ PyMem_Realloc(void *ptr, size_t new_size) | |||
| void | ||||
| PyMem_Free(void *ptr) | ||||
| { | ||||
|     OBJECT_STAT_INC(frees); | ||||
|     _PyMem.free(_PyMem.ctx, ptr); | ||||
| } | ||||
| 
 | ||||
|  | @ -696,6 +705,9 @@ PyObject_Malloc(size_t size) | |||
|     /* see PyMem_RawMalloc() */ | ||||
|     if (size > (size_t)PY_SSIZE_T_MAX) | ||||
|         return NULL; | ||||
|     OBJECT_STAT_INC_COND(allocations512, size < 512); | ||||
|     OBJECT_STAT_INC_COND(allocations4k, size >= 512 && size < 4094); | ||||
|     OBJECT_STAT_INC_COND(allocations_big, size >= 4094); | ||||
|     OBJECT_STAT_INC(allocations); | ||||
|     return _PyObject.malloc(_PyObject.ctx, size); | ||||
| } | ||||
|  | @ -706,6 +718,9 @@ PyObject_Calloc(size_t nelem, size_t elsize) | |||
|     /* see PyMem_RawMalloc() */ | ||||
|     if (elsize != 0 && nelem > (size_t)PY_SSIZE_T_MAX / elsize) | ||||
|         return NULL; | ||||
|     OBJECT_STAT_INC_COND(allocations512, elsize < 512); | ||||
|     OBJECT_STAT_INC_COND(allocations4k, elsize >= 512 && elsize < 4094); | ||||
|     OBJECT_STAT_INC_COND(allocations_big, elsize >= 4094); | ||||
|     OBJECT_STAT_INC(allocations); | ||||
|     return _PyObject.calloc(_PyObject.ctx, nelem, elsize); | ||||
| } | ||||
|  |  | |||
|  | @ -1195,6 +1195,7 @@ maybe_freelist_pop(Py_ssize_t size) | |||
| #endif | ||||
|             _Py_NewReference((PyObject *)op); | ||||
|             /* END inlined _PyObject_InitVar() */ | ||||
|             OBJECT_STAT_INC(from_freelist); | ||||
|             return op; | ||||
|         } | ||||
|     } | ||||
|  | @ -1224,6 +1225,7 @@ maybe_freelist_push(PyTupleObject *op) | |||
|         op->ob_item[0] = (PyObject *) STATE.free_list[index]; | ||||
|         STATE.free_list[index] = op; | ||||
|         STATE.numfree[index]++; | ||||
|         OBJECT_STAT_INC(to_freelist); | ||||
|         return 1; | ||||
|     } | ||||
| #endif | ||||
|  |  | |||
|  | @ -351,6 +351,7 @@ _context_alloc(void) | |||
|         state->numfree--; | ||||
|         ctx = state->freelist; | ||||
|         state->freelist = (PyContext *)ctx->ctx_weakreflist; | ||||
|         OBJECT_STAT_INC(from_freelist); | ||||
|         ctx->ctx_weakreflist = NULL; | ||||
|         _Py_NewReference((PyObject *)ctx); | ||||
|     } | ||||
|  | @ -482,6 +483,7 @@ context_tp_dealloc(PyContext *self) | |||
|         state->numfree++; | ||||
|         self->ctx_weakreflist = (PyObject *)state->freelist; | ||||
|         state->freelist = self; | ||||
|         OBJECT_STAT_INC(to_freelist); | ||||
|     } | ||||
|     else | ||||
| #endif | ||||
|  |  | |||
|  | @ -183,7 +183,12 @@ print_call_stats(FILE *out, CallStats *stats) | |||
| static void | ||||
| print_object_stats(FILE *out, ObjectStats *stats) | ||||
| { | ||||
|     fprintf(out, "Object allocations from freelist: %" PRIu64 "\n", stats->from_freelist); | ||||
|     fprintf(out, "Object frees to freelist: %" PRIu64 "\n", stats->to_freelist); | ||||
|     fprintf(out, "Object allocations: %" PRIu64 "\n", stats->allocations); | ||||
|     fprintf(out, "Object allocations to 512 bytes: %" PRIu64 "\n", stats->allocations512); | ||||
|     fprintf(out, "Object allocations to 4 kbytes: %" PRIu64 "\n", stats->allocations4k); | ||||
|     fprintf(out, "Object allocations over 4 kbytes: %" PRIu64 "\n", stats->allocations_big); | ||||
|     fprintf(out, "Object frees: %" PRIu64 "\n", stats->frees); | ||||
|     fprintf(out, "Object new values: %" PRIu64 "\n", stats->new_values); | ||||
|     fprintf(out, "Object materialize dict (on request): %" PRIu64 "\n", stats->dict_materialized_on_request); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Mark Shannon
						Mark Shannon