Slowness in compile()/eval()

Pedro Rodriguez pedro_rodriguez at club-internet.fr
Thu Jan 17 11:35:37 EST 2002


Thanks for taking time to answer Alex, but with your remarks
I can narrow the things that bother me (questions are inline)

"Alex Martelli" <aleax at aleax.it> wrote:

> "Pedro Rodriguez" <pedro_rodriguez at club-internet.fr> wrote in message
> news:pan.2002.01.17.14.19.06.888663.2742 at club-internet.fr...
>> Hello,
>>
>> while investigating on lazy evaluations, I found these strange results
>> while doing some timings. I expected that using :
>>     d = eval(code)
>> where
>>     code = compile("i+i", '<string>', 'eval')
> 
> This uses a GLOBAL variable named 'i'...
> 
>> should give an execution time of the same magnitude as :
>>     d = f(i)
>> where
>>     def f(i): return i+i
> 
> ...while this uses a LOCAL one.
> 
> 
>> it turns out to be almost 4x slower.
>>
>> Investigating with the dis module, I noticed that the result of compile
>> uses LOAD_NAME where a function uses LOAD_FAST. Is this due to local
>> namespace lookup ?
> 
> Right.  Local is faster than global, exactly because it can be loaded
> without a lookup (LOAD_NAME).

Sorry, but there is no global variable named 'i'. Does LOAD_NAME do a
standard look up in namespaces, while LOAD_FAST is used when the compiler
know that a local lookup will be sufficient ?

If this is so, this means that 'compile()' takes the worst, or better
said the more 'general', guess on how to compile it, by not assuming
that variables in expression may be in local scope.


> 
> Change your function to:
>     def f(): return i+i
> and the time difference should just about go away.
> 

No, because I don't know what expression I have to compute. I am trying
to benchmark what could be gained by using a lazy evaluation on matrices
ops, and the expression I need to compute is not known. Simpler, consider
it comes from a evaluation, or an user input string.


> 
>> It turns out that using something like (with some tweaks) :
>>     code = compile("def f(i):\n return i*i\n", '<string>', 'exec')
>>     eval(code)
>> gives the expected computation time.
>>
>> I think I must be missing something on evaluation, but what ?
> 
> I don't think you're necessarily missing anything.

I wish I was sure :

- does compile() work as I describe above ?

- if this is the case, could this an idiom :
  instead of writing :
      code = compile("some expr", '<string>', "eval")
      val = eval(code)

  one should consider writing :
      code = compile("def __f(v1,v2,...):\n return some_expr\n"
                     , '<string>', 'exec')
      eval(code)
      f = locals()["__f"]
      val = f(v1, v2, ...)

- the proposed idiom above looks dirty to me (locals trick), there
  may be a better way through the 'new' module, but I don't have found
  it yet. 
  
- where do the definition of 'f' goes in :

# ---------------------------------------------------------------------
m.py
# ---------------------------------------------------------------------
def a():
    code = compile("def f():\n pass\n", '<string>', "exec")
    eval(code)
    print locals().keys()
    print locals()["f"]
    print f

#import dis
#dis.dis(a)
a()

# ---------------------------------------------------------------------

# ---------------------------------------------------------------------
output
# ---------------------------------------------------------------------
['code', 'f']
<function f at 0x80fbc24>
Traceback (most recent call last):
  File "m.py", line 10, in ?
    a()
  File "m.py", line 6, in a
    print f
NameError: global name 'f' is not defined
# ---------------------------------------------------------------------

- why is eval("some_expr") so slow with Python 2.x (will profile it)


Regards,
-- 

Pedro



More information about the Python-list mailing list