
2016-01-09 23:18 GMT+01:00 Terry Reedy <tjreedy@udel.edu>:
But as near as I can tell, your proposal cannot detect all relevant changes unless one is *very* careful. A dict maps hashable objects to objects. Objects represent values. So a dict represents a mapping of values to values. If an object is mutated, the object to object mapping is not changed, but the semantic value to value mapping *is* changed. In the following example, __version__ twice gives the 'wrong' answer from a value perspective.
dict.__version__ is a technical solution to implement efficient guards on namespace. You are true, that it's not enough to detect any kind of change. For example, to inline a function inside the same module, we need a guard on the global variable, but also a guard on the function itself. We need to disable the optimization if the function code (func.__code__) is modified. Maybe a guard is also needed on default values of function parameters. But guards on functions don't need to modify CPython internals. It's already possible to implement efficient guards on functions.
Replacing a call with a return value assumes that the function is immutable, deterministic, and without side-effect.
that the function is deterministic and has no side-effect, yep.
Perhaps this is what you meant by 'pure'. Are you proposing to provide astoptimizer with either a whitelist or blacklist of builtins that qualify or not?
Currently, I'm using a whitelist of builtin functions which are known to be pure. Later, I plan to detect automatically pure functions by analyzing the (AST) code.
Aside from this, I don't find this example motivational. I would either write '3' in the first place or write something like "slen = len('akjslkjgkjsdkfjsldjkfs')" outside of any loop. I would more likely write something like "key = 'jlkjfksjlkdfjlskfjkslkjeicji'; key_len = len(key)" to keep a reference to both the string and its length. Will astoptimizer 'propogate the constant' (in this case 'key')?
FYI I already have a working implementation of the astoptimizer: it's possible to run the full Python test suite with the optimizer. Implemented optimizations: https://faster-cpython.readthedocs.org/fat_python.html#optimizations Constant propagation and constant folding optimizations are implemented. A single optimization is not interesting, It's more interesting when you combine optimizations. Like constant propagation + constant folding + loop unrolling.
The question in my mind is whether real code has enough pure builtin calls of constants to justify the overhead.
Replacing len("abc") with 3 is not the goal of FAT Python. It's only an example simple to understand.
How often is this useful in modern real-world Python code? Many old uses of range have been or could be replaced with enumerate or a collection iterator, making it less common than it once was.
IMHO the optimizations currently implemented will not provide any major speedup. It will become more interesting with function inlining. The idea is more to create an API to support pluggable static optimizations.
How often is N small enough that one wants complete versus partial unrolling? Wouldn't it be simpler to only use a (specialized) loop-unroller where range is known to be the builtin?
What is the link between your question and dict.__version__? Victor