GithubHelp home page GithubHelp logo

paulirish / automated-chrome-profiling Goto Github PK

View Code? Open in Web Editor NEW
865.0 39.0 72.0 570 KB

Node.js recipes for automating javascript profiling in Chrome

Home Page: https://github.com/paulirish/automated-chrome-profiling#readme

JavaScript 100.00%

automated-chrome-profiling's Introduction

Let's say you want to evaluate the performance of some clientside JavaScript and want to automate it. Let's kick off our measurement in Node.js and collect the performance metrics from Chrome. Oh yeah.

We can use the Chrome debugging protocol and go directly to how Chrome's JS sampling profiler interacts with V8. So much power here, so we'll use chrome-remote-interface as a nice client in front of the protocol:

Step 1: Clone this repo and serve it

git clone https://github.com/paulirish/automated-chrome-profiling
cd automated-chrome-profiling
npm install # get the dependencies
npm start  # serves the folder at http://localhost:8080/ (port hardcoded)

Step 2: Run Chrome with an open debugging port:

# linux
google-chrome --remote-debugging-port=9222 --user-data-dir=$TMPDIR/chrome-profiling --no-default-browser-check

# mac
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir=$TMPDIR/chrome-profiling --no-default-browser-check

Navigate off the start page to example.com or something.

Step 3: Run the CPU profiling demo app

node get-cpu-profile.js

CPU Profiling

Read through get-cpu-profile.js. Here's what it does:

  • It navigates your open tab to http://localhost:8080/perf-test.html
  • Starts profiling
  • run's the page's startTest();
  • Stop profiling and retrieve the profiling result
  • Save it to disk. We can then load the data into Chrome DevTools to view

You can do other stuff. For example...

Timeline recording

You can record from the timeline. The saved files is drag/droppable into the Timeline panel. See get-timeline-trace.js

Finding forced layouts (reflows)

A bit more specialized, you can take that timeline recording and probe it with questions like.. "How many times is layout forced"

See test-for-layout-trashing.js

Timeline model

The raw trace data is.. pretty raw. The devtools-timeline-model package provides an ability to use the Chrome DevTools frontend's trace parsing.

const filename = 'demo/mdn-fling.json'

var fs = require('fs')
var traceToTimelineModel = require('./lib/timeline-model.js')

var events = fs.readFileSync(filename, 'utf8')
var model = traceToTimelineModel(events)

model.timelineModel // full event tree
model.irModel // interactions, input, animations
model.frameModel // frames, durations

image

image

Why profile JS like this?

Well, it started because testing the performance of asynchronous code is difficult. Obviously measuring endTime - startTime doesn't work. However, using a profiler gives you the insight of how many microseconds the CPU spent within each script, function and its children, making analysis much more sane.

Way more is possible

This is just the tip of the iceberg when it comes to using the devtools protocol to manipulate and measure the browser. Plenty of other projects around this space as well: see the devtools protocol section on awesome-chrome-devtools for more.

Contributors

automated-chrome-profiling's People

Contributors

cyrus-and avatar eflanagan0 avatar garthdb avatar paulirish avatar rjankie avatar sbougonsf avatar vladikoff avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

automated-chrome-profiling's Issues

Chrome Remote Interface not working with Selenium/ChromeDriver

Hey there. I am having some trouble using Chrome Remote Interface on top of Chromedriver. I use Chromedriver to start chrome, find the remote-debugging-port and then connect Chrome Remote Interface to this port. Although the connection is successful, subsequent commands do not (i.e client.Page.navigate()) produce any effect. I understand Chrome can be started with chrome-launcher but I would like to use Webdriver to simulate certain workflows

Here is a test script to reproduce the issue(Given chromedriver is installed):

//test.js
var webdriver = require("selenium-webdriver");
var chrome = require("selenium-webdriver/chrome");
var cdp = require("chrome-remote-interface");

async function test(){
  var options = new chrome.Options();

 options.addArguments(["--detach=true"]);

  //START DRIVER
  var driver = new webdriver.Builder().
  withCapabilities(options.toCapabilities()).build();

  //FIND REMOTE DEBUGGING PORT
  await driver.get("chrome://version");
  let element = await driver.findElement(webdriver.By.id('command_line'));
  let text = await element.getText();
  console.log('Chrome command line flags:');
  console.log(text);

  var splitStr=text.split(" ");
  let port = 0;
  splitStr.filter(function(word,index){
    if(word.match(/--remote-debugging-port=*/)){
      console.log(word);
      port = Number(word.split('=')[1]);

    }else{
    }
  });

  console.log(typeof port)
  console.log('Port:');
  console.log(port);

  //START CHROME REMOTE INTERFACE
  cdp({
    port:port
  }, function(chrome){
    console.log(chrome);
    chrome.Page.enable();
    chrome.Page.navigate({'url': 'https://yahoo.com'}) //NOT WORKING
  }).on('error', function (e) {
    console.error('Cannot connect to Chrome', e);
  });

}

test();

SELENIUM_BROWSER=chrome node test.js

This script works when Chrome is started via chrome-launcher, so my guess is starting Chrome via chromedriver may have options enabled that impede Chrome Remote interface to work on top of it.

Need help with running automated chrome profile test

I'm having trouble getting this to run a pilot performance test.

Issue 1 - Instructions in demo/perf-tests.html: "Run the script from this folder: node index.js"
I don't see any index.js in the project so appreciate if you could send in pointers to resolve this.
We are planning to use this as part of continuous performance testing to get data from chrome profile.

Issue 2 - Start a server of port 8000 in demo folder. Not able to do that either.

Appreciate your help!

Timeline data not populated when using Runtime.runScript

Hi Paul,

Awesome resource again!

I would like to trace several scripts. Instead of using Page.navigate I prefer to inject them on the fly. I'm doing so like this:

const frameworkCode = // loaded source
const testCode = // loaded source

Runtime.compileScript({
  expression: `
    ${frameworkCode}
    ${testCode}
  `,
  sourceURL: 'mount-long-sequence.js',
  persistScript: true
})
.then(Runtime.runScript)

But when I use Tracing to fetch timeline data, I don't have any event related to the JavaScript execution ๐Ÿ˜ข I've tried to play with categories and finally came to the conclusion that for some reason Tracing doesn't catch JavaScript code executed like this. But I may be wrong.

Do you know if it's possible? Am I missing something?

Thanks!

Assessing rendering impact (timeline? tracing?)

Hey folks,

Your profiler example works great and I was able to quickly automate and get (profiler) results for my test page.

However, even more important in my case is to get access to a timeline and asses rendering performance. I'd like to be able to see how much time is spent on scripting/reflowing/painting/etc. and just how expensive certain things are to render overall. Ultimately, this would allow to create rendering performance benchmarks to compare multiple versions of an app, determine faster one, catch regressions, etc.

So... after some searching, it appears that timeline can no longer be accessed in favor of tracing. Ok, cool. But I can't figure out how to get any sensible info from the Tracing API, similar to your example.

I'm doing this:

Page.loadEventFired(function () {

  Tracing.start();

  Runtime.evaluate({ "expression": "..." });

  setTimeout(function() {
    Tracing.end();
  }, 3000);
});

Page.navigate({ 'url': options.url });

Tracing.dataCollected(function(data) {
  console.log(data);
  chrome.close();
});

And the "collected data" looks like this:

{ value:
   [ { pid: 9409,
       tid: 15419,
       ts: 73298730977,
       ph: 'X',
       cat: 'toplevel',
       name: 'MessagePumpLibevent::OnLibeventNotification',
       args: [Object],
       tdur: 0,
       tts: 84955 },
     { pid: 9409,
       tid: 15419,
       ts: 73298731035,
       ph: 'X',
       cat: 'ipc,toplevel',
       name: 'ChannelReader::DispatchInputData',
       args: [Object],
       tdur: 0,
       tts: 84974,
       bind_id: '0x2e3e4702',
       flow_in: true },
     { pid: 9409,
       tid: 15419,
       ts: 0,
       ph: 'M',
       cat: '__metadata',
       name: 'overhead',
       args: [Object] },
     { pid: 9409,
       tid: 0,
       ts: 0,
       ph: 'M',
       cat: '__metadata',
       name: 'num_cpus',
       args: [Object] },
     { pid: 9409,
       tid: 15419,
       ts: 0,
       ph: 'M',
       cat: '__metadata',
       name: 'process_sort_index',
       args: [Object] },
     { pid: 9409,
       tid: 15419,
       ts: 0,
       ph: 'M',
       cat: '__metadata',
       name: 'process_name',
       args: [Object] },
     { pid: 9409,
       tid: 1299,
       ts: 0,
       ph: 'M',
       cat: '__metadata',
       name: 'thread_sort_index',
       args: [Object] },
     { pid: 9409,
       tid: 1299,
       ts: 0,
       ph: 'M',
       cat: '__metadata',
       name: 'thread_name',
       args: [Object] },
     { pid: 9409,
       tid: 15419,
       ts: 0,
       ph: 'M',
       cat: '__metadata',
       name: 'thread_name',
       args: [Object] } ] }

There doesn't seem to be anything useful. What am I doing wrong? Any way to tap into timeline results?

No JavaScript Stack trace any more ?

Hi Paul,

when I use your script (node get-timeline-trace.js) and I open the resulting trace in Chrome (tried M56, M57 and Canary 59), I'm not getting the javaScript stackTrace:
screen shot 2017-03-21 at 9 08 08 pm
However, if I profile your website by pressing "record" in the timeline view, I'm getting everything:
screen shot 2017-03-21 at 9 07 45 pm

So, I put a debugger in the devtools code to see what tracing and options were used and got this:
"categories": ["-*", "devtools.timeline", "v8.execute", "disabled-by-default-devtools.timeline", "disabled-by-default-devtools.timeline.frame", "toplevel", "blink.console", "blink.user_timing", "latencyInfo", "disabled-by-default-devtools.timeline.stack"].join(','), "options": "sampling-frequency=10000", "bufferUsageReportingInterval" : 500, "transferMode" : "ReportEvents"
but, even modifying get-timeline-trace.js with the 4 lines above, I'm still not getting the stack traces.
Do you know what could be the issue ? We are still stuck with the CpuProfile for our automation (via ChromeDriver because of a somewhat related issue), so I wanted to try by hitting Chrome directly, but did not work.

Would appreciate any pointers !

Take care,
Steven
automated-chrome-profiling: latest version
node: v6.2.2
Chrome: 57.0.2987.110 (64-bit)
OS: MacOs 10.12.3

Auto record and save chrome developer tools is not working

Hi Paulirish,

After i followed the instructions ,I am encountering the following issues.

  1. I am able to see the CPU profile under the C:\tools\automated-chrome-profiling , but when i load the profile i am not able to see any content
    2.Getting error when i run node get-timeline-trace.js , node log-trace-metrics.js

My main goal is with Auto record capture the Performance metrics aka Timeline and later on i can load it and do some analysis.

Please see the blow screenshots

I am not sure what went wrong .Could you you please advise!

image

image

image

image

image

image

Thanks,
Raj

Need help in understanding mdn-fling.json

Hi,
Really appreciate your help doing POC using automated-chrome-profiling and stuck here!

1)Could you please explain how did you generate mdn-fling.json ?

log-trace-metrics.js file has const filename = 'demo/mdn-fling.json'
2) And also where do we need to save the below one and how it works and which .js file we need to run i.e npm .js
_Timeline model

const filename = 'demo/mdn-fling.json'

var fs = require('fs')
var traceToTimelineModel = require('./lib/timeline-model.js')

var events = fs.readFileSync(filename, 'utf8')
var model = traceToTimelineModel(events)

model.timelineModel // full event tree
model.irModel // interactions, input, animations
model.frameModel // frames, durations_

image

Question : Does get-timeline-trace.js gives traces for single url?

hi,

Since get-timeline-trace.js has single url of https://github.com/paulirish/automated-chrome-profiling does it captures only single url, though user browses multi url's after login via mail url?

Really appreciate your help doing POC using automated-chrome-profiling and stuck here!

Here is what i did :

In the get-timeline-trace.js file provided main url and saved it.

Then executed the below steps.
Step 1: npm start
Step 2: Run Chrome with an open debugging port:
chrome --remote-debugging-port=9222
Step 3:
3a) Type main url i. Login into application ( mentioned in get-timeline-trace.js) Ex: https://xxxx/sc/login.html?response_type=code&redirect_uri=http%3A%2F%2Fxxxx.ep.corp%2Fauth%2Fcallback&scope=&client_id=xxx-qa1
3b)Landed on 2nd page different url from #3a i.e #a redirect to #3b Ex: http://xxxxxxx/projects/19306/timecards/browse
3c)Clicked on Batch Tab from the 3b page then it lands on different page i.e different url Ex: http://xxxxxx/projects/19306/batches/browse
3d)created new batch of #3c i.e post (form)
3e)Logout
Step 4: Ran below commands
node get-cpu-profile.js
node get-timeline-trace.js

Results : In generated profile-1550277791150.devtools.trace able to see only main url #3a which is mentioned in get-timeline-trace.js file

Questions :
1)Though user browse different urls via main login url,does it always get the trace just for the main url? Ex: https://xxxx/sc/login.html?response_type=code&redirect_uri=http%3A%2F%2Fxxxx.ep.corp%2Fauth%2Fcallback&scope=&client_id=xxx-qa1

  1. If so #1, then how to mention multi url's Page.navigateunder get-timeline-trace.js

image

image

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.