Violation Long running JavaScript task took xx ms
Asked Answered
G

15

520

Recently, I got this kind of warning, and this is my first time getting it:

[Violation] Long running JavaScript task took 234ms
[Violation] Forced reflow while executing JavaScript took 45ms

I'm working on a group project and I have no idea where this is coming from. This never happened before. Suddenly, it appeared when someone else got involved in the project. How do I find what file/function causes this warning? I've been looking for the answer, but mostly about the solution on how to solve it. I can't solve it if I can't even find the source of the problem.

In this case, the warning appears only on Chrome. I tried to use Edge, but I didn't get any similar warnings, and I haven't tested it on Firefox yet.

I even get the error from jquery.min.js:

[Violation] Handler took 231ms of runtime (50ms allowed)            jquery.min.js:2
Gnat answered 19/12, 2016 at 8:29 Comment(8)
Where do you see this warning? You don't say what environment you're working in. Assuming some browser, but which one etc?Cartomancy
@SamiKuhmonen sorry for that, i've updated my question. i used Chrome. i didn't find any similar error on Edge.Gnat
I just wanted to add that this warning message, introduced late 2016, may also appear due to any extensions you may have installed in Chrome. It's easy to check for that by testing in private mode.Oller
Clicking on the right side link, indicating you the script where the violations happens, will bring you to the place in the code where it happens.Redwing
I am using Ionic 4 (Angular 8), my code was working fine, suddenly this kind of violation started coming - there is no data showing in my list now?Lentamente
Out of curiosity I just visited the google.com portal with Chrome and developer console open. And guess what? Got this message: "[Violation] Forced reflow while executing JavaScript took 52ms"!Mambo
By any chance you're using imwheel? If yes, can you try disabling that and see if you still get those violations?Bundesrat
For what it is worth, came here as i got the same notice in Chrome 95.0.4638.54. It came when using Toasts in Bootstrap 5 with the bootstrap.min.js. When i switched to bootstrap.bundle.min.js the notice was gone.Demineralize
V
385

Update: Chrome 58+ hid these and other debug messages by default. To display them click the arrow next to 'Info' and select 'Verbose'.

Chrome 57 turned on 'hide violations' by default. To turn them back on you need to enable filters and uncheck the 'hide violations' box.

suddenly it appears when someone else involved in the project

I think it's more likely you updated to Chrome 56. This warning is a wonderful new feature, in my opinion, please only turn it off if you're desperate and your assessor will take marks away from you. The underlying problems are there in the other browsers but the browsers just aren't telling you there's a problem. The Chromium ticket is here but there isn't really any interesting discussion on it.

These messages are warnings instead of errors because it's not really going to cause major problems. It may cause frames to get dropped or otherwise cause a less smooth experience.

They're worth investigating and fixing to improve the quality of your application however. The way to do this is by paying attention to what circumstances the messages appear, and doing performance testing to narrow down where the issue is occurring. The simplest way to start performance testing is to insert some code like this:

function someMethodIThinkMightBeSlow() {
    const startTime = performance.now();

    // Do the normal stuff for this function

    const duration = performance.now() - startTime;
    console.log(`someMethodIThinkMightBeSlow took ${duration}ms`);
}

If you want to get more advanced, you could also use Chrome's profiler, or make use of a benchmarking library like this one.

Once you've found some code that's taking a long time (50ms is Chrome's threshold), you have a couple of options:

  1. Cut out some/all of that task that may be unnecessary
  2. Figure out how to do the same task faster
  3. Divide the code into multiple asynchronous steps

(1) and (2) may be difficult or impossible, but it's sometimes really easy and should be your first attempts. If needed, it should always be possible to do (3). To do this you will use something like:

setTimeout(functionToRunVerySoonButNotNow);

or

// This one is not available natively in IE, but there are polyfills available.
Promise.resolve().then(functionToRunVerySoonButNotNow);

You can read more about the asynchronous nature of JavaScript here.

Vicar answered 20/2, 2017 at 23:53 Comment(11)
Just a suggestion, instead of using performance.now(), you could use console.time (developer.mozilla.org/en-US/docs/Web/API/Console/time) console.time('UniquetLabelName') ....code here.... console.timeEnd('UniqueLabelName')Isotonic
@Isotonic I guess so. I'm not sure what value that really adds though. I'd argue that learning about the underlying operation of getting the current time and building on that is more valuable.Vicar
Great answer, voltrevo! My question is, if code like this this is a violation, what exactly is it in violation of? There has to be some kind of standard that Google is applying, but is that standard publicly documented anywhere?Antipathy
@Antipathy Dunno, I'd like to know if there's some guideline it's referring to as well.Vicar
Just curious if anyone knows how the 50ms limit is exceeded for Google Inbox re: Google Inbox, for instance, seems to have 150ms for "Handler runtime."Lithiasis
@Antipathy I can only guess that it's saying that the code that is animating is in violation of providing at least a 60 frame per second and therefore giving a poor user experience. .Alfieri
Promise.resolve().then(functionToRunVerySoonButNotNow); won't help at all here. It will run in a microtask right after the current task and won't let the browser do anything else. That is, for the browser, it's exactly the same as a synchronous action: it will block the UI (even more badly than normally since usual fool's guards will have hard time to figure out it's a long running task and they should move this to the next event loop iteration as they usually do. Stoopid demo, be careful.Soldierly
@Antipathy I'm not sure, but I think this could be the thing that it violates developers.google.com/web/fundamentals/performance/renderingFortyniner
the answer from @therobinkim is better as they offer real life examples to find the culprit code/module. Explaining what reflow is... useless at least to me.Rhinitis
@Vicar Suppose I am making a raycasted world using HTML canvas API. It is surely computationally expensive but it can't be helped. How to get rid of the message at least ?(because someone viewing my demo which is otherwise running smoothly wouldn't want a polluted console)Saharanpur
I agree that the warning is nice but Chrome definitely should give pointer to the line that caused the forced reflow. When you have a project that uses 15 javascript libraries and you get this warning out of blue, it's pretty hard to figure out the exact cause.Heatherheatherly
O
155

These are just warnings as everyone mentioned. However, if you're keen on resolving these (which you should), then you need to identify what is causing the warning first. There's no one reason due to which you can get force reflow warning. Someone has created a list for some possible options. You can follow the discussion for more information.
Here's the gist of the possible reasons:

What forces layout / reflow

All of the below properties or methods, when requested/called in JavaScript, will trigger the browser to synchronously calculate the style and layout*. This is also called reflow or layout thrashing, and is common performance bottleneck.

Element

Box metrics
  • elem.offsetLeft, elem.offsetTop, elem.offsetWidth, elem.offsetHeight, elem.offsetParent
  • elem.clientLeft, elem.clientTop, elem.clientWidth, elem.clientHeight
  • elem.getClientRects(), elem.getBoundingClientRect()
Scroll stuff
  • elem.scrollBy(), elem.scrollTo()
  • elem.scrollIntoView(), elem.scrollIntoViewIfNeeded()
  • elem.scrollWidth, elem.scrollHeight
  • elem.scrollLeft, elem.scrollTop also, setting them
Focus
  • elem.focus() can trigger a double forced layout (source)
Also…
  • elem.computedRole, elem.computedName
  • elem.innerText (source)

getComputedStyle

window.getComputedStyle() will typically force style recalc (source)

window.getComputedStyle() will force layout, as well, if any of the following is true:

  1. The element is in a shadow tree
  2. There are media queries (viewport-related ones). Specifically, one of the following: (source) * min-width, min-height, max-width, max-height, width, height * aspect-ratio, min-aspect-ratio, max-aspect-ratio
    • device-pixel-ratio, resolution, orientation
  3. The property requested is one of the following: (source)
    • height, width * top, right, bottom, left * margin [-top, -right, -bottom, -left, or shorthand] only if the margin is fixed. * padding [-top, -right, -bottom, -left, or shorthand] only if the padding is fixed. * transform, transform-origin, perspective-origin * translate, rotate, scale * webkit-filter, backdrop-filter * motion-path, motion-offset, motion-rotation * x, y, rx, ry

window

  • window.scrollX, window.scrollY
  • window.innerHeight, window.innerWidth
  • window.getMatchedCSSRules() only forces style

Forms

  • inputElem.focus()
  • inputElem.select(), textareaElem.select() (source)

Mouse events

  • mouseEvt.layerX, mouseEvt.layerY, mouseEvt.offsetX, mouseEvt.offsetY (source)

document

  • doc.scrollingElement only forces style

Range

  • range.getClientRects(), range.getBoundingClientRect()

SVG

contenteditable

  • Lots & lots of stuff, …including copying an image to clipboard (source)

Check more here.

Also, here's Chromium source code from the original issue and a discussion about a performance API for the warnings.


Edit: There's also an article on how to minimize layout reflow on PageSpeed Insight by Google. It explains what browser reflow is:

Reflow is the name of the web browser process for re-calculating the positions and geometries of elements in the document, for the purpose of re-rendering part or all of the document. Because reflow is a user-blocking operation in the browser, it is useful for developers to understand how to improve reflow time and also to understand the effects of various document properties (DOM depth, CSS rule efficiency, different types of style changes) on reflow time. Sometimes reflowing a single element in the document may require reflowing its parent elements and also any elements which follow it.

In addition, it explains how to minimize it:

  1. Reduce unnecessary DOM depth. Changes at one level in the DOM tree can cause changes at every level of the tree - all the way up to the root, and all the way down into the children of the modified node. This leads to more time being spent performing reflow.
  2. Minimize CSS rules, and remove unused CSS rules.
  3. If you make complex rendering changes such as animations, do so out of the flow. Use position-absolute or position-fixed to accomplish this.
  4. Avoid unnecessary complex CSS selectors - descendant selectors in particular - which require more CPU power to do selector matching.
Oospore answered 26/6, 2017 at 9:32 Comment(2)
More background: the Chromium source code from the original issue and a discussion about a performance API for the warnings.Lithiasis
According to the above, simply reading element.scrollTop triggers a reflow. This strikes me as a counter-intuitive phenomenon. I can understand why setting element.scrollTop would trigger a reflow, but simply reading its value? Can someone explain further why this is the case, if indeed this is the case?Scholasticate
I
43

A couple of ideas:

  • Remove half of your code (maybe via commenting it out).

    • Is the problem still there? Great, you've narrowed down the possibilities! Repeat.

    • Is the problem not there? Ok, look at the half you commented out!

  • Are you using any version control system (eg, Git)? If so, git checkout some of your more recent commits. When was the problem introduced? Look at the commit to see exactly what code changed when the problem first arrived.

Iberia answered 19/12, 2016 at 8:34 Comment(12)
thank you for your answer. i did remove half and even exclude my main .js file from the project. somehow the error still occurred. this is why i'm so frustrating about it. and yeah, i'm using git. i just realized this error today. there have been a lot of commits since this became group project. might do a deep checking. thanks again for the ideas.Gnat
@Gnat use the same strategy with finding the git commit. For example, if I had 10 commits (A, B, C, D, E, F, G, H, I, J) where A was the oldest, I'd git checkout E to see if the problem already exists. If yes, I'll continue to look for the problem in the first half of the commits. Otherwise, I look for the problem in the second half.Iberia
@Gnat Also, if you omitted your main .js file and the problem persists... it could be a library you brought in via a <script src="..."> tag! Maybe something not worth worrying about (especially since it's just a warning)?Iberia
i've finally found where the problem is. i used your second idea to track the changes. and yes, the problem comes from an external .js file. apparently, it does matter. it slows my site quite significant. anyway, thanks again for your answers and ideas.Gnat
@Gnat Sure thing. Good luck w/ your project!Iberia
This is console feature There is setting for show and hide violation, he just turned on that why its appearingRegulus
You can use git bisect to apply the binary search. I think it's just for the purpose of bug finding.Bouzoun
git bisect is totally cool. For finding a bug, or just any change among many commits. No more forgetting which one worked or didn't.Rumery
You can't remove half of a large project. This is only possible in single file projects.Manfred
Hahahaha, the slow process of elimination... you'll love this: https://mcmap.net/q/75025/-what-is-the-best-way-to-debug-performance-problemsJacoby
git-scm.com/docs/git-bisect is more suited to search for a commit that started a problemWorld
I've done this for 20 years lol this is too funny. It works so well. Its nice with PHP, you can just insert die('foo') anywhere, JS I use alert('foo') to prompt where it reached before it crapped out - and you know where you are stopping.Phore
S
21

I found the root of this message in my code, which searched and hid or showed nodes (offline). This was my code:

search.addEventListener('keyup', function() {
    for (const node of nodes)
        if (node.innerText.toLowerCase().includes(this.value.toLowerCase()))
            node.classList.remove('hidden');
        else
            node.classList.add('hidden');
});

The performance tab (profiler) shows the event taking about 60 ms: Chromium performance profiler layout recalculation reflow

Now:

search.addEventListener('keyup', function() {
    const nodesToHide = [];
    const nodesToShow = [];
    for (const node of nodes)
        if (node.innerText.toLowerCase().includes(this.value.toLowerCase()))
            nodesToShow.push(node);
        else
            nodesToHide.push(node);

    nodesToHide.forEach(node => node.classList.add('hidden'));
    nodesToShow.forEach(node => node.classList.remove('hidden'));
});

The performance tab (profiler) now shows the event taking about 1 ms: Chromium profiler dark

And I feel that the search works faster now (229 nodes).

Stapes answered 1/3, 2018 at 10:25 Comment(1)
In summary, by receiving the violation, you were able to optimize your code, and it performs better now.Festival
S
16

In order to identify the source of the problem, run your application, and record it in Chrome's Performance tab.

There you can check various functions that took a long time to run. In my case, the one that correlated with warnings in console was from a file which was loaded by the AdBlock extension, but this could be something else in your case.

Check these files and try to identify if this is some extension's code or yours. (If it is yours, then you have found the source of your problem.)

Specific answered 20/8, 2017 at 15:55 Comment(2)
Nope, I don't have AdBlock and I still get it in the console.Quixotism
Try to analyze it with Performance tab, and look for source of the functions which run long time. This could be anything, but this is a potential way to identify source of the issue.Specific
S
6

Look in the Chrome console under the Network tab and find the scripts which take the longest to load.

In my case there were a set of Angular add on scripts that I had included but not yet used in the app :

<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-utils/0.1.1/angular-ui-utils.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular-animate.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular-aria.min.js"></script>

These were the only JavaScript files that took longer to load than the time that the "Long Running Task" error specified.

All of these files run on my other websites with no errors generated but I was getting this "Long Running Task" error on a new web app that barely had any functionality. The error stopped immediately upon removing.

My best guess is that these Angular add ons were looking recursively into increasingly deep sections of the DOM for their start tags - finding none, they had to traverse the entire DOM before exiting, which took longer than Chrome expects - thus the warning.

Sketchy answered 16/3, 2017 at 15:16 Comment(0)
M
5

I found a solution in Apache Cordova source code. They implement like this:

var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve();
var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };

Simple implementation, but smart way.

Over the Android 4.4, use Promise. For older browsers, use setTimeout()


Usage:

nextTick(function() {
  // your code
});

After inserting this trick code, all warning messages are gone.

Molarity answered 16/11, 2017 at 3:19 Comment(0)
P
5

Adding my insights here as this thread was the "go to" stackoverflow question on the topic.

My problem was in a Material-UI app (early stages)

  • placement of custom Theme provider was the cause

when I did some calculations forcing rendering of the page (one component, "display results", depends on what is set in others, "input sections").

Everything was fine until I updated the "state" that forces the "results component" to rerender. The main issue here was that I had a material-ui theme (https://material-ui.com/customization/theming/#a-note-on-performance) in the same renderer (App.js / return.. ) as the "results component", SummaryAppBarPure

Solution was to lift the ThemeProvider one level up (Index.js), and wrapping the App component here, thus not forcing the ThemeProvider to recalculate and draw / layout / reflow.

before

in App.js:

  return (
    <>
      <MyThemeProvider>
      <Container className={classes.appMaxWidth}>

        <SummaryAppBarPure
//...

in index.js

ReactDOM.render(
  <React.StrictMode>
      <App />
//...

after

in App.js:

return (
    <>
      {/* move theme to index. made reflow problem go away */}
      {/* <MyThemeProvider> */}
      <Container className={classes.appMaxWidth}>

        <SummaryAppBarPure
//...

in index.js

ReactDOM.render(
  <React.StrictMode>
    <MyThemeProvider>
      <App />
//...
Pleuropneumonia answered 10/5, 2020 at 9:57 Comment(0)
B
4

This was added in the Chrome 56 beta, even though it isn't on this changelog from the Chromium Blog: Chrome 56 Beta: “Not Secure” warning, Web Bluetooth, and CSS position: sticky

You can hide this in the filter bar of the console with the Hide violations checkbox.

Bay answered 3/1, 2017 at 11:12 Comment(0)
G
4

This is violation error from Google Chrome that shows when the Verbose logging level is enabled.

Example of error message:

screenshot of the warning

Explanation:

Reflow is the name of the web browser process for re-calculating the positions and geometries of elements in the document, for the purpose of re-rendering part or all of the document. Because reflow is a user-blocking operation in the browser, it is useful for developers to understand how to improve reflow time and also to understand the effects of various document properties (DOM depth, CSS rule efficiency, different types of style changes) on reflow time. Sometimes reflowing a single element in the document may require reflowing its parent elements and also any elements which follow it.

Original article: Minimizing browser reflow by Lindsey Simon, UX Developer, posted on developers.google.com.

And this is the link Google Chrome gives you in the Performance profiler, on the layout profiles (the mauve regions), for more info on the warning.

Geer answered 29/5, 2019 at 19:40 Comment(0)
W
3

If you're using Chrome Canary (or Beta), just check the 'Hide Violations' option.

Hide Violations Checkbox in Chrome 56 Console

Wallywalnut answered 24/1, 2017 at 9:57 Comment(0)
T
1

For what it’s worth, here are my 2¢ when I encountered the

[Violation] Forced reflow while executing JavaScript took <N>ms

warning. The page in question is generated from user content, so I don’t really have much influence over the size of the DOM. In my case, the problem is a table of two columns with potentially hundreds, even thousands of rows. (No on-demand row loading implemented yet, sorry!)

Using jQuery, on keydown the page selects a set of rows and toggles their visibility. I noticed that using toggle() on that set triggers the warning more readily than using hide() & show() explicitly.

For more details on this particular performance scenario, see also this article.

Thresher answered 4/7, 2020 at 7:40 Comment(0)
D
-2

The answer is that it's a feature in newer Chrome browsers where it alerts you if the web page causes excessive browser reflows while executing JS. Please refer to

Deafen answered 16/11, 2022 at 10:57 Comment(0)
S
-3

Forced reflow often happens when you have a function called multiple times before the end of execution.

For example, you may have the problem on a smartphone, but not on a classic browser.

I suggest using a setTimeout to solve the problem.

This isn't very important, but I repeat, the problem arises when you call a function several times, and not when the function takes more than 50 ms. I think you are mistaken in your answers.

  1. Turn off 1-by-1 calls and reload the code to see if it still produces the error.
  2. If a second script causes the error, use a setTimeOut based on the duration of the violation.
Sthilaire answered 25/3, 2019 at 14:2 Comment(1)
This is not a solution. It's a suggestion better left as a comment to the original question.Geer
D
-11

This is not an error just simple a message. To execute this message change
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> (example)
to
<!DOCTYPE html>(the Firefox source expect this)

The message was shown in Google Chrome 74 and Opera 60 . After changing it was clear, 0 verbose.
A solution approach

Debacle answered 26/5, 2019 at 11:45 Comment(1)
Just some advice: Your answer has nothing to do with the questions. Either fix your answer or remove it. The question was "why is the Chrome browser console showing a violation warning". The answer is that it's a feature in newer Chrome browsers where it alerts you if the web page causes excessive browser reflows while executing JS. Please refer to this resource from Google for more info.Geer

© 2022 - 2024 — McMap. All rights reserved.