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

long chains without overflowing the stack fails on FF 10-23 #1622

Merged
merged 2 commits into from
Sep 24, 2015

Conversation

mbest
Copy link
Member

@mbest mbest commented Sep 5, 2015

The test Dependent Observable Should allow long chains without overflowing the stack fails on FF 10-23 with InternalError: too much recusion.

Noting: #358 & #359.

@brianmhunt
Copy link
Member Author

@mbest Any thoughts on the best way to handle this? A few come to mind, and I had thought about putting a PR together but I noticed you had already done some work on this already and I'm sure would know better than I do where to start.

The basic options seem to be:

  1. Lower the depth in the test;
  2. Make an explicit exception in the test for FF 10-23;
  3. Employ a technique like allow long subscriber chains #359 (at src/subscribables/subscribable.js notifySubscribers)

I noted that the depth in the current test is 200, but is 10,000 in the patch.

My personal inclination is towards a patch like #359, but I'd be gambling that there are no side-effects.

@mbest
Copy link
Member

mbest commented Sep 4, 2015

While investigating this, I decided to run the test against previous versions to figure out when this started failing. It was working with Knockout 3.2.0, but not with 3.3.0. I'll look into it some more.

@mbest mbest added this to the 3.4.0 milestone Sep 5, 2015
…, especially for Firefox support (version 10-23).
@mbest mbest force-pushed the 1622-reduce-computed-notification-stack-overhead branch from 63df63f to f3be8d5 Compare September 5, 2015 01:12
@mbest
Copy link
Member

mbest commented Sep 5, 2015

Okay. So this is one way to fix this issue. This more-or-less mirrors what I did originally (688a567, #1088): reducing the function call depth for each iteration and eliminating the use of call and bind.

// without the need to use "bind". Older versions of Firefox seem to use up a lot more stack space
// when using a bound function or using "call". See #1622.
var evaluationTimeoutInstance = null;
computedObservable.evaluatePossiblyAsync = function () {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This undoes the performance benefits of #1841; in most cases a closure will be more memory and slower than a function on the prototype chain, notably with newer browsers.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're okay with the test failing in older FF, then we can simply ignore these changes and possibly skip the test for those browsers. After all, the test already failed with version 3.3.0.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with that, and as you say, going forward the use of deferred updates makes this issue go away. @SteveSanderson ?

I think then the answer might be to just reduce the number of iterations to 100. Legacy FF should pass with that (I think it succeeds with 130 or so, but not positive– if we go this route, I'll fix it up).

…PossiblyAsync; reduce recursion test depth to match success result in FF.
@mbest
Copy link
Member

mbest commented Sep 24, 2015

I've made a further commit to undo some of my previous changes. This keeps the logic of moving the "change" notification to evaluatePossiblyAsync, reducing a couple layers of function calls from the recursion. This still requires reducing the depth value in the test to make it pass but allows for a greater depth than doing nothing.

@brianmhunt
Copy link
Member Author

Thanks @mbest – The updated PR looks good to me –– bearing in mind the caveat that I haven't stared at this enough to really understand any potential side-effects or pitfalls.

mbest added a commit that referenced this pull request Sep 24, 2015
…ion-stack-overhead

long chains without overflowing the stack fails on FF 10-23
@mbest mbest merged commit 8decc43 into master Sep 24, 2015
@mbest
Copy link
Member

mbest commented Sep 24, 2015

Thanks. I'm happy with it too. I've merged it now.

@mbest mbest deleted the 1622-reduce-computed-notification-stack-overhead branch September 24, 2015 19:37
@brianmhunt
Copy link
Member Author

I merged the above into the 1360-gulp branch, but as you can see there is still an odd continuing failure:

Firefox 38.0.0 (Linux 0.0.0) Dependent Observable Should allow long chains without overflowing the stack FAILED
InternalError: too much recursion in /home/travis/build/knockout/knockout/src/subscribables/subscribable.js (line 72)
ko_subscribable_fn.notifySubscribers@/home/travis/build/knockout/knockout/src/subscribables/subscribable.js:72:25
computedFn.evaluatePossiblyAsync@/home/travis/build/knockout/knockout/src/subscribables/dependentObservable.js:211:17
ko_subscribable_fn.notifySubscribers@/home/travis/build/knockout/knockout/src/subscribables/subscribable.js:72:25
...
ko_subscribable_fn.notifySubscribers@/home/travis/build/knockout/knockout/src/subscribables/subscribable.js:72:25
observableFn.valueHasMutated@/home/travis/build/knockout/knockout/src/subscribables/observable.js:46:36
observable@/home/travis/build/knockout/knockout/src/subscribables/observable.js:12:17
@/home/travis/build/knockout/knockout/spec/dependentObservableBehaviors.js:516:9

Firefox 17 and 24 pass; all three failed prior builds without this patch. Not sure why FF 38 would have this regression.

@mbest
Copy link
Member

mbest commented Sep 25, 2015

I'll check that out. I had tested it with Firefox 16.

@brianmhunt
Copy link
Member Author

Here's a jsFiddle to show stack depth

FF 42 has a call stack of 200–262,000; Chrome is 8–20,000. FF 38.3.0esr has a call stack of 200–284,000 (On Mac OS X). May be a problem only on Linux? That'd be strange.

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

Successfully merging this pull request may close these issues.

None yet

3 participants