Open Bug 1846115 Opened 1 year ago Updated 6 months ago

The debugger can cause webpage lagging

Categories

(Core :: JavaScript Engine, defect, P3)

defect

Tracking

()

UNCONFIRMED
Performance Impact low

People

(Reporter: yjbrowserjyt, Unassigned)

References

(Depends on 1 open bug, )

Details

(Keywords: perf:animation, reproducible)

Attachments

(1 file)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.183
Firefox for Android

Steps to reproduce:

To prevent web pages from being debugged, the industry typically employs a timer to enter the debugger loop.
just like:
setInterval(function(){
check();
}, 2000);
var check = function(){
function doCheck(a){
if (('' + a / a)['length'] !== 1 || a % 20 === 0){
(function() {}'constructor'());
} else {
(function() {}'constructor'());
}
doCheck(++a);
}
try {
doCheck(0);
}catch(err){}
};
check();

In Firefox browser on Android, there may be lags or slowdowns when the page is scrolling or when there are canvas drawings present.

Actual results:

I have created a test website to test for you. When you click the button in the top-left corner, the yellow ball rotation becomes laggy.
https://www.yjllq.com/fpstest.html

Expected results:

I believe that the Android version of Firefox (GeckoView) should have a master switch. When the device is connected for debugging, this master switch would be turned on, and the debugger would take effect. At other times, the debugger should be an empty implementation and not cause any lag.

The Bugbug bot thinks this bug should belong to the 'DevTools::Debugger' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.

Component: Untriaged → Debugger
Product: Firefox → DevTools
Duplicate of this bug: 1846114

Actual snippet from the example with debugger keywords:

    	let check = function(){
			function doCheck(a){
				if (('' + a / a)['length'] !== 1 || a % 20 === 0){
					(function() {}['constructor']('debugger')());
				} else {
					(function() {}['constructor']('debugger')());
				}
				doCheck(++a);
			}
			try {
				doCheck(0);
			}catch(err){}
		};
    function start(){
            setInterval(function(){
			check();
		}, 1000);

Looks like the STRs do not involve starting devtools or trying to debug the page. Simply having this script with debugger statements slows down the page on geckoview?

Component: Debugger → General
Product: DevTools → GeckoView

(In reply to Julian Descottes [:jdescottes] from comment #4)

Looks like the STRs do not involve starting devtools or trying to debug the page. Simply having this script with debugger statements slows down the page on geckoview?

Yes, as long as this statement is executed, it will cause the page to stall and there is no need to run devtool. But this statement will be frequently applied to prevent web pages from being debugged. Running this statement in Chrome does not cause stuttering. I think geckoview should fix this issue.

The severity field is not set for this bug.
:owlish, could you have a look please?

For more information, please visit BugBot documentation.

Flags: needinfo?(bugzeeeeee)

Reproduces for me on desktop as well

Component: General → Desktop
Flags: needinfo?(bugzeeeeee)
Product: GeckoView → Web Compatibility
Attached video debugger test.mp4

Verified this issue and it's still reproducible on Firefox versions 123 and 125.

Environment:
Operating system: Windows 10 / OnePlus 6 A6000 (Android 11)
Browsers: Firefox Nightly 125.0a1 (2024-02-20) / Firefox Release 123 / Chrome 121.0.6167.185

Notes:

  • Not reproducible on Chrome
  • Same behaviour on android
Summary: On Android phones, the debugger can cause webpage lagging. → The debugger can cause webpage lagging

Leaving a ni myself to capture a perf profile

Flags: needinfo?(kberezina)

There are a few separate issues going on here:

  1. The testcase is spamming new Function(...) in a loop that can cause performance problems without any debugger attached or debugger statement included. This is a performance issue that we can compare with chrome and see if it could be sped up slightly. The if statement is simply trying to confuse JITs so they don't optimize away things. I don't know if current versions of Firefox or Chrome optimize through this or not.

  2. This testcase recurses until an exception is thrown, so it is also sensitive to stack limits of different browsers. In the past (eg. Bug 1537609) we found some cases in the wild affected by this but have since set a reasonable limit.

  3. When a debugger is attached in Firefox, it fires a hook on every new script (including those generated by new Function) which slows the page down further. This is independent of whether a debugger statement is present. We could consider ignoring / speeding-up scripts that are dynamically injected if we thought this anti-debugger technique was actually a concern (noting that without the debugger, there is already performance problems on the page from spamming new functions).

  4. Actually running code in a loop with 'debugger' statement is a classic evil-trap, but firefox debugger does have the easy ability to turn off breaking on these statements already.

Realistically, only point 1 is worth doing much about and that is just a general performance matter (mostly GC performance of functions is poorer in Firefox than Chrome). I don't think the assumption of Comment 0 that this is due to debugger is correct.

Since we think this is a perf issue, I'm going to move this into the perf component.

Component: Site Reports → Performance
Product: Web Compatibility → Core
Version: Firefox 115 → unspecified

This bug was moved into the Performance component.

:yjbrowserjyt, could you make sure the following information is on this bug?

  • For slowness or high CPU usage, capture a profile with http://profiler.firefox.com/, upload it and share the link here.
  • For memory usage issues, capture a memory dump from about:memory and attach it to this bug.
  • Troubleshooting information: Go to about:support, click "Copy raw data to clipboard", paste it into a file, save it, and attach the file here.

If the requested information is already in the bug, please confirm it is recent.

Thank you.

Flags: needinfo?(yjbrowserjyt)

Profile from Nightly 126.0a1 on Android device: https://share.firefox.dev/3U68vdS

Flags: needinfo?(yjbrowserjyt)
Flags: needinfo?(kberezina)
Performance Impact: --- → ?

Moving to the JS engine component.

(In reply to Ted Campbell [:tcampbell] from comment #10)

  1. The testcase is spamming new Function(...) in a loop that can cause performance problems without any debugger attached or debugger statement included. This is a performance issue that we can compare with chrome and see if it could be sped up slightly. The if statement is simply trying to confuse JITs so they don't optimize away things. I don't know if current versions of Firefox or Chrome optimize through this or not.

[...]

Realistically, only point 1 is worth doing much about and that is just a general performance matter (mostly GC performance of functions is poorer in Firefox than Chrome). I don't think the assumption of Comment 0 that this is due to debugger is correct.

Component: Performance → JavaScript Engine

Without digging into what any other engines are doing here, the key piece here is this line:

(function() {}['constructor']('debugger')());

This is a roundabout way of writing (new Function("debugger"))(). We end up parsing the input and creating a new script on every invocation. In a stripped down microbenchmark, we spend ~90% of our time inside CreateDynamicFunction. The fact that we create a new script each time also prevents us from (eg) inlining.

We have an eval cache to help us reuse scripts between eval statements. If we wanted to make this case faster, we would presumably have to add a similar cache for the Function constructor.

Bug 1420440 is open to track this.

Severity: -- → S3
Depends on: 1420440
Priority: -- → P3

The Performance Impact Calculator has determined this bug's performance impact to be low. If you'd like to request re-triage, you can reset the Performance Impact flag to "?" or needinfo the triage sheriff.

Platforms: [x] Windows [x] macOS [x] Linux [x] Android
Websites affected: Rare
[x] Affects animation smoothness
[x] Able to reproduce locally

Performance Impact: ? → low
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: