Profiling


Profiling

Concerns
-
Tracking Memory Leaks
-
Improve Application Performance
Profiling

Begin with an Object
object [ key ] = value ;
String only
Any variable type
Profiling

The Object Graph

Profiling

An Object's size
-
Shallow
Two sizes
-
The Object itself
-
Usually a small constant footprint
-
Retained
-
The sum of shallow size of all decendents
Profiling

An Object's retaining tree

Profiling

What is considered as Garbage?
All variables which cannot be reached from the root node

Profiling

Garbage Collection
-
Find all garbage
-
Return memory used by garbage variables to the system

Mark & Sweep
Profiling

The cost of allocating memory
-
Scoops memory from the "young" memory pool
-
This is cheap & fast until this pool runs out of memory
- Runtime then forced to perform a garbage collection
which can lead to clunky performance...
Every call to new
Be careful with creating new objects.
-
Mind new objects creation patterns
-
Mind how long you hold on to them
Profiling

Managed Memory - Summary
Allocations are cheap & fast until
the "young" pool runs out of memory
All variables are part of the object graph
Objects have two sizes
-
Shallow (self)
-
Retained (self+descendents)
All variables that cannot be reached from the root are garbage
Runtime is then forced to perform a garbage collection
which can lead to clunky performance...
Profiling

Memory Profiling Tools

Profiling

Comercial Tools


Free during development for debugging
License is required to run in production
Profiling

Comercial Tools
Free open source PM2 package
License is required for dashboards


Profiling

Comercial Tools
by Rising stack
Has a free tier




Profiling

Time Api requests
Available as built-in or 3rd-party middleware




Profiling

Bash command tools
- Linux perf events
- node --prof flag
- Apache Benchmark - ab
- Dtrace
- Flame Graphs
- Joyent mdb
- gcore - generates core dumps in production
Watch this for further information
Runtime Performance Workflow
- Sample stack traces via perf
- Visualize code distribution with CPU flame graphs
- Identify performance issues...
Profiling

Use Chrome Devtools
All tabs available including: Sources / Timeline / Profiling

A debugger interface for Node.js applications
uses the Blink Developer Tools (formerly WebKit Web Inspector). sponsored by IBM StrongLoop.
Profiling

Use Chrome Devtools
All tabs available including: Sources / Timeline / Profiling
Runs Node.js programs inside Chrome DevTools
(using Electron to blend Node.js and Chromium features).
Read this blog post
Comparison to node-inspector


Profiling

Devtools profiling workflow
- Make assumptions regarding suspicious actions in your code that may be causing memory leaks
-
Inspect and validate those suspicions in the memory timeline tab
-
Capture two or more Heap snapshots
-
The snapshots capture objects graph
-
Don’t capture scalar values in the object graph
- Compare two or more snapshots to find leaks
-
Use both Summery & Comparison views of the profiles tab
Profiling

Devtools profiling tips
-
Ignore parentheses
-
Ignore dimmed
-
Garbage is collected before each snapshot is taken
-
Test using incognito mode
to avoid extensions code included in your snapshots... -
Focus on the signal
Profiling

Closures memory leaks example
Help the GC out by assigning null to closure variables.
let closureVar = {};
doWork(function callback() {
let data = closureVar.usefulData;
// Do a bunch of work...
// Do a bunch of work...
// Do a bunch of work...
data = null;
});
Profiling

What is wrong with this code?
let theThing = null;
let replaceThing = function () {
let originalThing = theThing;
let unused = function () {
if (originalThing)
console.log("hi");
};
theThing = {
longStr: new Array(1000000).join('*'),
someMethod: function () {
console.log('someMessage...');
}
};
};
setInterval(replaceThing, 1000);
Profiling

let theThing = null;
let replaceThing = function () {
let originalThing = theThing;
// Define a closure that references originalThing but doesn't ever actually
// get called. But because this closure exists, originalThing will be in the
// lexical environment for all closures defined in replaceThing, instead of
// being optimized out of it. If you remove this function, there is no leak.
let unused = function () {
if (originalThing)
console.log("hi");
};
theThing = {
longStr: new Array(1000000).join('*'),
// While originalThing is theoretically accessible by this function, it
// obviously doesn't use it. But because originalThing is part of the
// lexical environment, someMethod will hold a reference to originalThing,
// and so even though we are replacing theThing with something that has no
// effective way to reference the old value of theThing, the old value
// will never get cleaned up!
someMethod: function () {
console.log('someMessage...');
}
};
// If you add `originalThing = null` here, there is no leak.
};
setInterval(replaceThing, 1000);
Profiling JavaScript Applications
By Yariv Gilad
Profiling JavaScript Applications
- 1,633