UNPKG

5.53 kBMarkdownView Raw
1## Understanding the analysis
2
3An unknown issue occurs when Clinic.js' analysis algorithms are unable to categorize the sampling results but nevertheless an issue *of some kind* has been detected.
4
5This outcome can be attributed to one of two scenarios:
6
71. Ambient noise – for instance, other applications using the CPU or memory – during the sampling period has polluted the results.
82. There is a genuine performance issue but `clinic doctor` doesn't recognize it.
9
10In the case of ambient noise, there may still be a specific, categorizable performance issue.
11
12We can make eliminate the possibility of ambient noise and make it easier for Clinic.js to definitively recognize the issue by:
13
14- Closing down as many applications as possible, especially applications that are CPU- or Memory- intensive.
15- Using the `--on-port` flag. This can reduce the chances of unknown issues because there is no time gap nor additional system activity between the server starting and the load test beginning.
16
17By way of example, instead of running `clinic -- node app.js` in one terminal and `autocannon localhost:3000` in another, it is preferable and recommended to trigger both in one command using the following command:
18
19```sh
20clinic doctor --on-port="autocannon localhost:3000" -- node app.js
21```
22
23An even simpler form of this is to use the `--autocannon` flag,
24
25```sh
26clinic doctor --autocannon / -- node app.js
27```
28
29If after taking these steps an unknown categorization continues to occur then we can instead attempt to infer the nature of the performance issue using specialist diagnostic tooling, such
30as `clinic flame`, `clinic bubble` or Node Inspector.
31
32## Next Steps
33
34- First eliminate the possibility of ambient noise
35 - Reduce noise by closing down as many other applications running on the system as possible - especially CPU or Memory intensive applications
36 - Ensure that the `--on-port` flag is being used to trigger load testing instead of initiating load testing independently
37- Use `clinic bubbleprof` to create a diagram of the application's asynchronous flow (see `clinic bubbleprof --help`)
38- Explore the Bubbleprof diagram. Look for long lines and large circles representing persistent delays, then drill down to reveal the lines of code responsible
39 - A common problem is the overuse or misuse of promises. `clinic bubbleprof` will visualize promise activity, make a point of looking out for it in the diagram.
40- Use `clinic flame` to generate a flamegraph
41 - Run `clinic flame --help` to get started
42- Look for "hot" blocks, these are functions that are observed (at a higher relative frequency) to be at the top the stack per CPU sample – in other words, such functions are blocking the event loop
43- For memory analysis use the [`--inspect`](https://nodejs.org/en/docs/inspector) flag with the Chrome Devtools *Memory* tab.
44 - Run `node --inspect <FILENAME>`
45 - Open Chrome and navigate to [chrome://inspect](chrome://inspect)
46 - Under the **Remote Target** heading, there should be a target with the official Node.js icon
47 - Click the `inspect` link for that target – this will connect Chrome Devtools to the Node processes remote debug interface
48 - In Devtools, select the *Memory* tab
49 - Select the *Take heap snapshot* radio box, and then click *Take snapshot*
50 - Put the process under load (in the same way that the process was load tested for Clinic.js)
51 - Click *Profiles* in the left panel, then click *Take snapshot* again
52 - Under the *HEAP SNAPSHOTS* left panel, select the second Snapshot (it will be called *Snapshot 2*)
53 - Locate the dropdown box just above the "Constructor" column (most likely the dropdown box says *Summary*)
54 - Click the dropdown, and select *Comparison* – this compares the before and after snapshots of the heap
55 - Click the *# Delta* and/or *Size Delta* columns to sort by the difference in object counts
56 or object size, categorized by constructor type
57 - Use the interactive trees in the Constructor column to drill down into the specifics
58 - Use the *Retainers* panel to understand the chain of object references
59
60## Reference
61- [Clinic.js Flame](https://clinicjs.org/flame)
62- [Overview of blocking vs non-blocking](https://nodejs.org/en/docs/guides/blocking-vs-non-blocking/)
63- [Concurrency model and Event Loop
64](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop)
65- [Don't Block the Event Loop (or the Worker Pool)](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/)
66- Understanding Flamegraphs and how to use 0x: [Tuning Node.js app performance with autocannon and 0x](https://www.nearform.com/blog/tuning-node-js-app-performance-with-autocannon-and-0x/)
67- [Clinic.js Bubbleprof](https://clinicjs.org/bubbleprof)
68- [Chrome Devtools Docs: Fix Memory Problems](https://developers.google.com/web/tools/chrome-devtools/memory-problems/)
69- [Chrome Devtools Docs: Memory Terminology](https://developers.google.com/web/tools/chrome-devtools/memory-problems/memory-101)
70- [Chrome Devtools Docs: How to record heap snapshots](https://developers.google.com/web/tools/chrome-devtools/memory-problems/heap-snapshots)
71- [Node Docs: Inspector](https://nodejs.org/en/docs/inspector/)
72- **Advanced**: [Core dump analysis tool for Linux: llnode](https://github.com/nodejs/llnode)
73- **Advanced**: [Core dump analysis tool for SmartOS: mdb_v8](https://github.com/joyent/mdb_v8)
74- **Advanced**: [Core dump analysis tool for Linux which wraps SmartOS mdb](https://www.npmjs.com/package/autopsy)