The Cost of Dynamism (was Re: Pyhon 2.x or 3.x, which is faster?)

BartC bc at freeuk.com
Sun Mar 13 18:03:58 EDT 2016


On 13/03/2016 20:57, Chris Angelico wrote:
> On Mon, Mar 14, 2016 at 6:39 AM, BartC <bc at freeuk.com> wrote:
>> I used it in my benchmark to replace the if-else chain checking three lots
>> of ranges:
>>
>> switch(c)
>> if case(ord("A"),ord("B"),ord("C"),ord("D"),ord("E"),ord("F"),

>> It worked, but took 110 seconds; 80 seconds without the ord's and comparing
>> strings (but I still think it's perverse that integer ops are slower than
>> string ops).
>>
>> But 110 or 80 seconds, the original Python was 3.6 seconds. (Probably,
>> someone could tweak it to work with ranges, but this is extra programmer
>> effort that you say is too valuable to waste on such matters.)
>
> This is not comparing ranges, though. This is comparing against
> individual values.

That's true. (It's not my code for 'switch' and 'case', and I assume 
that the "==" operation it does on the arguments would not work when a 
range is passed, whatever form that might be in.)

Nevertheless, a true switch statement would be expected to work just as 
well with lots of individual case values, as with a smaller set of ranges.

  To talk about comparing ranges, I would expect the
> code to look something like this:
>
> switch(c)
> if case("A", "Z"):
>      upper += 1
> elif case("a", "z"):
>      lower += 1
> elif case("0", "9"):
>      digits += 1
> else:
>      other += 1
>
> THIS is comparing ranges.


> The underlying comparisons must be
> inequalities, not equalities. I absolutely *do not care* about
> performance until the code looks good - at least reasonably good.

Yes, that would be faster. I made a much-simplified case() work like 
your example, and the timing was 12 seconds.

(But that just worked with one single range, not an arbitrary mix of 
single values and ranges as a proper switch. Allowing any number of 
ranges per case, it took 25 seconds, and it's still not quite a full 
switch.)

> (By the way, your switch/case pair is non-reentrant. Plus it uses a
> class in a weird way. Why not, if you're working like this, just have
> two functions and a module-global? Just as non-reentrant, much cleaner
> code.)

I chose this because it looked odd, and was likely to perform poorly!

My point being that it's difficult to put together something that looks 
like, and is as easy to use as a switch in other languages, and is still 
efficient. (The 12 seconds still took over 3 times as long as as a 
simple if-elif chain, and the tests are still sequential so expect a 
slow-down with lots groups to test.)

-- 
Bartc



More information about the Python-list mailing list