Yellow Lab Tools

Untangling and counting the spaghettis...
Tested url:   {{phantomasResults.url}}
New test

Error: {{phantomasResults.error}}

Phantomas timed out
Phantomas config error
Phantomas failed to load page
Phantomas internal error
Javascript execution tree error
JSON undefined error

Summary

{{notations.domComplexity}}
DOM complexity
DOM elements count
{{phantomasResults.metrics.DOMelementsCount}}

A high number of DOM elements means a lot of work for the browser to render the page.

It also slows down Javascript DOM queries, as there are more elements to search through.

DOM max depth
{{phantomasResults.metrics.DOMelementMaxDepth}}

A deep DOM makes difficult the CSS matching with DOM elements.

It also slows down Javascript modifications to the DOM because dimensions calculations bubble up. Same thing for Javascript events.

Number of iframes
{{phantomasResults.metrics.iframesCount}}

iFrames are the most complex HTML elements. They are pages just like the main page and the browser needs to create a new page context, wich has a cost.

IDs duplicated
{{phantomasResults.metrics.DOMidDuplicated}}

IDs of HTML elements must be document-wide unique. This can cause problems with getElementById returning the wrong element.

{{notations.domManipulations}}
DOM read and write
DOM inserts
{{phantomasResults.metrics.DOMinserts}}

Working with the DOM in Javascript triggers layout calculations and slows down the page.

Try, as much as possible, to have an HTML page fully generated by the server instead of making changes with JS.

DOM queries
{{phantomasResults.metrics.DOMqueries}}

DOM queries are like looking in a large catalog of items. Even if the browsers made progress on the performances of a query, many websites make hundreds of them.

Try to reduce the number of queries by refactoring your Javascript code.

Avoid also to have a read query between two write queries. To reduce the number repaints and optimize performances, browsers buffer the DOM writing operations. But each time a DOM reading is asked, the browser needs to empty the buffer. This can be particularly slow inside a loop.

JS interactions time
{{totalJSTime}} ms

Please note that the tool is not accurate. The time indicated here is generally 3 or 4 times slower than on modern browsers.

Some DOM manipulations can be very slow. For example, searching with a complex selector, making big changes to the DOM, animating an element, inserting an iframe, ...

{{notations.duplicatedDomQueries}}
Duplicated DOM queries
Avoidable queries
{{duplicatedQueriesCountAll}}

This is the number of queries that could be avoided by removing all duplicated queries.

Simply save the result of a query in a variable. Ok it is not always simple, especially with third-party scripts, but at least do it with your own code.

{{notations.eventsBound}}
Events bound
Events bound
{{phantomasResults.metrics.eventsBound}}

Binding too many events has a cost.

It can be avoided by using "event delegation". Instead of binding events on each element one by one, events delegation binds them on the top level document element and uses the bubbling principle.

{{notations.jsBadPractices}}
Bad Javascript
Javascript errors
{{phantomasResults.metrics.jsErrors}}

Just to let you know there are some errors on the page.

Please note that some errors only occur in the PhantomJS browser, so you might need to double check on other browsers.

eval calls
{{phantomasResults.metrics.evalCalls}}

The 'eval' function is slow and a bad coding practice. Try to get rid of it.

document.write calls
{{phantomasResults.metrics.documentWriteCalls}}

They slow down the page construction, especially if they are used to insert scripts in the page. Remove them ASAP.

If you cannot remove them because they come from a third-party script (such as ads), have a look at PostScribe.

Console messages
{{phantomasResults.metrics.consoleMessages}}

Try to keep your console clean when in production. Debugging is good for development only.

Writing in the console has a cost, especially when dumping large object variables.

There is also a problem with Internet Explorer 8, not knowing the console object.

Global variables
{{phantomasResults.metrics.globalVariables}}

It is a bad practice because they clutter up the global namespace. If two scripts use the same variable name in the global scope, it can cause conflicts and it is generally hard to debug.

Global variables also take a (very) little bit longer to access than local variables.

{{notations.jQueryLoading}}
jQuery version
jQuery version
{{phantomasResults.metrics.jQueryVersion}}

Current latest version of jQuery is 1.11 or 2.1

Each new version of jQuery optimizes performances. Do not keep an old version of jQuery. Updating can break a few things, but it is generally quite easy to fix them up, so don't hesitate.

{{phantomasResults.metrics.jQueryDifferentVersions}} versions loaded
{{version}} &

{{notations.cssComplexity}}
CSS complexity
Rules count
{{phantomasResults.metrics.cssRules}}

Having a huge number of CSS rules hurts performances. If the number of CSS rules is higher than the number of DOM elements, there is clearly a problem.

The problem generally occurs when all the pages of a website load all the CSS, concatenated in a single stylesheet. Solution is to create one main CSS file with global rules and one custom files per page.

Complex selectors
{{phantomasResults.metrics.cssComplexSelectors}}

{{notations.badCss}}
Bad CSS
Duplicated selectors
{{phantomasResults.metrics.cssDuplicatedSelectors}}

Empty rules
{{phantomasResults.metrics.cssEmptyRules}}

CSS expressions
{{phantomasResults.metrics.cssExpressions}}

Uses of !important
{{phantomasResults.metrics.cssImportants}}

Old IE fixes
{{phantomasResults.metrics.cssOldIEFixes}}

Old prefixes
{{phantomasResults.metrics.cssOldPropertyPrefixes}}

Universal selectors
{{phantomasResults.metrics.cssUniversalSelectors}}

Redundant body selectors
{{phantomasResults.metrics.cssRedundantBodySelectors}}

{{notations.requests}}
Requests number
Total requests
{{phantomasResults.metrics.requests}}

Documents
{{phantomasResults.metrics.htmlCount}}
Scripts
{{phantomasResults.metrics.jsCount}}
Stylesheets
{{phantomasResults.metrics.cssCount}}
Images
{{phantomasResults.metrics.imageCount}}
Fonts
{{phantomasResults.metrics.webfontCount}}
Videos
{{phantomasResults.metrics.videoCount}}
JSON
{{phantomasResults.metrics.jsonCount}}
Other
{{phantomasResults.metrics.otherCount}}
{{notations.network}}
Network
404 not found
{{phantomasResults.metrics.notFound}}

Connections closed
{{phantomasResults.metrics.closedConnections}}

Duplicated requests
{{phantomasResults.metrics.multipleRequests}}

Caching disabled
{{phantomasResults.metrics.cachingDisabled}}

Caching not specified
{{phantomasResults.metrics.cachingNotSpecified}}

Caching too short
{{phantomasResults.metrics.cachingTooShort}}

Different domains
{{phantomasResults.metrics.domains}}

Javascript Timeline

This graph gives a quick view of when the Javascript interactions with the DOM occur during the loading of the page.

Timestamp: {{$index * timelineIntervalDuration | number: 0}} ms
0 ms
{{endTime | number: 0}} ms
DOM creation
DOM interactive
DOM content loaded event
Page completion
Page is complete
Executing Javascript and DOM queries here is a bad practice and slows down the DOM construction.
Some frameworks do things here, but it's not reliable and should be avoided.
Also known as "document ready". This is where you should execute top-priority scripts, like binding action buttons or launch a video player.
Here you can execute mid-priority tasks. Loading a script with createElement('script') is one way to do so.
The page is considered loaded, it's time for low priority things : trackers, social plugins, easter egg...

Javascript Profiler

The table below shows the interactions between Javascript and the DOM. It is usefull to understand what's going on when the page loads.
The tool is slower than a real browser, so durations are a little exagerated.

Filter by
ms
Type
Params
Duration
Timestamp
{{$index}}
{{node.data.type}}
{{node.data.callDetails.arguments[0]}} : {{node.data.callDetails.arguments[1]}} : {{node.data.callDetails.arguments[2]}} : {{node.data.callDetails.arguments[3]}}

Called on DOM element

{{node.data.callDetails.context.domElement}}

Called on 1 jQuery element

{{node.data.callDetails.context.firstElementPath}}

Called on {{node.data.callDetails.context.length}} jQuery elements

The .bind() method attaches the event listener to each jQuery element one by one. Using the .on() method is preferred if available (from v1.7).

First one is: {{node.data.callDetails.context.firstElementPath}}

Backtrace

{{trace.fnName || '(anonymous)'}}
can't find any backtrace :/

Sub processes

Type
Params
Duration
{{$index}}
{{node.data.type}}
{{node.data.callDetails.arguments[0]}} : {{node.data.callDetails.arguments[1]}} : {{node.data.callDetails.arguments[2]}} : {{node.data.callDetails.arguments[3]}}
{{node.data.time}} ms
{{node.data.time}} ms
{{node.data.timestamp | number: 0}}

Metrics from Phantomas report

Phantomas is a web performance metrics collector. You can find here the (almost) entire list of metrics from Phantomas.

{{moduleName}}

{{metricName}}: {{phantomasResults.metrics[metricName] | number: 0}} {{metric.unit}}
{{metric.desc}} (unreliable)
Show offenders
Hide offenders
  • {{offender}}