Sunday, May 13, 2012

Javascript Recursion Improvement


Someone at work jokingly sent out an email with a html file intended to crash your browser that was the following




<html>
<script type="text/javascript">
function crash(){
for(i=0;i<5000000001;i++){
document.write(i);
}
}
</script>
<body onload="crash();">
</body>
</html>



Anyways it doesn't do a great job of it in Chrome and a conversation arose that it created a friendly competition to see who could write javascript to make a page count to 5,000,000,000 as quickly as possible without causing the browser to become unresponsive or crash.



I came up with the following piece of javascript that is intended to be used in Chrome.




<html>
<script type="text/javascript">
function countToFiveBillion(counter, num){
if(num < 5000000000)
{
num++;
if(num % 18700 == 0){
counter.innerHTML = num;
setTimeout(function() {countToFiveBillion(counter, num)}, 1);
} else {
countToFiveBillion(counter, num);
}
}
}
function initiateCountDown()
{
var counter = document.getElementById("counter");
var num = +counter.innerHTML;
countToFiveBillion(counter, num);
}
</script>
<body onload="initiateCountDown();">
<div id="counter">0</div>
</body>

</html>



The reason that this will only run in chrome is that I'm using the setTimeout call to avoid creating a stackoverflow in chrome. (Chrome also allows you the largest stack for recursive calls out of all of the browsers).



Is there any way for me to make this count any quicker? I think that I can increase the amount counted a little before it causes an overflow (somewhere less than 100 though) The only stipulation is that is has to display as many numbers as possible as it counts.





Improved Code:




<html>
<script type="text/javascript">
var counter;
var num = 0;
function countToFiveBillion(){
if(num < 5000000000)
{
num++;
if(num % 18701 == 0){
setTimeout("countToFiveBillion()", 1);
counter.value = num;
} else {
countToFiveBillion();
}
} else {
counter.value = "number greater than 5 Billion";
}
}
function initiateCountDown()
{
counter = document.getElementById('counter');
countToFiveBillion();
}
</script>
<body onload="initiateCountDown();">
<input type="text" id="counter" value="0" />
</body>

</html>



  • Made count and element globabl

  • Switched to text input instead of div

  • moved update UI to after setting the callback


Source: Tips4all

1 comment:

  1. Webworker example, index.html

    <!DOCTYPE HTML>
    <html>
    <head>
    <title>5 billion</title>
    </head>
    <body>
    <input type="text" id="counter" value="0" />
    <script type="text/javascript" charset="utf-8">
    var
    iCounter = document.getElementById('counter')
    , counter = new Worker('worker.js');

    iCounter.value = 0;
    counter.addEventListener('message', function (e) {
    iCounter.value = e.data;
    }, false);
    </script>
    </body>
    </html>


    worker.js:

    for (var i = 0; i < 5e9; i++) {
    if (i % 18701 === 0) {
    postMessage(i);
    }
    }


    The counting can be splited in multiple workers if needed.

    ReplyDelete