GoogleChrome / lighthouse

Automated auditing, performance metrics, and best practices for the web.
https://developer.chrome.com/docs/lighthouse/overview/
Apache License 2.0
28.4k stars 9.39k forks source link

Improve "Tracing has already been started" message #15775

Open aldobarrios81 opened 9 months ago

aldobarrios81 commented 9 months ago

FAQ

URL

https://machupicchuperuagency.com/

What happened?

Protocol error (Tracing.start): Tracing has already been started (possibly in another tab).

Channel: DevTools
Initial URL: https://machupicchuperuagency.com/
Chrome Version: 120.0.0.0
Stack Trace: it: Protocol error (Tracing.start): Tracing has already been started (possibly in another tab).
    at <instance_members_initializer> (devtools://devtools/bundled/third_party/puppeteer/puppeteer.js:1:35543)
    at new jt (devtools://devtools/bundled/third_party/puppeteer/puppeteer.js:1:35582)
    at Ht.create (devtools://devtools/bundled/third_party/puppeteer/puppeteer.js:1:34950)
    at s._rawSend (devtools://devtools/bundled/third_party/puppeteer/puppeteer.js:1:73366)
    at $t.send (devtools://devtools/bundled/third_party/puppeteer/puppeteer.js:1:36495)
    at I1.sendCommand (devtools://devtools/bundled/third_party/lighthouse/lighthouse-dt-bundle.js:446:13207)
    at t.startSensitiveInstrumentation (devtools://devtools/bundled/third_party/lighthouse/lighthouse-dt-bundle.js:13:55448)
    at async devtools://devtools/bundled/third_party/lighthouse/lighthouse-dt-bundle.js:446:21110
    at async collectPhaseArtifacts (devtools://devtools/bundled/third_party/lighthouse/lighthouse-dt-bundle.js:446:21238)
    at async _navigation (devtools://devtools/bundled/third_party/lighthouse/lighthouse-dt-bundle.js:449:11655)

What did you expect?

Complete report

What have you tried?

No response

How were you running Lighthouse?

Chrome DevTools

Lighthouse Version

11.2.0

Chrome Version

No response

Node Version

No response

OS

No response

Relevant log output

No response

adamraine commented 9 months ago

I can't reproduce this. Does restarting your Chrome help?

gersanco commented 9 months ago

I have the same error, it happens in Incognito mode. But, when I restarted the browser, it worked.

hilja commented 9 months ago

I get this too when trying to generate mobile and desktop report at the same time with Promise.all(), using node. I solved it my by launching Chrome in a separate worker thread with tinypool. But I’d rather have one Chrome instance running where I generate the reports, that would take less resources. I really have to scale up my box.

I tried to open a new tab with Puppeteer for each form-factor but that didn’t help.

Any ideas how to isolate the report runs in the same Chrome process?

Here's my Tinypool setup if anyone’s interested:

export default async function ({ formFactors, ...runnerOpts }: JobData) {
  try {
    const pool = new Tinypool({
      filename: new URL('./worker.js', import.meta.url).href,
      idleTimeout: 1000,
    })

    return Promise.all<NormalizedResult>(
      formFactors.map(formFactor => pool.run({ ...runnerOpts, formFactor }))
    )
  } catch (err: any) {
    console.error(err, 'REPORT_POOL_ERROR')
    throw err
  }
}
hilja commented 9 months ago

Not exactly the same as with OP, but here's a repro anyway. This should fail with ProtocolError: Protocol error (Tracing.start): Tracing has already been started (possibly in another tab):

import * as chromeLauncher from 'chrome-launcher'
import lighthouse from 'lighthouse'
import lrDesktopConfig from 'lighthouse/core/config/lr-desktop-config.js'
import lrMobileConfig from 'lighthouse/core/config/lr-mobile-config.js'

const chrome = await chromeLauncher.launch({
  chromeFlags: [
    '--disable-dev-shm-usage',
    '--disable-setuid-sandbox',
    '--headless',
    '--no-sandbox',
  ],
})

export default async function ({
  formFactors,
  url,
}: {
  formFactors: ('mobile' | 'desktop')[]
  url: string
}) {
  try {
    const results = await Promise.all(
      formFactors.map(formFactor =>
        lighthouse(
          url,
          { formFactor, port: chrome.port },
          formFactor === 'mobile' ? lrMobileConfig : lrDesktopConfig
        )
      )
    )

    return results
  } catch (err) {
    console.error(err)
    throw err
  }
}
hilja commented 9 months ago

A bit off-topic but here's some observation running Chrome in a Node worker thread using Tinypool (a fork of Piscina).

This is the memory utilization:

Screenshot 2024-02-15 at 15 42 00
  1. The left-most drop is a new deploy.
  2. The next two peaks are each one set of reports created (one set = mobile and desktop report).
  3. The last peak is three sets created at the same time.

After every peak the pool is nuked await pool.destroy() and chrome killed chrome.kill(). But as you see the memory is not fully cleared, classic memory leak. That might be an issue with Tinypool/Piscina, there’s a similar issue here https://github.com/piscinajs/piscina/issues/442. Shot in the dark but in the sharp repo people say that moving Alpine solved their memory issues because it has a different memory allocator https://github.com/lovell/sharp/issues/955#issuecomment-390398044.

I know Chrome need a lot of memory, but it's out of control here, 1 gig is not that much but this was me just testing for few times, in a prod env you'd need much much more, which will get costly.

So I'm thinking it would be less resource intensive to have one Chrome instance which can run reports parallel in separate tabs etc, after the report is done close the tab and I assume the tabs memory is released. Something like that.

adamraine commented 8 months ago

I can't reproduce the original issue. Keeping this open to track improvements to the error message that explain why running multiple Lighthouse instances at the same time can be bad.


@hilja taking a look at your code, running multiple Lighthouse tests at the same time on the same browser instance is not supported for the reason the error message explains. Each browser instance can only support tracing on one tab at a time.

You could try getting a new browser instance for each Lighthouse test by calling chromeLauncher.launch once for each call to lighthouse.

hilja commented 8 months ago

running multiple Lighthouse tests at the same time on the same browser instance is not supported

Got it. Is that a fundamental limitation of Lighthouse or something that might change in the future?

Off-topic but, I managed to figure this out pretty well after-all. I was initiating Tinypool inside the function, where as I should've done it outside 😅

Also I found out that the load of the machine effects the results quote a lot, so ideally you'd only run one LH test per machine. This sounds ridiculously expensive and wasteful, but I'm hosted on fly.io and their VMs can be powered down easily since the cold start is about 1 second. Also powered down machines at fly are free (at least for now) so I can have like 30 of them with not much more cost than having one 24/7 running machine. I set the concurrent connections limit to 1 per machine and let their load balancer handle the task distribution. It's all very experimental at the moment and it's not in production yet but so far it's been working okay.

In this scenario memory leaks also don't matter, plus I switched to Alpine (running chromium) which apparently handles memory fragmentation better, it’s largely black magic to me but it has something to do with jemalloc maybe.

adamraine commented 8 months ago

Got it. Is that a fundamental limitation of Lighthouse or something that might change in the future?

This error is actually a limitation of Chrome itself and unlikely to change in the future.