Most of the programming language has feature to increase limit of recursion depth (python => sys.setrecursionlimit, ruby => RUBY_THREAD_VM_STACK_SIZE). How to do this with Crystal?
Specifically, I want this code to be compiled and run without error.
def foobar(depth)
return true if depth == 5000000
foobar(depth + 1)
end
p foobar(0) # => true
There is no explicit recursion depth limit. Your code simply exceeds the stack size (which is 8MB) and there’s no more room on the stack for the program to continue further.
Changing the stack size is technically possible, but I don’t think it’s a good idea because it affects all fibers and thus heavily increases the overall memory use. It’s probably better to refactor the code to avoid such deep recursion.
I believe (plz someone correct mt if I’m wrong) this is set by the OS, Crystal runtime just catch a signal and translate into an exception, so this post can help you:
TL;DR; ulimit -s shows the stack default size ulimit -s 16384 set the stack size to 16M.
The stack size for the main fiber is determined by OS settings, but the stack size for fibers other than the main fiber is fixed at 8MiB.
This is purely out of curiosity, but where did this number 8MiB come from?
According to DeepWiki, changing the stack size requires modifying Crystal’s source code and recompiling it. This is a rare limitation within Crystal, where many things are configurable.
I haven’t encountered a real-world need to increase or decrease the stack size. Still, I found it interesting.
I believe we chose 8MB because it’s the default stack size on Linux at least. Some BSD have much smaller stack sizes by default, though (e.g. OpenBSD).
It’s also virtual memory, and most of the stacks are only allocated when needed. That being said, there’s a limit on virtual memory, so having the ability to set a smaller stack size could be interesting (less virt => more fibers), and maybe fallback to use ulimit by default.
The recursion limit is configurable on Python and Ruby, because those apply to their virtual machines, not the underlying interpreter process itself. This would suggest that a similar method could exist for Crystal’s interpreter too.