Thanks for code tips! I appreciate them. Ok, I kind of not sure I correctly remember why this topic was raised, so let me remember. You said that using a separate function has a performance hit. The purpose of my program was to establish that timing of function interrogate() == statement interrogate + compile time It doesn't appear to me that you dispute this claim, so let's accept it. Since a typical program shouldn't compile lots of code snippets (not in number of millions certainly) this means the performance of function and statement is the same for out purposes. I believe this closes performance question.
min(alist) is a more-direct, simpler, faster, easier to read way of calculating sorted(alist)[0].
You're muddying the water by including a for-loop and call to range() inside the code snippet being tested. We're trying to compare your function interrogate(test, 'value += 1') with the standard call to test.value += 1. Why include the time required to generate a range() object, and iterate over it ten times, as part of the code snippet? All that does is mix up the time required to execute common code and the time required to execute the code we care about.
If it's not obvious why your approach is flawed, consider this extreme example:
Timer("time.sleep(1000); interrogate(test, 'value += 1')", ...) Timer("time.sleep(1000); test.value += 1", ...)
The differences in speed between the interrogate call (using exec) and the direct access to test.value will be swamped by the time used by the common code.
A more accurate measurement is to remove the "for i in..." part from command, and increase the number=1000 argument to Timer.repeat() to 10000.
inc5 = compile_command(command)
This is an unfair test. We're comparing directly accessing test.value versus indirectly accessing test.value using exec. Regardless of whether the caller compiles the statement manually before passing it to exec, or just passes it to exec to compile it automatically, the cost of that compilation has to be payed. Pulling that outside of the timing code just hides the true cost.
Pre-compiling before passing to exec is a good optimization for the cases where you need to exec the same code snippet over and over again. If you want to execute "for i in range(1000): exec(s)" then it makes sense to pull out the compilation of s outside of the loop. But generally when timing code snippets, the only purpose of the loop is to minimize errors and give more accurate results, so pulling out the compilation just hides some of the real cost.
timing("interrogate(test, command)") timing(command.replace('value', 'test.value')) timing("interrogate(test, inc5)")
Result:
15
Where does the 15 come from?
'interrogate(test, command)' -> 0.0908 ms # test.value = 30015 '\nfor i in range(10):\n test.value += 1\n' -> 0.00408 ms # test.value = 60015 'interrogate(test, inc5)' -> 0.00469 ms # test.value = 90015
so interrogate() with additional precompiling introduces very little overhead.
Only because you're ignoring the overhead of pre-compiling. A more accurate test would be:
timing("inc5 = compile_command(command); interrogate(test, inc5)")
Though I agree it's inconvenient to write functions as strings;
If you think that's inconvenient, just try writing functions as code objects without calling compile :)
-- Steven D'Aprano _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas