Skip to content
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

Potential bug in tail-call optimizations with try/with block #54

Closed
Horusiath opened this issue May 1, 2017 · 4 comments · Fixed by #147
Closed

Potential bug in tail-call optimizations with try/with block #54

Horusiath opened this issue May 1, 2017 · 4 comments · Fixed by #147
Labels

Comments

@Horusiath
Copy link
Owner

Related issue found on SO: http://stackoverflow.com/questions/43714625/tail-call-seems-disabled-by-an-enclosing-try-block-in-fsharp-akka-but-not-usin

Content

Consider the following two skeletal snippets, A and B. In both cases, return! is the last executed operation and, IMHO, should be optimised like a tail call

Scenario A - here return! is properly optimised and the runtime stack is kept constant

let loop ... =
    actor {
        ...
        return! loop ...
    }

Scenario B - here return! is not interpreted as a tail call anymore and the runtime stack keeps growing, possibly leading to stack overflow exceptions

let loop ... =
    actor {
        try
            ...
            return! loop ...
        with ...
    }

The only difference is the try block which encloses the actor implementation. Note that the corresponding MailboxProcessor scenarios are both optimised as tail calls

@Horusiath Horusiath added the bug label May 1, 2017
@Horusiath
Copy link
Owner Author

Horusiath commented Jun 6, 2017

It looks like Async builder has pretty intensive trampoline logic hidden beneath async {...} computation expression. This one will take a while. Hopac does this differently via specialized class (we could make an effect from it), but need to evaluate this one.

@Horusiath
Copy link
Owner Author

From what I've managed to learn, async builder itself is also leaking when used with try blocks. I guess the solution here will be to stop rely on actor { ... } computation expression (it's already possible) and move to standard function-based API.

@codingedgar
Copy link

From what I've managed to learn, async builder itself is also leaking when used with try blocks. I guess the solution here will be to stop rely on actor { ... } computation expression (it's already possible) and move to standard function-based API.

what do you mean? it's not necessary to use actor anymore?

@Horusiath
Copy link
Owner Author

@codingedgar There's an example of using non-CE actor function definition in README of this repo. However this specific issue is related to leaking Async usage in tail calls and I'm not really sure, there's an easy way out of this (also: since the issue was posted, the internals of F# Async changed massivelly, so this issue should be reevaluated).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants