Adding two integers in CPython
Posted on 25 November 2017Ignoring cheap operations (arithmetic, logical, bits) and some not-so-cheap operations (branching), this is the operational cost of adding two integers in CPython.
-
1 (hot) indirect read: read bytecode buffer. (NEXTOP macro)
-
1 jump-table jump: instruction selection (BINARY_ADD in this case).
-
2 (hot) indirect reads: pop the evaluation stack. (POP macro, TOP macro)
-
2 indirect reads: RTTI check for int type. (PyInt_CheckExact macro)
-
2 indirect reads: extract int value. (PyInt_AS_LONG macro)
-
1 unsigned long add: the actual addition (maybe).
-
1 overflow check. Four paths:
-
“Fast” path: (cached int object)
-
1 range check: determine if value is cached.
-
1 (warm) global read: read the cached object.
-
1 indirect increment: reference count.
-
-
“Slow” path: (not cached; int object ‘free list’ not full)
-
1 global read: use free list.
-
1 global write: advance free list.
-
1 indirect write: set object type. (PyObject_INIT macro)
-
1 indirect write: initialize reference count. (_Py_NewReference macro)
-
1 indirect write: set integer value.
-
-
“Slower” path: (not cached; free list full / not allocated)
-
1 memory allocation: allocate new PyIntObject free list.
-
1 indirect write: chain new free list to current (full) free list.
-
1 global write: set new free list as current free list.
-
1000 (hot) indirect writes: link PyIntObjects to each other.
-
Go to “Slow” path.
-
-
“Slowest” path: (addition overflow)
-
2 indirect reads: RTTI check.
-
1 double-indirect reads: read number method table.
-
1 triple-indirect reads: read addition method from table. (NB_BINOP)
-
1 quadruple-indirect call: go to int addition. (int_add)
-
2 indirect reads: RTTI check for int type. (CONVERT_TO_LONG)
-
2 indirect reads: extract int value.
-
1 unsigned long add: the actual addition (again).
-
1 overflow check (again).
-
1 global read: read PyLong_Type number method table.
-
1 indirect read: read long addition method.
-
1 doubly-indirect call: go to long addition. (long_add)
-
Convert ints to longs: (CONVERT_BINOP macro)
-
2 indirect reads: RTTI check for int type.
-
2 indirect reads: extract int value (third time). (PyInt_AS_LONG)
-
Allocate temporary long objects: (in PyLong_FromLong)
- Quite extensive, not going into detail.
-
-
1 object allocation: for addition result.
- Quite extensive, not going into detail.
-
4* indirect reads & writes: arbitrary-precision addition.
-
2 indirect decrements: refcount for temporary longs. (Py_DECREF)
-
2 indirect function calls: object deallocation. (_Py_Dealloc)
-
-
-
2 indirect decrements: refcount for popped stack values. (Py_DECREF)
-
(Possible) 2 indirect function calls: object deallocation. (_Py_Dealloc)
-
1 (hot) indirect write: set top of evaluation stack. (SET_TOP macro)