mirror of
https://github.com/python/cpython.git
synced 2026-01-06 15:32:22 +00:00
bpo-46072: Add top level stats struct (GH-30169)
This commit is contained in:
parent
396b58345f
commit
efd6236d36
6 changed files with 153 additions and 102 deletions
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
Py_ssize_t _Py_QuickenedCount = 0;
|
||||
#ifdef Py_STATS
|
||||
SpecializationStats _specialization_stats[256] = { 0 };
|
||||
PyStats _py_stats = { 0 };
|
||||
|
||||
#define ADD_STAT_TO_DICT(res, field) \
|
||||
do { \
|
||||
|
|
@ -64,20 +64,19 @@ stats_to_dict(SpecializationStats *stats)
|
|||
if (res == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ADD_STAT_TO_DICT(res, specialization_success);
|
||||
ADD_STAT_TO_DICT(res, specialization_failure);
|
||||
ADD_STAT_TO_DICT(res, success);
|
||||
ADD_STAT_TO_DICT(res, failure);
|
||||
ADD_STAT_TO_DICT(res, hit);
|
||||
ADD_STAT_TO_DICT(res, deferred);
|
||||
ADD_STAT_TO_DICT(res, miss);
|
||||
ADD_STAT_TO_DICT(res, deopt);
|
||||
ADD_STAT_TO_DICT(res, unquickened);
|
||||
PyObject *failure_kinds = PyTuple_New(SPECIALIZATION_FAILURE_KINDS);
|
||||
if (failure_kinds == NULL) {
|
||||
Py_DECREF(res);
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 0; i < SPECIALIZATION_FAILURE_KINDS; i++) {
|
||||
PyObject *stat = PyLong_FromUnsignedLongLong(stats->specialization_failure_kinds[i]);
|
||||
PyObject *stat = PyLong_FromUnsignedLongLong(stats->failure_kinds[i]);
|
||||
if (stat == NULL) {
|
||||
Py_DECREF(res);
|
||||
Py_DECREF(failure_kinds);
|
||||
|
|
@ -85,7 +84,7 @@ stats_to_dict(SpecializationStats *stats)
|
|||
}
|
||||
PyTuple_SET_ITEM(failure_kinds, i, stat);
|
||||
}
|
||||
if (PyDict_SetItemString(res, "specialization_failure_kinds", failure_kinds)) {
|
||||
if (PyDict_SetItemString(res, "failure_kinds", failure_kinds)) {
|
||||
Py_DECREF(res);
|
||||
Py_DECREF(failure_kinds);
|
||||
return NULL;
|
||||
|
|
@ -101,7 +100,7 @@ add_stat_dict(
|
|||
int opcode,
|
||||
const char *name) {
|
||||
|
||||
SpecializationStats *stats = &_specialization_stats[opcode];
|
||||
SpecializationStats *stats = &_py_stats.opcode_stats[opcode].specialization;
|
||||
PyObject *d = stats_to_dict(stats);
|
||||
if (d == NULL) {
|
||||
return -1;
|
||||
|
|
@ -137,25 +136,38 @@ _Py_GetSpecializationStats(void) {
|
|||
#endif
|
||||
|
||||
|
||||
#define PRINT_STAT(name, field) fprintf(out, " %s." #field " : %" PRIu64 "\n", name, stats->field);
|
||||
#define PRINT_STAT(i, field) \
|
||||
if (stats[i].field) { \
|
||||
fprintf(out, " opcode[%d]." #field " : %" PRIu64 "\n", i, stats[i].field); \
|
||||
}
|
||||
|
||||
static void
|
||||
print_stats(FILE *out, SpecializationStats *stats, const char *name)
|
||||
print_spec_stats(FILE *out, OpcodeStats *stats)
|
||||
{
|
||||
PRINT_STAT(name, specialization_success);
|
||||
PRINT_STAT(name, specialization_failure);
|
||||
PRINT_STAT(name, hit);
|
||||
PRINT_STAT(name, deferred);
|
||||
PRINT_STAT(name, miss);
|
||||
PRINT_STAT(name, deopt);
|
||||
PRINT_STAT(name, unquickened);
|
||||
for (int i = 0; i < SPECIALIZATION_FAILURE_KINDS; i++) {
|
||||
fprintf(out, " %s.specialization_failure_kinds[%d] : %" PRIu64 "\n",
|
||||
name, i, stats->specialization_failure_kinds[i]);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
PRINT_STAT(i, specialization.success);
|
||||
PRINT_STAT(i, specialization.failure);
|
||||
PRINT_STAT(i, specialization.hit);
|
||||
PRINT_STAT(i, specialization.deferred);
|
||||
PRINT_STAT(i, specialization.miss);
|
||||
PRINT_STAT(i, specialization.deopt);
|
||||
PRINT_STAT(i, execution_count);
|
||||
for (int j = 0; j < SPECIALIZATION_FAILURE_KINDS; j++) {
|
||||
uint64_t val = stats[i].specialization.failure_kinds[j];
|
||||
if (val) {
|
||||
fprintf(out, " opcode[%d].specialization.failure_kinds[%d] : %"
|
||||
PRIu64 "\n", i, j, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef PRINT_STAT
|
||||
|
||||
static void
|
||||
print_stats(FILE *out, PyStats *stats) {
|
||||
print_spec_stats(out, stats->opcode_stats);
|
||||
}
|
||||
|
||||
void
|
||||
_Py_PrintSpecializationStats(int to_file)
|
||||
{
|
||||
|
|
@ -189,15 +201,7 @@ _Py_PrintSpecializationStats(int to_file)
|
|||
else {
|
||||
fprintf(out, "Specialization stats:\n");
|
||||
}
|
||||
print_stats(out, &_specialization_stats[LOAD_ATTR], "load_attr");
|
||||
print_stats(out, &_specialization_stats[LOAD_GLOBAL], "load_global");
|
||||
print_stats(out, &_specialization_stats[LOAD_METHOD], "load_method");
|
||||
print_stats(out, &_specialization_stats[BINARY_SUBSCR], "binary_subscr");
|
||||
print_stats(out, &_specialization_stats[STORE_SUBSCR], "store_subscr");
|
||||
print_stats(out, &_specialization_stats[STORE_ATTR], "store_attr");
|
||||
print_stats(out, &_specialization_stats[CALL_NO_KW], "call_no_kw");
|
||||
print_stats(out, &_specialization_stats[BINARY_OP], "binary_op");
|
||||
print_stats(out, &_specialization_stats[COMPARE_OP], "compare_op");
|
||||
print_stats(out, &_py_stats);
|
||||
if (out != stderr) {
|
||||
fclose(out);
|
||||
}
|
||||
|
|
@ -205,7 +209,7 @@ _Py_PrintSpecializationStats(int to_file)
|
|||
|
||||
#ifdef Py_STATS
|
||||
|
||||
#define SPECIALIZATION_FAIL(opcode, kind) _specialization_stats[opcode].specialization_failure_kinds[kind]++
|
||||
#define SPECIALIZATION_FAIL(opcode, kind) _py_stats.opcode_stats[opcode].specialization.failure_kinds[kind]++
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -775,12 +779,12 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, Sp
|
|||
goto success;
|
||||
}
|
||||
fail:
|
||||
STAT_INC(LOAD_ATTR, specialization_failure);
|
||||
STAT_INC(LOAD_ATTR, failure);
|
||||
assert(!PyErr_Occurred());
|
||||
cache_backoff(cache0);
|
||||
return 0;
|
||||
success:
|
||||
STAT_INC(LOAD_ATTR, specialization_success);
|
||||
STAT_INC(LOAD_ATTR, success);
|
||||
assert(!PyErr_Occurred());
|
||||
cache0->counter = initial_counter_value();
|
||||
return 0;
|
||||
|
|
@ -857,12 +861,12 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, S
|
|||
goto success;
|
||||
}
|
||||
fail:
|
||||
STAT_INC(STORE_ATTR, specialization_failure);
|
||||
STAT_INC(STORE_ATTR, failure);
|
||||
assert(!PyErr_Occurred());
|
||||
cache_backoff(cache0);
|
||||
return 0;
|
||||
success:
|
||||
STAT_INC(STORE_ATTR, specialization_success);
|
||||
STAT_INC(STORE_ATTR, success);
|
||||
assert(!PyErr_Occurred());
|
||||
cache0->counter = initial_counter_value();
|
||||
return 0;
|
||||
|
|
@ -1013,12 +1017,12 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
|
|||
cache2->obj = descr;
|
||||
// Fall through.
|
||||
success:
|
||||
STAT_INC(LOAD_METHOD, specialization_success);
|
||||
STAT_INC(LOAD_METHOD, success);
|
||||
assert(!PyErr_Occurred());
|
||||
cache0->counter = initial_counter_value();
|
||||
return 0;
|
||||
fail:
|
||||
STAT_INC(LOAD_METHOD, specialization_failure);
|
||||
STAT_INC(LOAD_METHOD, failure);
|
||||
assert(!PyErr_Occurred());
|
||||
cache_backoff(cache0);
|
||||
return 0;
|
||||
|
|
@ -1084,12 +1088,12 @@ _Py_Specialize_LoadGlobal(
|
|||
*instr = _Py_MAKECODEUNIT(LOAD_GLOBAL_BUILTIN, _Py_OPARG(*instr));
|
||||
goto success;
|
||||
fail:
|
||||
STAT_INC(LOAD_GLOBAL, specialization_failure);
|
||||
STAT_INC(LOAD_GLOBAL, failure);
|
||||
assert(!PyErr_Occurred());
|
||||
cache_backoff(cache0);
|
||||
return 0;
|
||||
success:
|
||||
STAT_INC(LOAD_GLOBAL, specialization_success);
|
||||
STAT_INC(LOAD_GLOBAL, success);
|
||||
assert(!PyErr_Occurred());
|
||||
cache0->counter = initial_counter_value();
|
||||
return 0;
|
||||
|
|
@ -1211,12 +1215,12 @@ _Py_Specialize_BinarySubscr(
|
|||
SPECIALIZATION_FAIL(BINARY_SUBSCR,
|
||||
binary_subscr_fail_kind(container_type, sub));
|
||||
fail:
|
||||
STAT_INC(BINARY_SUBSCR, specialization_failure);
|
||||
STAT_INC(BINARY_SUBSCR, failure);
|
||||
assert(!PyErr_Occurred());
|
||||
cache_backoff(cache0);
|
||||
return 0;
|
||||
success:
|
||||
STAT_INC(BINARY_SUBSCR, specialization_success);
|
||||
STAT_INC(BINARY_SUBSCR, success);
|
||||
assert(!PyErr_Occurred());
|
||||
cache0->counter = initial_counter_value();
|
||||
return 0;
|
||||
|
|
@ -1259,12 +1263,12 @@ _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *ins
|
|||
goto fail;
|
||||
}
|
||||
fail:
|
||||
STAT_INC(STORE_SUBSCR, specialization_failure);
|
||||
STAT_INC(STORE_SUBSCR, failure);
|
||||
assert(!PyErr_Occurred());
|
||||
*instr = _Py_MAKECODEUNIT(_Py_OPCODE(*instr), ADAPTIVE_CACHE_BACKOFF);
|
||||
return 0;
|
||||
success:
|
||||
STAT_INC(STORE_SUBSCR, specialization_success);
|
||||
STAT_INC(STORE_SUBSCR, success);
|
||||
assert(!PyErr_Occurred());
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1518,12 +1522,12 @@ _Py_Specialize_CallNoKw(
|
|||
}
|
||||
_PyAdaptiveEntry *cache0 = &cache->adaptive;
|
||||
if (fail) {
|
||||
STAT_INC(CALL_NO_KW, specialization_failure);
|
||||
STAT_INC(CALL_NO_KW, failure);
|
||||
assert(!PyErr_Occurred());
|
||||
cache_backoff(cache0);
|
||||
}
|
||||
else {
|
||||
STAT_INC(CALL_NO_KW, specialization_success);
|
||||
STAT_INC(CALL_NO_KW, success);
|
||||
assert(!PyErr_Occurred());
|
||||
cache0->counter = initial_counter_value();
|
||||
}
|
||||
|
|
@ -1604,11 +1608,11 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
|
|||
}
|
||||
SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_OTHER);
|
||||
failure:
|
||||
STAT_INC(BINARY_OP, specialization_failure);
|
||||
STAT_INC(BINARY_OP, failure);
|
||||
cache_backoff(adaptive);
|
||||
return;
|
||||
success:
|
||||
STAT_INC(BINARY_OP, specialization_success);
|
||||
STAT_INC(BINARY_OP, success);
|
||||
adaptive->counter = initial_counter_value();
|
||||
}
|
||||
|
||||
|
|
@ -1675,10 +1679,10 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs,
|
|||
}
|
||||
SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_OTHER);
|
||||
failure:
|
||||
STAT_INC(COMPARE_OP, specialization_failure);
|
||||
STAT_INC(COMPARE_OP, failure);
|
||||
cache_backoff(adaptive);
|
||||
return;
|
||||
success:
|
||||
STAT_INC(COMPARE_OP, specialization_success);
|
||||
STAT_INC(COMPARE_OP, success);
|
||||
adaptive->counter = initial_counter_value();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue