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

Rendering a large number of elements exceeds maximum call stack size #29

Closed
thomashoneyman opened this issue Jul 21, 2017 · 3 comments
Closed

Comments

@thomashoneyman
Copy link

Hi Bodil,

Thank you for your effort in putting together this library — I’ve been using it happily in a few projects.

I have come across an error in which rendering a large number of elements to the page will exceed Javascript’s maximum call stack size. The code in question relies on traverse_ to render several thousand rows of a table.

About The Error

The error in question:

Uncaught RangeError: Maximum call stack size exceeded
    at Monad.Applicative0 (bundle.js:24516)

...

// bundle.js 24516
var monadMarkupM = new Control_Monad.Monad(function () {
      return applicativeMarkupM;
  }, function () {
      return bindMarkupM;
  });

@justinwoo helped me realize that by default monadic code isn’t tail recursive; if I need it to be, I need to use a traversal that implements MonadRec from purescript-tailrec. If the monad implements MonadRec, I can use purescript-safely or write my own tail-recursive function and all is well.

However, MarkupM doesn’t have an instance of MonadRec. In a discussion with @natefaubion, he had suggested there may not be a possible instance of MonadRec for this monad.

Finally, I am relying on purescript-pux, which itself relies on Smolder for its HTML. At the moment, I am not aware of a way to use another HTML library with Pux.

Reproduction

I’ve created a GitHub repo that implements a simple demonstration of this, and which should be easily cloned / run if you’d like to take a look at the error and the code that causes it directly.

https://github.com/saylu/purescript-framework-benchmark

Next Steps

With all of this said, the main questions I am looking to answer are:

  1. Is there a way to handle this case effectively in Smolder?
  2. If not, is there a possible workaround so that it is possible to render a large number of items, even if it is slow?

Wishing you the best,
Thomas

@natefaubion
Copy link

One possible fix would be to make the tail Lazy (MarkupM e a).

@bodil
Copy link
Owner

bodil commented Jul 21, 2017

Actually, something I've been meaning to do for a while is convert MarkupM to use purescript-free, which is stack safe by design, but which didn't exist yet when Markup became a free monad.

I've been playing with this today, and I've got a version which breaks backwards compatibility in all sorts of ways, and complicates renderers a bit, but which happily patches trees of 100k nodes using purescript-smolder-dom, and going beyond that I ran out of V8 heap space before blowing the stack, so I'm going to assume it's adequately stack safe.

@bodil bodil closed this as completed in 6c6c941 Jul 21, 2017
@thomashoneyman
Copy link
Author

Thanks for such a quick effort!

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

No branches or pull requests

3 participants