How to change the maximum recursion depth?

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
User avatar
WhiteHare
Posts: 129
Joined: Thu Oct 04, 2018 4:00 am

How to change the maximum recursion depth?

Post by WhiteHare » Mon Oct 22, 2018 5:49 pm

I wrote a simple recursive function:

Code: Select all

def copyRadioBufferToString(i):
    if (radioBuffer[i]==0):
        return ""  # null string
    else:
        return chr(radioBuffer[i])+copyRadioBufferToString(i+1)

def receivedString():
    return copyRadioBufferToString(0)
to create and return a string from a radio's receive buffer, but it fairly quickly ran into micropython's maximum recursion runtime depth error, even though it works on shorter strings just fine and even though I'm running it on an nRF52840 with gobs of free RAM. Seems overly limiting. Is there a way to change the recursion depth limit so that it's not so over constrained? In this particular case, for example, the strings could be up to 255 characters in length, so a maximum recursion depth of, say, 300 or better would be desirable.
Last edited by WhiteHare on Mon Oct 22, 2018 5:52 pm, edited 1 time in total.

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: How to change the maximum recursion depth?

Post by jickster » Mon Oct 22, 2018 5:50 pm

What's the exact error?

User avatar
WhiteHare
Posts: 129
Joined: Thu Oct 04, 2018 4:00 am

Re: How to change the maximum recursion depth?

Post by WhiteHare » Mon Oct 22, 2018 5:55 pm

jickster wrote:
Mon Oct 22, 2018 5:50 pm
What's the exact error?

Code: Select all

Traceback (most recent call last):
  File "<stdin>", in <module>
  File "main.py", in start
  File "main.py", in receivedString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
  File "main.py", in copyRadioBufferToString
RuntimeError: maximum recursion depth exceeded

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: How to change the maximum recursion depth?

Post by jickster » Mon Oct 22, 2018 5:58 pm

Set a bigger number

Code: Select all

void mp_stack_set_limit(mp_uint_t limit) {
    MP_STATE_THREAD(stack_limit) = limit;
}
or disable the option

Code: Select all

// Whether to check C stack usage. C stack used for calling Python functions,
// etc. Not checking means segfault on overflow.
#define MICROPY_STACK_CHECK (1)
or limit recursion. Your code is easy to fix.

User avatar
WhiteHare
Posts: 129
Joined: Thu Oct 04, 2018 4:00 am

Re: How to change the maximum recursion depth?

Post by WhiteHare » Mon Oct 22, 2018 6:22 pm

Ahhhhhh... much better now. Disabling the stack check fixed the problem.

Thanks for your quick reply! :D :D :D

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: How to change the maximum recursion depth?

Post by pythoncoder » Tue Oct 23, 2018 6:41 am

In general it's best to avoid heavy recursion when programming microcontrollers because of their limited resources. The use of the string addition operator is also inefficient on RAM use compared to string.join(). So I'd rewrite it as an iterative function.

You might like to read the docs which provides useful guidance on how to write efficient MicroPython code.
Peter Hinch
Index to my micropython libraries.

HermannSW
Posts: 197
Joined: Wed Nov 01, 2017 7:46 am
Contact:

Re: How to change the maximum recursion depth?

Post by HermannSW » Tue Oct 23, 2018 7:36 am

pythoncoder wrote:
Tue Oct 23, 2018 6:41 am
You might like to read the docs which provides useful guidance on how to write efficient MicroPython code.
Thanks for that pointer, very informative.

I have defined a 768 element mixed bool/256bit integer list (ISALPHA).
Since it does not need to be changed, it could be a tuple as well.

From the docs I see that the 256bit integers could reside on flash, but that tupels always reside in RAM.
There are only 76 256bit integers in that list, which I could define as i0, ..., i75 and they would reside on flash.
Is there a way to reference those integers in the tuple without loading them into RAM?
Pico-W Access Point static file webserver:
https://github.com/Hermann-SW/pico-w

Tiny MicroPython robots (the PCB IS the robot platform)
viewtopic.php?f=5&t=11454

webrepl_client.py
https://github.com/Hermann-SW/webrepl#webrepl-shell

User avatar
WhiteHare
Posts: 129
Joined: Thu Oct 04, 2018 4:00 am

Re: How to change the maximum recursion depth?

Post by WhiteHare » Tue Oct 23, 2018 12:05 pm

pythoncoder wrote:
Tue Oct 23, 2018 6:41 am
In general it's best to avoid heavy recursion when programming microcontrollers because of their limited resources. The use of the string addition operator is also inefficient on RAM use compared to string.join(). So I'd rewrite it as an iterative function.

You might like to read the docs which provides useful guidance on how to write efficient MicroPython code.
That's a very helpful comment. :D I'll be sure to look into that when I get to the optimization phase.

Thank you!

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: How to change the maximum recursion depth?

Post by pythoncoder » Wed Oct 24, 2018 5:05 am

@HermannSW Storing data in Flash requires the Python file containing the data to be frozen as bytecode. This involves compiling the firmware.

If your 768 element data is in range 0>=d<=255 then the most efficient way is to store it in a frozen file is as a bytes object. Since this is immutable it does not get copied to RAM. You then address individual elements using array index notation. In other words don't use a tuple which inevitably consumes RAM.

Avoid slicing the bytes object as slices are copied to RAM.

Code: Select all

from my_frozen_module import data
a = data[760]  # good
b = data[3:7]  # Uses RAM
If slicing is important, read up on memoryview objects. An example of a frozen file using these may be found in the code sample here where a function returns a slice into a bytes object without allocation.
Peter Hinch
Index to my micropython libraries.

Post Reply