Add specialization stats for FOR_ITER. (GH-31079)

This commit is contained in:
Mark Shannon 2022-02-02 15:56:47 +00:00 committed by GitHub
parent f66c857572
commit 0d05da1fbf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 1 deletions

View file

@ -4212,6 +4212,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
PREDICTED(FOR_ITER);
/* before: [iter]; after: [iter, iter()] *or* [] */
PyObject *iter = TOP();
#ifdef Py_STATS
extern int _PySpecialization_ClassifyIterator(PyObject *);
_py_stats.opcode_stats[FOR_ITER].specialization.failure++;
_py_stats.opcode_stats[FOR_ITER].specialization.failure_kinds[_PySpecialization_ClassifyIterator(iter)]++;
#endif
PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter);
if (next != NULL) {
PUSH(next);

View file

@ -548,6 +548,23 @@ initial_counter_value(void) {
#define SPEC_FAIL_NOT_FOLLOWED_BY_COND_JUMP 14
#define SPEC_FAIL_BIG_INT 15
/* FOR_ITER */
#define SPEC_FAIL_ITER_GENERATOR 10
#define SPEC_FAIL_ITER_COROUTINE 11
#define SPEC_FAIL_ITER_ASYNC_GENERATOR 12
#define SPEC_FAIL_ITER_LIST 13
#define SPEC_FAIL_ITER_TUPLE 14
#define SPEC_FAIL_ITER_SET 15
#define SPEC_FAIL_ITER_STRING 16
#define SPEC_FAIL_ITER_BYTES 17
#define SPEC_FAIL_ITER_RANGE 18
#define SPEC_FAIL_ITER_ITERTOOLS 19
#define SPEC_FAIL_ITER_DICT_KEYS 20
#define SPEC_FAIL_ITER_DICT_ITEMS 21
#define SPEC_FAIL_ITER_DICT_VALUES 22
#define SPEC_FAIL_ITER_ENUMERATE 23
static int
specialize_module_load_attr(
PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
@ -1817,3 +1834,54 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs,
STAT_INC(COMPARE_OP, success);
adaptive->counter = initial_counter_value();
}
int
_PySpecialization_ClassifyIterator(PyObject *iter)
{
if (PyGen_CheckExact(iter)) {
return SPEC_FAIL_ITER_GENERATOR;
}
if (PyCoro_CheckExact(iter)) {
return SPEC_FAIL_ITER_COROUTINE;
}
if (PyAsyncGen_CheckExact(iter)) {
return SPEC_FAIL_ITER_ASYNC_GENERATOR;
}
PyTypeObject *t = _Py_TYPE(iter);
if (t == &PyListIter_Type) {
return SPEC_FAIL_ITER_LIST;
}
if (t == &PyTupleIter_Type) {
return SPEC_FAIL_ITER_TUPLE;
}
if (t == &PyDictIterKey_Type) {
return SPEC_FAIL_ITER_DICT_KEYS;
}
if (t == &PyDictIterValue_Type) {
return SPEC_FAIL_ITER_DICT_VALUES;
}
if (t == &PyDictIterItem_Type) {
return SPEC_FAIL_ITER_DICT_ITEMS;
}
if (t == &PySetIter_Type) {
return SPEC_FAIL_ITER_SET;
}
if (t == &PyUnicodeIter_Type) {
return SPEC_FAIL_ITER_STRING;
}
if (t == &PyBytesIter_Type) {
return SPEC_FAIL_ITER_BYTES;
}
if (t == &PyRangeIter_Type) {
return SPEC_FAIL_ITER_RANGE;
}
if (t == &PyEnum_Type) {
return SPEC_FAIL_ITER_ENUMERATE;
}
if (strncmp(t->tp_name, "itertools", 8) == 0) {
return SPEC_FAIL_ITER_ITERTOOLS;
}
return SPEC_FAIL_OTHER;
}

View file

@ -26,7 +26,7 @@
TOTAL = "specialization.deferred", "specialization.hit", "specialization.miss", "execution_count"
def print_specialization_stats(name, family_stats):
if "specialization.deferred" not in family_stats:
if "specialization.failure" not in family_stats:
return
total = sum(family_stats.get(kind, 0) for kind in TOTAL)
if total == 0: