-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tail recursion limit not working #3118
Comments
I did some debugging and profiling and found that the limit counter is counting just fine, but its just slowing to a crawl before reaching the limit, because it spends ever increasing time in prepareTailCallArguments every time it recurs. Problem is Lines 554 to 572 in 2a943a5
So the problem is clear, but I'm a little confused about the overall handling of contexts and variables here to know the proper fix. |
@jschobben It looks like this regression is a result from some of your tail recursion changes in #3020. Any ideas how to best resolve this? |
Hmm, this looks like a silly bug. Line 549-559 is supposed to only execute once (sort of a lazy init or cache). Maybe with the function literals that now happens each time for this example. The "cache" is tied to a node in the AST, which probably works differently in this new use case. A fix should probably be in restoring the "running once" of the if-block. Might be a bit tricky with the dynamic-ness of function literals. Right now I'm not around my pc for a while, building openscad on my phone works but takes up to 2 hours :D |
A temporary workaround might be to change |
Or maybe the call to I need my debugger :D |
Yes I'm thinking that resolveArguments should be changed so that it returns a map with containing all of Then on Line 549, instead of checking Since setting default arguments is currently dependent on whether the call site contains arguments, this means that it won't re-evaluate in the following case where default should get modified:
Results:
But its inconsistent because when no arguments are passed, it does re-evaluate the defaults, which is more like what I would expect:
Results in:
|
I started looking at changing Its not very clear how positional vs named arguments are supposed to behave in some situations, so I wrote this test script to help see: arg-permutations.scad.txt It basically defines the following function, and calls it with all combinations (I decided its too many to quote the whole script directly) of named and un-named parameters in all possible positions:
Here is the output, which I've filtered to show only lines which I consider problematic:
I'm not sure the best way to handle all these, but I think they would be covered if we followed the way Python seems to handle such situations:
|
Alternatively we could process all named args first, and fill in positional gaps with any other args, which I think would also allow for all those test cases to function in a somewhat reasonable manner without any warnings or errors. But that would be a little trickier to implement, and maybe that encourages sloppy, harder to decipher scripts. |
Wouldn't changing that probably break a whole bunch of existing code? |
@MichaelAtOz you mean the second suggestion I made of processing named args and filling the gaps? I think it would only change behavior of code that wasn't really working in the first place, which is to say some parameters were already being overridden/ignored (and without warning in some cases). If we would rather keep behavior as is and simply warn whenever parameter values are being overridden then we could do that without breaking anything at all. So ignoring the ones that already emit warnings leaves 9 cases from the above example which silently override named or positional arguments:
Adding a warning based on the second "Python rule" I wrote above would address cases 1,2,4,6,7,9 from that remaining set. Then there's 3 left:
These could be covered by the first Python rule above, but that feels heavy handed and would create warnings where there's not necessarily a problem But regardless of the decided solution I think this test case is important to add so we can know for sure whether or not changes to |
I've just opened a PR with the fix for original issue, plus added warnings as discussed above. @jschobben Since you've worked on this most recently, I'd appreciate a review of my changes if you have time. I changed the local stack handling because context keeps a There was one other thing that caused me some headache, where I thought I could evaluate and set the variables in-order with a single loop in Lines 555 to 562 in fb5fe91
Until I finally realized that its a problem because c_next is actually a parent of c_local. That seems backwards, but I couldn't figure out a way to rearrange contexts and make it all work. |
That is a decently-sized PR, hope you don't mind if it takes me a while 🙂 Guess it was still more complicated than fixing the Just to be clear, is most of it to enable the fix, or does the warnings part also cover a lot of code (beside test cases/expected output)? I'll try my best at a phone-based review. One other question: there aren't real KPI tests yet, but how does this impact performance? As that was the reason to introduce the flawed caching. |
About c_local/c_next: I suppose those could have benefitted from some more comments, indeed, and c_next should maybe be called c_entry or something. |
Well, 12 of the 18 files changed are test related. I fix a small spelling in the warnings "then" -> "than", and added quotes around named variables, so that affected a few more than the one test I added.. I did end up getting a little carried away and doing some whitespace refactoring in The biggest actual code change was re-writing
I tried your performance test suggestion, and added a loop to give it a bit more to chew on:
Results are averaged over 5 consecutive runs per build:
So its consistently a bit faster than before. Let me know if you have any other test ideas to try. |
Oh and I did a small unrelated refactoring in |
@jschobben Just to summarize, I was mainly hoping for some input or thoughts about the changes in The tests pass at least, which is a good sign, but I don't know if we are thoroughly testing all the possibilities that function literals introduce. |
@thehans unfortunately I barely had time the past week, sorry about that. At first sight the changes look good, and improving performance is of course excellent 🙂 To be honest I felt the whole In 2 days I'll be back home, then I can do a proper review. |
Minimal fix for #3118 Tail recursion limit not working
Finally found some time to look, after enjoying 2 flight cancellations 😅 |
Fixed by #3181 |
The text was updated successfully, but these errors were encountered: