# Recursion limits

**URL:** <https://discuss.python.org/t/recursion-limits/33869>\
**Category:** Core Development\
**Created:** [September 16, 2023, 9:46am UTC](https://discuss.python.org/t/recursion-limits/33869 "2023-09-16T09:46:01Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![storchaka](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/storchaka/32/217_2.png) [@storchaka](https://discuss.python.org/u/storchaka)\
**Post date:** [September 16, 2023, 9:46am UTC](https://discuss.python.org/t/recursion-limits/33869/1 "2023-09-16T09:46:02Z")

</div>

In 2016 I wrote a script which measures how many recursive operations can Python do before crash ([Fastcall uses more C stack · Issue #73044 · python/cpython · GitHub](https://github.com/python/cpython/issues/73044), [Reduce stack consumption of PyObject\_CallFunctionObjArgs() and like · Issue #73056 · python/cpython · GitHub](https://github.com/python/cpython/issues/73056)). It was used to find and fix some regressions in 3.7. It is now available at [https://github.com/serhiy-storchaka/python-misc/blob/main/stack\_overflow.py](https://github.com/serhiy-storchaka/python-misc/blob/main/stack_overflow.py).

It is interesting to look how stack consumption was changed with Python versions. Here are results for the debug build on Linux for Python from 3.3 to future 3.13. Release builds have lesser stack consumption and allows deeper recursion. On Windows the stack size is smaller.

| | 3.3 | 3.4 | 3.5 | 3.6 | 3.7 | 3.8 | 3.9 | 3.10 | 3.11 | 3.12 | main |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| test\_ast\_parse | 87154 | 130804 | 130877 | 130877 | 130804 | 130877 | **104731** | 104658 | 130877 | **2994** (104684) | 2992 (104684) |
| test\_chain | 65397 | 174459 | 261762 | 261616 | 261762 | 261762 | 261762 | 261762 | 261762 | **174459** | 261762 |
| test\_compile | 32693 | 104658 | 130804 | 130804 | 130804 | **87227** | 87227 | **74771** | 74698 | **2995** (87203) | 2995 (87251) |
| test\_deepcopy | 1390 | 8176 | 8305 | **6541** | 6234 | 6229 | 6709 | 7072 | unlimited | unlimited | unlimited |
| test\_eq | 26142 | 52327 | 52327 | 52363 | **43650** | 43613 | 43613 | **40243** | 40243 | **1498 (34909)** | 1498 (34909) |
| test\_filter | 104658 | 130877 | 130804 | 104731 | 104658 | 104731 | **74771** | 74771 | 104731 | 104658 | 104731 |
| test\_hash | 65397 | 104731 | 104658 | 104731 | 104731 | 104731 | 130950 | **104658** | 104731 | 104731 | 104731 |
| test\_islice | 104585 | 174459 | 174459 | 174459 | 174459 | 174459 | 174605 | 174459 | 174605 | **74698** | 74771 |
| test\_json\_dump | 40170 | 58149 | 58148 | 58148 | 58148 | 58148 | 58149 | **40243** | 52363 | **1497** (52342) | 1497 (52340) |
| test\_json\_load | 43540 | 58112 | 58149 | 58149 | 58149 | 58149 | **52327** | 58149 | **47603** | **1497 (43646)** | 1497 (43622) |
| test\_map | 65397 | 130877 | 130877 | **74698** | 74771 | 74771 | **65470** | 65397 | 65433 | 65433 | 65433 |
| test\_marshal\_dump | 1999 | 1999 | 1999 | 1999 | 1999 | 1999 | 1999 | 1999 | 1999 | 1999 | 1999 |
| test\_marshal\_load | 1999 | 1999 | 1999 | 1999 | 1999 | 1999 | 1999 | 1999 | 1999 | 1999 | 1999 |
| test\_partial | 58112 | 87227 | 87227 | **65433** | 65433 | 65470 | 74771 | **65397** | 65470 | **1497 (58151)** | 1497 (58151) |
| test\_pickle\_dump | 32693 | 47603 | 47604 | 47567 | **43613** | 43613 | **40280** | **29089** | 37380 | **749 (32711)** | 749 (32711) |
| test\_python\_call | 2314 | 8871 | 8176 | **7368** | 7812 | 8180 | 8871 | 8724 | 9874 | **498 (8304)** | 498 **(8049)** |
| test\_python\_call\_keyword | 2314 | 8867 | 8176 | **7376** | 7812 | 8176 | 8875 | 8725 | 9875 | **498 (8310)** | 498 **(8055)** |
| test\_python\_function | 2616 | 13779 | 13779 | 13084 | 12463 | 12463 | 13430 | 14151 | unlimited | unlimited | unlimited |
| test\_python\_generator | 3079 | 24934 | **20136** | 22768 | 21799 | 21799 | 22768 | **16362** | 18684 | unlimited | unlimited |
| test\_python\_getitem | 2294 | 8176 | 7586 | **6978** | 8180 | 9182 | 11896 | 13084 | unlimited | **107070** (unlimited) | 107070 (unlimited) |
| test\_python\_iterator | 2161 | 7072 | **6460** | **5627** | 6983 | 8445 | 10908 | 10469 | 15870 | **749 (11897)** | 749 (11897) |
| test\_python\_method | 2615 | 13779 | 13770 | 13084 | **12463** | 12463 | 13421 | 14151 | unlimited | unlimited | unlimited |
| test\_repr | 52327 | 65397 | 65433 | 65397 | 65433 | 65469 | **58149** | 65397 | 65433 | **1496 (52342)** | 1496 (52342) |
| test\_yield\_from | 3096 | 24934 | **20136** | 22750 | 21799 | 21799 | 22750 | **14535** | 16362 | 74771 | **65397** |

As a rule, stack consumption remained the same. In some cases, it got better with each version. I highlighted in bold cases when it got worse.

---

<div class="post-metadata">

**Author:** ![storchaka](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/storchaka/32/217_2.png) [@storchaka](https://discuss.python.org/u/storchaka)\
**Post date:** [September 16, 2023, 10:28am UTC](https://discuss.python.org/t/recursion-limits/33869/2 "2023-09-16T10:28:42Z")

</div>

Many regressions in 3.12 are due to new hard limit (C\_RECURSION\_LIMIT). In parenthesis I added results for builds with removed hard limit.

---

<div class="post-metadata">

**Author:** ![malemburg](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/malemburg/32/50_2.png) [@malemburg](https://discuss.python.org/u/malemburg)\
**Post date:** [September 16, 2023, 10:37am UTC](https://discuss.python.org/t/recursion-limits/33869/3 "2023-09-16T10:37:59Z")

</div>

Thanks for compiling the table, those are interesting results. Some of those values appear to be very low for 3.12 and even in the range where normal applications (e.g. recursive parsers) could run into those limits. I wonder why C\_RECURSION\_LIMIT was set to such a low value (1500 in the current repo).

Aside: The table is cut off on the right in the normal browser view (it does show in the emails Discourse sends). You can see the full table by hovering over the post and then clicking the expand button on the upper right:

![image](https://us1.discourse-cdn.com/flex002/uploads/python1/original/2X/a/a7d9cec45127772ef94f52f72b4b199a55afb5fb.png)

---

<div class="post-metadata">

**Author:** ![storchaka](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/storchaka/32/217_2.png) [@storchaka](https://discuss.python.org/u/storchaka)\
**Post date:** [September 16, 2023, 10:51am UTC](https://discuss.python.org/t/recursion-limits/33869/4 "2023-09-16T10:51:35Z")

</div>

Here is a smaller table, for 3.10+

| | 3.10 | 3.11 | 3.12 | main |
| --- | --- | --- | --- | --- |
| test\_ast\_parse | 104658 | 130877 | **2994 (104684)** | 2992 (104684) |
| test\_chain | 261762 | 261762 | **174459** | 261762 |
| test\_compile | **74771** | 74698 | **2995** (87203) | 2995 (87251) |
| test\_deepcopy | 7072 | unlimited | unlimited | unlimited |
| test\_eq | **40243** | 40243 | **1498 (34909)** | 1498 (34909) |
| test\_filter | 74771 | 104731 | 104658 | 104731 |
| test\_hash | **104658** | 104731 | 104731 | 104731 |
| test\_islice | 174459 | 174605 | **74698** | 74771 |
| test\_json\_dump | **40243** | 52363 | **1497** (52342) | 1497 (52340) |
| test\_json\_load | 58149 | **47603** | **1497 (43646)** | 1497 (43622) |
| test\_map | 65397 | 65433 | 65433 | 65433 |
| test\_marshal\_dump | 1999 | 1999 | 1999 | 1999 |
| test\_marshal\_load | 1999 | 1999 | 1999 | 1999 |
| test\_partial | **65397** | 65470 | **1497 (58151)** | 1497 (58151) |
| test\_pickle\_dump | **29089** | 37380 | **749 (32711)** | 749 (32711) |
| test\_python\_call | 8724 | 9874 | **498 (8304)** | 498 **(8049)** |
| test\_python\_call\_keyword | 8725 | 9875 | **498 (8310)** | 498 **(8055)** |
| test\_python\_function | 14151 | unlimited | unlimited | unlimited |
| test\_python\_generator | **16362** | 18684 | unlimited | unlimited |
| test\_python\_getitem | 13084 | unlimited | **107070** (unlimited) | 107070 (unlimited) |
| test\_python\_iterator | 10469 | 15870 | **749 (11897)** | 749 (11897) |
| test\_python\_method | 14151 | unlimited | unlimited | unlimited |
| test\_repr | 65397 | 65433 | **1496 (52342)** | 1496 (52342) |
| test\_yield\_from | **14535** | 16362 | 74771 | **65397** |
