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

Comments

Projects
None yet
3 participants
@thomashoneyman

thomashoneyman commented Jul 21, 2017

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

This comment has been minimized.

natefaubion commented Jul 21, 2017

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

@bodil

This comment has been minimized.

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 in 6c6c941 Jul 21, 2017

@thomashoneyman

This comment has been minimized.

thomashoneyman commented Jul 22, 2017

Thanks for such a quick effort!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment