DescriptionEvery generic attribute lookup (ie no overridden __getattribute__) starts by hitting _PyType_Lookup on the type and then maybe hitting the object dict if it exists. If we know the type through feedback, we can 1) cache the result of _PyType_Lookup (the descriptor) and 2) skip the dict lookup if the dict doesn't exist.
This is implemented by digging out the code from PyObject_Generic[G|S]etAttr and inlining it with extra constant parameters that are fixed at compilation time. LLVM then propagates those constants through the inlined body and does the Right Thing.
2to3:
22.120000 -> 21.800000: 1.47% faster
django:
Min: 0.594583 -> 0.582381: 2.10% faster
Avg: 0.604536 -> 0.588952: 2.65% faster
Significant (t=17.944955, a=0.95)
Stddev: 0.00518 -> 0.00330: 57.04% smaller
rietveld:
Min: 0.392147 -> 0.381066: 2.91% faster
Avg: 0.399033 -> 0.389779: 2.37% faster
Significant (t=5.930455, a=0.95)
Stddev: 0.00808 -> 0.00752: 7.39% smaller
slowpickle:
Min: 0.389578 -> 0.351653: 10.78% faster
Avg: 0.395050 -> 0.352043: 12.22% faster
Significant (t=95.702589, a=0.95)
Stddev: 0.00317 -> 0.00018: 1631.34% smaller
slowspitfire:
Min: 0.346205 -> 0.337817: 2.48% faster
Avg: 0.347899 -> 0.339405: 2.50% faster
Significant (t=8.062652, a=0.95)
Stddev: 0.00531 -> 0.00523: 1.61% smaller
slowunpickle:
Min: 0.193255 -> 0.172468: 12.05% faster
Avg: 0.195854 -> 0.172629: 13.45% faster
Significant (t=132.029606, a=0.95)
Stddev: 0.00124 -> 0.00011: 1057.79% smaller
Patch Set 1 #Patch Set 2 : Refactor and optimize STORE_ATTR #Patch Set 3 : Minor cleanups #Patch Set 4 : Fix a memory leak #
Total comments: 83
Patch Set 5 : Refactored attribute access data and code into a helper class #
Total comments: 45
Patch Set 6 : Round 2, merge with trunk #
Total comments: 8
MessagesTotal messages: 8
|