If the code is exactly the same every time it runs, why didn't it use exact same amount of execution time?
For example, code as simple as:
console.time();
console.timeEnd();
would yield different result every time I run it.
To understand why it is so, first of all you should know JS works in conurrency model. There is event loop in Javascript which is responsible for executing the JS code. So this reference will definitely help to answer this question.
There are lots of things happening that use memory in your computer while you have your browser open and your script is running. Those things affect how much memory your browser has access to. The more memory your browser has available at that time, the faster your script will run.
Related
This question already has answers here:
setInterval() behaviour with 0 milliseconds in JavaScript
(5 answers)
Closed 10 years ago.
setInterval()
Calls a function or executes a code snippet repeatedly, with a fixed time delay between each call to that function.
while()
Creates a loop that executes a specified statement as long as the test condition evaluates to true. The condition is evaluated before
executing the statement.
If I use while(true) to execute a specific statement, my browser either crashes(Firefox), lags(Opera), or the statement won't be executed(Chrome), but if I used setInterval() with a fixed time of 0 seconds, everything works perfectly, even though its only 0 seconds, and while(true) can't logically be faster than 0 seconds, but why does this happen?
while() example:
<!DOCTYPE html>
<html>
<body>
<div id="counter"></div>
<script>
var i = 0;
while (true)
{
document.getElementById("counter").innerHTML += i++;
}
</script>
</body>
</html>
setInterval() example:
<!DOCTYPE html>
<html>
<body>
<div id="counter"></div>
<script>
var i = 0;
setInterval(function() { counter() }, 0);
function counter()
{
document.getElementById("counter").innerHTML += i++;
}
</script>
</body>
</html>
There is a large difference which involves locking. The first approach, the while loop is going to lock up the user's cpu because it runs forever without stopping and will take up 100% of the processor. setInterval actually has a minimum amount which is implicit, and depends on the browser. I believe it is around 10ms. So, your setInterval is actually only running for a millisecond or so doing that simple update, once every 10ms. This is harsh on the processor, but will not require 100% of the processor and can be mitigated with task management by the operating system.
while(1) generates an infinite loop, that is, JavaScript will simply run forever and never give control back to the browser, which therefor freezes, because it is unable to to anything else ever again (until the script is killed).
setTimeout(func, 0) behaves differently in the sense that after it executes, control is given back to the browser, which may then decide what to do after. Setting 0ms in setTimeout does not guarantee that the JavaScript code is run directly after it stops. With the 0ms parameter you merely tell the browser that you'd like the code to run directly after it stops, but the browser is free to do something else entirely before actually doing so.
Javascript in browsers is single threaded and event driven. No two things run concurrently, ever, and the event loop is king. If your JS never gives up control of the single thread (by ending a function), then nothing else can use the thread. The same thread handles JS and DOM, so the user can't even scroll or click on anything if your JS is hogging the thread.
setInterval (or indeed setTimeout) with a delay of 0 (milliseconds, not seconds) only means add this function to the event queue after the given delay, there is no guarantee the function will be executed at that exact time.
EDIT : actually, web workers can run JS at the same time as the main browser thread, but they don't see any of the same memory / can't access the DOM, so the points / assumptions above still hold, sort of... If you want to get into Web workers, you'll want a pretty good understanding of JS / functional programming.
EDIT (again) : Why do you want to loop forever? If you are polling (only reason I could think of), please don't do that. There's almost always a better way, especially in JS. The functional way, is to define the function you want executed when an event occurs (the thing you were polling for), and then attach that function to the event (how you do this depends on the event).
while(true) will block any execution until the conditional loop is finished, which we already know will never happen. (Chrome)
setInterval tells the environment to execute arbitrary code every x milliseconds, it wont block your browser because the "scheduler" has still the control.
Do you have a particular reason for using a never-ending loop, and even, manipulating the DOM with every each step?
If you use the while loop it'll most likely to lock the browser and client completely, also causing a possible CPU over-load if not terminated in a way.
The loop while tries to finish it's work in the most possible least microseconds. So it may even try to execute a million steps in a possible second, and maybe even more, in this case it depends on the client. However, at such speed updating the DOM wouldn't be possible.
In the case for setInterval, it's quite different from while loop, in fact, it's more appropriate to call it a function repeater. It repeats the given function after the given time is passed. So even if the time is 0, it has a step where it checks if the waiting time has passed now, and should the next repeat be run.
So you may consider while loop more instant than of 0 seconds delay.
I've created a script that runs every 1 second looking for a change in a value. Consider the code bellow:
setInterval(function() {
var inputOne = jQuery('#0_img_file');
var inputTwo = jQuery('.0_img-file').attr('src');
return function() {
if (inputOne.val() !== inputTwo) {
jQuery('.0_img-file').attr('src', inputOne.val());
}
}
}(), 1000);
So heres my question, could this script affect the site experience to the user or any kind of other stuff am not aware of?
I know there is functions in jquery like onChange, change etc but it only works if the user changes the value automatically, I've noticed it does not capture changes if other scripts change the value of an input.
First of all your code runs 10 times per second, not once. However, your browser is likely running on a computer with at least 2 multigigahertz cores with hyperthreading, megabytes of caching on board and you name it. So no, repeating a trivial task every 100ms (or 1s) is not going to noticeably slow down your browser, JS is usually rather fast.
Just don't run 100 jobs like this, you will start to feel it. And of course, you should just hook onto events of the scripts modifying the values, instead of polling for changes, which should be possible just fine with Javascript - due to its prototyped nature it's trivial to plug into existing code.
I've noticed it does not capture changes if other scripts change the value of an input.
That's because you probably use .attr('value', something) or .attr('checked', true') instead of .val(something) and .prop('checked', true).
So heres my question, could this script affect the site experience to the user or any kind of other stuff am not aware of?
Of course it can. Especially if the script make some heavy operations. Many browsers execute Javascript in only one thread. So when your script start, the browser will freeze during it's execution. If you have only one light script, it's ok. But if you abuse of this method, you will have some performances problems.
Well, I think the site will be little slower. The script calls a function every 1 second, so it will not have much problem on good computers. Besides, not everyone has good computers. Some users uses slow computers will have problem in perfomance, so usinh other way is needed.
Today I watched a colleague of my program a small game in Python on his Raspberry Pi. The game engine ran by using a while(true) or infinite loop. I myself use a websocket program in PHP that uses while(true). In these examples a infinite while loop is used which doesn't cause the program to become unresponsive. Without it, it wouldn't work properly. However in JavaScript we need to avoid a infinite loop at all costs. When a loop becomes infinite the browser hangs and becomes unresponsive.
My question: What is the difference between a infinite loop running in a compiled Python program and a infinite loop written in JavaScript running in a browser?
The difference is that the JavaScript runs on the browser's UI thread (preventing it from pumping normal OS messages like paint), whereas the Python program doesn't have a UI, and thus it doesn't matter if the main thread is hogged by your code.
You're still blocking the main thread either way, but in different contexts.
The main diffrence between the Python and the JavaScript code is that the Python code takes care of updating the UI, whereas the JS code just loops it's game logic and is therefore preventing the browser from updating it's view.
When you make a game, you usually put your in a loop where the first call goes to the game logic to update positions, player health, cat count and something like this. After that, you call a render method so that your updated content is processed as a picture and send to the screen. Then you start again. In JavaScript, you omitt the call to the render function and therefore the browser's UI never updates.
This has nothing to do with threading, but in a language like Pyhton (and many others) you can separate the game logic and the rendering so that when your logic is taking a while to do it's cat repositioning the programm is still able to update your screen (with the same, non-updated content over and over but that's another topic).
TL;DR The JavaScript blocks the rendering process of the Browser, whereas the Python loop explicitly calls the rendering function for it's UI.
For JS you should use setInterval(function, time), as #RĂșnarBerg noted.
EDIT: #mouser noted that you can also use web workers, which seem to be a html5 approach to multi-threading in JS. It may be worth a look if you are developing a game in JS, especially since it's supported in all major browser according to w3schools.
In Python, your loop probably looks like this:
while true:
TakeInput()
DoStuff()
So each iteration of the loop does something, and it keeps doing that forever.
In JavaScript, the input usually comes from the browser. If your JavaScript code is looping forever, the browser never gets a chance to let your code know new input has arrived.
You could write JavaScript code like this:
while (true) {
x = input('Give me input!');
// Process x
alert(result);
}
which would approximate the Python code, but that's not the way JavaScript usually works, and side-steps the browser all together.
Javascript has asynchronous runtime, meaning that your code doesn't usually have to wait for other parts to continue. You can run an infinite non-blocking loop with setInterval(fn, time) which executes the function fn at an interval of time milliseconds.
hi i m working a project which have huge javascript code sometimes javascript code executes automaticaly and hangs browser with message "kill this page" in chrome is there is any way to track the error .like calling calling a function when infinite loop arrives or browsser hangs like that .please give me some suggestion about debugging javascript code plz.
There is no way of doing what you wish inside javascript.
However you can use a tool like DynaTrace Ajax Edition to trace cpu usage in the browser to identify what is happening.
Infinite loop can be caused in many different bad programming logic, and there is no reliable logic to detect in every case. So I highly doubt if any programming language or IDE would offer any reliable infinite loop detection.
What you saw was basically a runtime detection based on how long script execution has taken before the browser could update and refresh the UI.
Sometimes this kind of long running JavaScript could be caused by infinite loop, but many times they are just big loops or loops that perform too much work that makes UI unresponsive.
Because JavaScript is not multi-thread, therefore to avoid the later case above, you could consider breaking the loops into small units of work, once a unit is finished, don't run the next unit, but instead call the next unit of work with setTimeout with a small time delay (such as 250ms). This would give the browser a chance to breath and update UI, and unmark your script as "long-running" script.
You may also use logging such as Firebug Logging to log the loops with enough values that help you find out if those loops are indeed infinite loops.
Hy guys!
I have a recursive function that takes time to perform. The IE is "thinking" that function is like a loop with no end.
What should I do to make IE don't show the error?
Thks guys!
You cannot, it is a functionality in most browsers to give the user a way out if he visits a webpage with javascript that ties up his cpu for too long and thus kills the browser.
The only way around it, is to performance optimize your code so it goes faster :)
I am assuming the "error" look like this, otherwise my answer is wrong:
Javascript in your browser runs in a single thread. If you have some kind of code running (recursive or otherwise) that does not yield to the browser every now and then, the browser will pause the script and ask the user whether they want to stop the code or continue. If this didn't happen there would be no way for the user to regain control (if you like your long-running code is running on the same thread as the UI, that is, the webpage). That's why ajax calls are structured in such a way that your code does not wait (that is, block) for the result, but instead a callback function is, well, called back with the results.
So how do you yield in a long-running piece of code? Several ways (ajax is one example) but the most popular is to use setTimeout in some way. Unfortunately it's just not that easy to explain how to use it without knowing what you are doing exactly. Any small examples I could give would be artificial.
So the strict answer to your question is "rewrite your code into execution chunks such t
hat there's no one chunk that takes a long time to execute".