开发者

Javascript tail recursion

开发者 https://www.devze.com 2022-12-31 01:35 出处:网络
Why the following code runs so.... slow....... ? <html><body><script type=\"text/javascript\">

Why the following code runs so.... slow....... ?

<html><body><script type="text/javascript">
    var i = 0;

    f();

    function f() {
        if (i == 5000开发者_Python百科) {
            document.write("Done");
        } else {
            i++;
            tail();
        }
    }

    function tail() {
        var fn = tail.caller;
        var args = arguments;
        setTimeout(function() {fn.apply(this, args)}, 0);
    };

</script></body></html>


A couple of reasons:

  1. Using the caller property on a function object introduces overhead (and is non-standard)

  2. The same for using the arguments pseudo-array (IIRC, this will slow down a function call by a factor of 2-5, depending on which browser you're using)

  3. setTimeout will typically take no less than 10ms to call your function back (although Chrome sometimes goes a bit faster than that), even when you specify 0 as the timeout. This will probably be the biggest reason: 5,000 iterations at ~10ms is 50 seconds.

That last item is the reason I said:

If you have a lot of loop iterations (e.g., a couple of hundred instead of 15), it may well be worth doing a chunk of them on each iteration rather than yielding on each iteration; the yield takes a measureable time (typically ~10-15ms).

...in my answer to your other recent question.

Note that your code can be rewritten without using caller or arguments, making it much clearer:

var i = 0;

f();

function f() {
    if (i == 5000) {
        document.write("Done");
    } else {
        i++;
        setTimeout(f, 0);
    }
}

Separately: I notice you used document.write in your code sample. If you're doing this with code executed during the page parse (which is the only place you can use document.write), rather than in code you trigger with an event handler after the page is parsed, you can't use setTimeout. This is because code that ouputs via document.write has to run synchronously with the HTML parser on page load. Script blocks are executed during the parse for exactly this reason: In case they emit HTML the parser has to deal with. If you want to modify the page after parsing (which I'd recommend), you want to use DOM methods to get an element reference, and then either use DOM methods to add to it or (and this is both easier and faster running) set the innerHTML property on the element.

My sense from both questions is that you probably do want to be looking into web workers, and only using the above for fallback for browsers that don't support them yet (IE, I'm afraid, but I bet IE9 will have them — and all the other major ones have them now).

0

精彩评论

暂无评论...
验证码 换一张
取 消