What determines that a script is long-running?
One of the programming barriers that web developers are constantly bumping up against is the dreaded long-running script dialog (also called a runaway script dialog). These frightening dialogs are displayed whenever your JavaScript code takes too long to execute. The cardinal rule of web programming is that a user should never see this dialog, as it indicates a lack of proper JavaScript code architecture. Or to put it in simple terms: your code is trying to do too much.
Brendan Eich, creator of JavaScript, is quoted as saying, “[JavaScript] that executes in whole seconds is probably doing something wrong…” My personal threshold is actually much smaller: no script should take longer than 100ms to execute on any browser at any time. If it takes any longer than that, the processing must be split up into smaller chunks.
Still, few web developers truly understand what triggers the long-running script dialog in various browsers, including myself. So I decided to sit down and figure out under what circumstances you’ll see this dialog. There are basically two different ways of determining that a script is long-running. First is by tracking how many statements have been executed and second is by timing how long the script takes to execute. Not surprisingly, the approach each browser takes is slightly different.
Internet Explorer determines that a script is long-running by the total amount of statements the JScript engine has executed. By default, the value is 5 million statements and can be altered via a registry setting. When your script exceeds this maximum number of statements, you’ll get this dialog:
The message, “A script on this page is causing Internet Explorer to run slowly. If it continues to run, your compute may become unresponsive.” is a bit harsh if not technically accurate. The options here are to stop the script or allow it to continue running. Script execution is completely halted while the dialog is being displayed. If you choose to continue running the script, then the executed statement count is reset. You will see the dialog again if the number of statements once again reaches the maximum.
Firefox determines that a script is long-running by timing how long the script engine has been executing code continuously. The default time is set to 10 seconds and can be altered via about:config. Note that the amount of time modal dialogs, such as alerts, are displayed does not count against the script engine execution code. When this execution time has been reached, Firefox displays a dialog with the following message:
Firefox’s message, “A script on this page may be busy, or it may have stopped responding. You can stop the script now, open the script in the debugger, or let the script continue,” is a bit more descriptive and arguably less scary than IE’s. The options on this dialog are to stop the script, debug the script, or allow the script to continue. As with Internet Explorer, allowing the script to continue resets the timeout for script execution. The “Debug Script” button only appears if you have Firebug installed and active on the given page; debugging the script takes you into a view of the script that is causing the issue in Firebug.
Safari also uses script engine execution time to determine when a script has become long-running. After some digging around in the WebKit source code, it looks like the default timeout is 5 seconds. When that threshold is reached, the following dialog is displayed:
The message here is, “A script on the page [url] is making Safari unresponsive. Do you want to continue running the script, or stop it?” Once again, not terribly ideal for a user to see. You can turn off long-running script detection by selecting Disable Runaway JavaScript Timer under the Develop menu.
Chrome is a bit trickier to track down. The long-running script control seems tied to the crash control of any given tab. I’ve dug through the source code and haven’t been able to figure out the exact limit placed on scripts, but it does appear to be time-based and may be 10 seconds (it’s likely either 5 or 10, to match Safari or Firefox). I’m trying to get in touch with someone on the project to confirm. Nonetheless, a long-running script will result in the following dialog:
Clearly, the Chrome dialog is a bit more vicious than the other browsers. Clicking on “Wait” results in the page continuing its processing until the next script timeout is reached; clicking on “Kill pages” removes the entire page from memory and it is replaced by a placeholder.
Opera is an interesting case: it doesn’t appear to have a long-running script limit. I ran several tests that completed even after minutes of code execution. During the time, the browser remain mostly responsive, which is impressive. I’m not sure if this approach is a good thing or a bad thing at the moment, but it’s what is implemented.
Regardless of the browser being used, your users should never encounter this dialog. It’s very important to do regular performance testing of the JavaScript in your site or web application before deploying to production. There are numerous tools you can use, such as Firebug’s profiler (Firefox), the YUI Profiler (all browsers), and Internet Explorer 8’s Profiler. You should be looking for any single script execution that takes 100ms or longer on any given browser; those methods involved with such a long execution should be evaluated for performance issues. Make sure you don’t use Chrome as your baseline since its JavaScript execution is orders of magnitude faster than others (same goes for Firefox 3.1 and the latest WebKit nightlies). It’s best to use Internet Explorer as a baseline and then look at other browsers; since IE is often the slowest JavaScript engine, fixing problems for it will certainly fix issues in other browsers as well.
Update (1/9): Added more description around the messages each dialog displays.
Translations
- Chinese (Simplified):
http://cuimingda.com/2009/01/what-determines-script-long-running.html - Spanish:
http://ernestdelgado.com/zakas/long-running-script.html
Disclaimer: Any viewpoints and opinions expressed in this article are those of Nicholas C. Zakas and do not, in any way, reflect those of Yahoo!, Wrox Publishing, O'Reilly Publishing, or anyone else. I speak only for myself, not for them.
You can leave a response, or trackback from your own site.


![Safari Long-Running Script Dialog Safari Dialog: A script on the page [url] is making Safari unresponsive. Do you want to continue running the script, or stop it?](http://www.nczonline.net/blog/wp-content/uploads/2009/01/safari_dialog-300x130.png)

25 Comments
[...] Zakas decided to dive deep on everyone’s favorite sign that you’ve done something wrong: Few web developers truly understand what triggers the long-running script dialog in various [...]
Ajaxian » What Causes the Long-Running Script Warning? on January 6th, 2009 at 11:33 am
[...] What determines that a script is long-running? | NCZOnline. [...]
What determines that a script is long-running? | NCZOnline | M.D.Risser on January 6th, 2009 at 6:26 pm
Hi Nick, great read, thanks.
I had a case a while back where I was debugging a recursive function. The bug was causing it to recurse infinitely and Firefox just kept hanging until I had to kill the whole app. I was surprised not to see the dialog appear and it’s contrary to the notion that it appears after X seconds.
Infinite recursion is a relatively rare occurrence, and certainly represents a programming bug, so fortunately is only of limited relevance. It does make me wonder if there are other situations where the dialog doesn’t appear.
Michael Mahemoff on January 6th, 2009 at 11:22 pm
Hi Mike,
It actually seems that recursive functions are a special case. I was digging through some source code and seemed to find some evidence indicating this, but I wasn’t able to figure out exactly what’s going on. But now I’m curious and will probably do some more research digging into this.
Nicholas C. Zakas on January 6th, 2009 at 11:39 pm
[...] What determines that a script is long-running? - Nicholas C. Zakas explores the actual way that browsers detect slow running Javascript for the ‘This script is running slowly’ messages that most browsers now feature. [...]
Reflective Perspective - Chris Alcock » The Morning Brew #259 on January 7th, 2009 at 4:38 am
[...] Seguramente muchas, pero ¿alguna vez te habías planteado que criterios iba a usar el navegador para lanzar dicho mensaje? Pues al parecer hay gente que si lo ha hecho y ha sacado las siguientes conclusiones: [...]
¿Cuando nuestro javascript está demasiado tiempo ejecutándose? : Blogografia on January 7th, 2009 at 7:01 am
Note that the IE limit of 5M instructions was first put in place back in 1997 as part of IE3 and, I believe, has not been changed in that time.
As hardware and script engine performance has improved the time it takes to bump into this warning has grown smaller and smaller. While developing my JSLitmus script performance testing tool ( http://www.broofa.com/Tools/JSLitmus/ ) I found myself getting the script alert w/in 500ms.
Hopefully IE8 has changed the way this alert gets triggered.
Robert K on January 7th, 2009 at 9:01 am
Hi Robert,
It was actually implemented in IE 4 and has remained unchanged since that time. Prior to that, IE 3.x used a timer mechanism with a timeout of 5 seconds. Thanks for sharing your tool!
Nicholas C. Zakas on January 7th, 2009 at 3:56 pm
[...] What determines that a script is long running? [...]
Ennuyer.net » Blog Archive » 2009-01-10 - Today’s Ruby/Rails Reading on January 9th, 2009 at 6:37 am
[...] my last post, I talked about the conditions under which the dreaded long-running script dialog is displayed in [...]
Speed up your JavaScript, Part 1 | NCZOnline on January 13th, 2009 at 9:02 am
[...] C. Zakas has taken his long running script post and is now flushing out ways to stop this from [...]
Ajaxian » Looping through your items without waiting around on January 14th, 2009 at 6:55 am
I actually prefer the IE way (count of statements) to the other browsers (count of runtime). If my machine is very busy or is starved of memory then I’ll sometimes get the long-running-script dialog in Firefox for, say, gmail (or sometimes even Firebug!) because it’s taking a long time to run even though it’s not doing much. A statement count avoids this problem.
Stuart Langridge on January 14th, 2009 at 7:22 am
What determines that a script is long-running?…
Thank you for submitting this cool story - Trackback from DotNetShoutout…
DotNetShoutout on January 24th, 2009 at 12:43 am
[...] Seguramente muchas, pero ¿alguna vez te habías planteado que criterios iba a usar el navegador para lanzar dicho mensaje? Pues al parecer hay gente que si lo ha hecho y ha sacado las siguientes conclusiones: [...]
¿Cuando nuestro javascript está demasiado tiempo ejecutándose? | aNieto2K on January 26th, 2009 at 2:49 pm
[...] The bottom line: always be on the look out for recursion in your JavaScript. Memoization and iteration are two ways to avoid excessive recursion and the long-running script dialog. [...]
Speed up your JavaScript, Part 3 | NCZOnline on January 31st, 2009 at 5:43 pm
[...] user cannot interact with the browser while a reflow is occurring. (Reflows will happen when the long-running script dialog is displayed because it represents a break in JavaScript execution, allowing the UI to [...]
Speed up your JavaScript, Part 4 | NCZOnline on February 4th, 2009 at 10:34 pm
The slow script error does not seem to be limited to a single script. Run a script once with a button click and there is no error. Run it again by clicking the button a second time and you get the error. So the counter seems to be cumulative in some cases, not limited to a single script. The script in question is a simple for-loop intended to trigger the slow script error, so the instructions per click should be identical.
Mike on March 14th, 2009 at 2:01 pm
[...] 解决问题的关键,就是限制通过DOM操作所引发回流的次数。大部分浏览器都不会在JavaScript的执行过程中更新DOM。相应的,这些浏览器将对对DOM的操作放进一个队列,并在JavaScript脚本执行完毕以后按顺序一次执行完毕。也就是说,在JavaScript执行的过程中,用户不能和浏览器进行互动,直到一个回流操作被执行。(失控脚本对话框会触发回流操作,因为他执行了一个中止JavaScript执行的操作,此时会对用户界面进行更新) [...]
如何提升JavaScript的运行速度(DOM篇) « 七月佑安 on March 15th, 2009 at 7:01 am
[...] 【原文标题】What determines that a script is long-running?【原文作者】Nicholas C. [...]
浏览器根据什么来判定脚本失控? « 七月佑安 on March 15th, 2009 at 7:11 am
[...] about JavaScript browser limits and how they present themselves. I started out by discussing the long-running script dialog and then moved on to other performance issues. I thought I had covered most of the annoying and [...]
JavaScript stack overflow error | NCZOnline on May 19th, 2009 at 9:02 am
[...] 根据Nicholas的说法,有四种代码会拖慢脚本的运行,并最终导致脚本失控。分别是次数过多的同步循环、庞大的函数体、不恰当的递归和不合理的DOM调用。这篇着重讲第一个原因。最后给出了一个开发模式,替换传统的循环结构,可以完全避免脚本失控的状况发生。 【原文标题】Speed up your JavaScript, Part 1 【原文作者】Nicholas C. Zakas 在我上一篇帖子(译文)中,谈到了各个浏览器究竟会在什么情况下弹出脚本失控提示,对于Internet Explorer来说,当浏览器执行了数量过多的语句时就会停止执行脚本,而其他的浏览器,则是持续执行脚本超过一定时间的时候就会给出提示。而我们要探讨的核心问题,不是这些浏览器如果探测失控的脚本,而是我们如何才可以让脚本运行的更快一些,从而避免这些警告。 脚本失控基本上有以下四个方面的原因: 1. 在循环中执行了太多的操作。 2. 臃肿的函数体 3. 过多的递归 4. 过多的DOM调用 [...]
如何提升JavaScript的运行速度(循环篇) « iUE on June 3rd, 2009 at 11:26 am
[...] 解决问题的关键,就是限制通过DOM操作所引发回流的次数。大部分浏览器都不会在JavaScript的执行过程中更新DOM。相应的,这些浏览器将对对DOM的操作放进一个队列,并在JavaScript脚本执行完毕以后按顺序一次执行完毕。也就是说,在JavaScript执行的过程中,用户不能和浏览器进行互动,直到一个回流操作被执行。(失控脚本对话框会触发回流操作,因为他执行了一个中止JavaScript执行的操作,此时会对用户界面进行更新) [...]
如何提升JavaScript的运行速度(DOM篇) « Oragg.com on June 14th, 2009 at 11:19 am
[...] 在我上一篇帖子(译文)中,谈到了各个浏览器究竟会在什么情况下弹出脚本失控提示,对于Internet Explorer来说,当浏览器执行了数量过多的语句时就会停止执行脚本,而其他的浏览器,则是持续执行脚本超过一定时间的时候就会给出提示。而我们要探讨的核心问题,不是这些浏览器如果探测失控的脚本,而是我们如何才可以让脚本运行的更快一些,从而避免这些警告。 [...]
如何提升JavaScript的运行速度(循环篇) « 七月佑安 on June 14th, 2009 at 2:15 pm
[...] 总结一下基本原则,不管是什么时候使用递归的时候都应该小心谨慎。memoization和迭代是代替递归的两种解决方案,最直接的结果当然就是避免那个提示脚本失控的对话框。 [...]
如何提升JavaScript的运行速度(递归篇) « 七月佑安 on June 14th, 2009 at 2:31 pm
[...] 本文译自Nicholas C. Zakas于2009年1月5日在个人网站上发表的《What determines that a script is long-running?》。原文是唯一的正式版,本文是经过原文作者授权的简体中文翻译版。译者在翻译的准确性上做了大量的努力,并承诺译文的内容完全忠于原文,但可能还是包含疏漏和不妥之处,欢迎大家指正。译序和译注的内容是非正式的,仅代表译者个人观点。 [...]
浏览器根据什么来判定脚本失控? « 七月佑安 on June 14th, 2009 at 2:45 pm
Leave a Comment