JavaScriptCore nested "call" performance issue
Asked Answered
T

1

53

If I define a function

inc = function(x) { return x + 1 }

and make a nested invocation of it

inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(1)))))))))))))))))))))

this will result in the value 22. If I revise the nested expression to instead make use of call, passing in null for this, as

inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, 1)))))))))))))))))))))

this will also produce the value 22.

But, on JavaScriptCore this second form appears to consume O(2^n) memory, where n is the number of nested calls. This is not the case if I try this JavaScript in Firefox or Chrome so it seems to be isolated to JavaScriptCore.

I have very little JavaScript experience (almost none). I don't have a feel for the tradeoffs that various JavaScript implementations might make, nor whether it is reasonable for the example code to be expensive in some implementations (providing generic support for closures or some such), while efficient in others.

My question is: Is this code inherently problematic? Should it be rewritten to be structured in a different way? Or is the code fine—does JavaScriptCore simply have a bug?

I've done some experimentation where refactoring a few of the inner calls to temporaries will "truncate" the memory doubling behavior

var temp1 = inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, 1)))))));

var temp2 = inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, temp1)))))));

inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, temp2)))))));
Transformism answered 19/12, 2014 at 14:40 Comment(5)
I'd sure call that a bug.Pecuniary
Thanks @Pointy. I've filed a rdar with Apple.Transformism
Moved rdar to WebKit: bugs.webkit.org/show_bug.cgi?id=139847Transformism
This question appears to be off-topic because it is in reality nothing more than a bug report, with two of the three questions this post asks being primarily opinion-based.Marcellus
The question is not subjective. It is about whether the behavior of a particular JavaScript VM is normal. Also, other programmers will want to know about the problem since iOS is a common dev target.Langtry
T
12

Based on comments on this question, the consensus is that there is no fundamental problem with the code as written, but that instead this is a bug in JavaScriptCore.

For the ticket filed, it has been confirmed as reproducible and has been imported into Apple's Radar system.

Transformism answered 21/12, 2014 at 18:36 Comment(3)
Just wondering when inc(x) normally desugar internally into inc.call(window, x) . Does null has to do something on this .Corliss
@Corliss I tried a test involving inc.call(window, inc.call(window, inc.call(window, ... and it exhibited the same problem.Transformism
Thanks Mike. I dont understand why this issue is closed some apple developers should probably reply with cause of this bug .Anyways its a great find @mike.Corliss

© 2022 - 2024 — McMap. All rights reserved.