It's a good question. The kind you have to ask when you are looking to optimize things. And testing is key, always.Ok, but the counting down compares using equality, the other one using less than.
I ran the test with both options by commenting out one or the other.
Code: Select all
@micropython.native
def counting_up():
i = 0
limit = 5000
busy = False
# while i < limit:
while i != limit:
i += 1
busy = True
busy = False
return [busy, i]
Code: Select all
Total run time for 100 iterations:
counting_up: 926.0 ms for 100 iterations, output:[False, 5000]
counting_down: 518.0 ms for 100 iterations, output:[False, 0]
using_range_from_zero: 1206.0 ms for 100 iterations, output:[False, 5000]
using_range_from_value: 1214.0 ms for 100 iterations, output:[False, 0]
Code: Select all
Total run time for 100 iterations:
counting_up: 794.0 ms for 100 iterations, output:[False, 5000]
counting_down: 518.0 ms for 100 iterations, output:[False, 0]
using_range_from_zero: 1206.0 ms for 100 iterations, output:[False, 5000]
using_range_from_value: 1214.0 ms for 100 iterations, output:[False, 0]
I think this is where designing the test can be super important. And, yes, it takes a lot more thought than either one of us can devote to this at the moment. Even the tests I concocted are likely flawed on more ways than one.That's not the same as comparing wheher a == 0 is faster than a == 23 which is what we were discussing originally. I don't have time to write a complete portable script like yours, sorry, but for fun this compares 4 cases:
I think the reason you are seeing the results you got is because the loops are not doing much. The variables are being allocated on the stack and very likely stay in registers for the entire run. If the variables stay in registers, execution will be very fast --almost regardless of the kind of comparison you might use.
You could, for example, try with a 32 bit number rather than an 8 bit number that is super-fast to load. Something like 0x12345678. That's one area where a countdown can take a serious hit. When I write code in assembler and have no choice but to compare to a number, I do my best to try to load that number into a register and never alter that register until I am done with the number. In that case, depending on the processor, there is no performance hit between counting up and down. Also, return the values and print them at the end (not for every loop). This is to force a situation where they are deemed important (as they might be in a real application) and not optimized away or otherwise discarded.
In other words, the question you are trying to answer is "How do these approaches differ in the context of of my real application?" as opposed to a laboratory experiment. It's like simulations; the only people who believe simulation results are the folks who wrote the simulation code.
Code: Select all
Idea is to test bare oprations and not much more
Absolutely agree on that one. Even if you are doing commercial work, do not ever optimize unless absolutely necessary. Or, at the very least, at the end of the process. Optimizing early is a complete waste of time. So, yeah, use range() and be super-Pythonic while prototyping. Worry about optimization later.I find it perfectly understandable that if one does not have one million devices, and might even have a one-shot script, one chooses range() because it simple, clear, just works, known by everybody, requires no tests, and so on.
The project I am working on will be re-written entirely in C. MicroPython was thought to be a faster way to get to a result for some testing. The theory was that you could write the entire application much faster, validate algorithms and ideas and then optimize by re-writing it in C. Once you know what you need to do, re-coding something in C isn't difficult at all. This, I think, is particularly true in embedded systems, where knowing what data you have to manage in memory and how can help you design a memory map for best efficiency.
Sadly, I have to comment, this was a mistake. The performance issues with MicroPython led to having to dive into early optimization and even writing a bunch of assembler code. When that happened, the development speed advantage of Python was absolutely gone. Had I known what I know now (this is my first time using MicroPython) I would have gone straight for C from the start. I would have been much farther along today had I taken that path. That said, MicroPython is a wonderful tool and it has many uses, even serious production applications --it just didn't fit what I happen to be doing.