String Iteration Optimization

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
martinjaymckee
Posts: 1
Joined: Tue Feb 01, 2022 6:17 pm

String Iteration Optimization

Post by martinjaymckee » Tue Feb 01, 2022 6:45 pm

So, I'm working on my first MicroPython project and I'm running into a performance issue. I have implemented an HD44780 library, and I found that it was taking far more time than I had expected. What is taking the time, however, surprised me. It's the iteration through the string.

I'm testing this using a profiling object I wrote. I have tested it and know that it is returning reasonable data. So what the program is doing is running a loop over a string and checking the time of the loop itself, and the loop body.

Code: Select all

import utime

import perf

if __name__ == '__main__':
    text = 'The quick brown fox jumps over the lazy dog'
    
    perf_sampler = perf.HistogramSampler()
    loop_sampler = perf.HistogramSampler()
    perf_updated = False
    
    while True:
        loop_sampler.begin()
        for c in text:	# <- The overhead is being calculated per iteration here
                         #	It is the difference between the iteration time and the body time
            perf_sampler.begin()
            utime.sleep_us(10)
            perf_sampler.end()
        perf_updated = loop_sampler.end()

        if perf_updated:
            overhead_us = ((loop_sampler.data.mean * loop_sampler.data.samples) - (perf_sampler.data.mean * perf_sampler.data.samples) ) / perf_sampler.data.samples
            print('Character Time = {} us / character'.format(loop_sampler.data.mean / len(text)))
            print('Character Body Time = {} us / character'.format(perf_sampler.data.mean))
            print('Character Loop Overhead = {} us / character'.format(overhead_us))
            print()
The result, on the RP2040 (Pi Pico) is a calculated overhead of 670us per character (character time ~800us, body time ~130us). With a clock rate of 125MHz, that would be around 83,000 clock cycles per character, which seems off to me.

So, the question is, is there a way for me to optimize this? I would even be willing to write the module in C/C++ if needed, but I'm not actually sure how to check where the time is being spent in the iteration. Since the strings are being formatted at runtime, I'm going to have actual strings in Python... unless I just go to C++ for the whole project (which I'd rather not do, as I went to micropython because I'd like to allow scripting on the system).

Any ideas are always greatly appreciated.

Cheers.

Post Reply