SkillAgentSearch skills...

Heatfiler

A JS profiler and code coverage tool that displays the result in a (live updating) heatmap

Install / Use

/learn @pvdz/Heatfiler
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Heatfiler

JS profiler slash code coverage reporting tool

Summary

Heatfiler allows you to easily run through your code and find the heavy points. Alternatively, you can use it to figure out which parts of your code are unused. It does this, for both cases, with a visueal heatmap which updates live as the code runs. It can either run on the same page (profiler and code) or in two different tabs, communicating through localStorage. There is also support for tracing a nodejs project this way.

It's fairly easy to integrate Heatfiler into an existing web project (unless it uses a module loader of some kind, like requirejs) by modifying the script tags and including Heatfiler. There are some examples in the project to demonstrate this. For nodejs it's even easier, though that requires some kind of webserver to work with.

The initial version was hacked together in about two days. The current version contains some more work. It uses ZeParser2 as the JS parsing and rewriting backend.

Demo

See heatfiler.qfox.nl for a live demo of the profiler.

Alternatively you can visit the github version which is probably more up to date :)

There is an example, you can click here to immediately run it.

I've also added three integration examples. Open one of:

  • http://heatfiler.qfox.nl/dragon/
  • http://heatfiler.qfox.nl/parallax/
  • http://heatfiler.qfox.nl/js1k/

and then open heatfiler in another tab (if not starting, click "Listen" tab and go). The heatmap updates real-time.

How it works

The profiler parses your script, injects "ping" calls into statements and expressions, and runs it. These "pings" will simply count how many times a certain (small) part of the script is executed. These stats are collected and processed. They are represented in the heatmap in a shade of red which signifies how often that part is executed. Red parts mean the script is executed often. To determine this it will check which part was called most often. All other counts are relative to this number. The shade of red is too.

The rewriting occurs with a set of rules that are "safe" and should not change the working of the code (though there might still be a bug for very obscure syntax, please report them if you find any). It should be possible for virtually any code to be rewritten this way. I've tried my best to catch'em'all :)

The code coverage does almost exactly the same thing as the profiler, except, of course, that it only highlights in red those parts which were never executed.

Build

Note that the build directory contains a built file (heatfiler-build.js). This file (should be up to date, but check commits to be sure) already includes zeparser2 and is a single .js resource to include in your projects, or nodejs. It's not minified, but I don't think that is important since this is a debugging tool. If the build is not up to date or you just want to build it yourself you can run bin/build.js from the project root.

UI

Tabs

The first tab, "Run code", allows you to enter code to execute. You can either enter actual JavaScript code there or a bunch of file urls. You can select to run them locally, or have the results stored to localStorage to load in another tab.

When you enter code, it will immediately show you the translated result, though that should not be very important to you. When using files, the translation will also appear below the code when running.

The "Listen" tab is used to start polling localStorage for results.

The "NodeJS" tab is used to poll a nodejs project. It should have Heatfiler integrated (see below) and the output file should be "ajaxable".

The "Result" tab, initially disabled, is where the heatmap will appear once you start running code or listening for results. It will be the most interesting part ;)

Run code

runcode

Select whether you are inputting code or a list of files. There will be a placeholder to get you started. The placeholder looks ugly on firefox :( But only because the spec for placeholder is messed up. Just press the example button.

For code, just enter the JavaScript code. It will be included through a dynamic <script> tag.

For the files, enter each file on its own line;

  • Prefix something with @ to have it eval as regular code instead of file path.
  • Prefix with a + or - to load it and include or exclude it from the stats. All files will be fetched and loaded (dynamic <script> tags) in given order.
  • Without prefix, + is assumed.
  • Prefix # for comments

All prefixes must be first chars. Whitespace is not ignored because I'm lazy.

Heatmap

heatmap

The results tab has a few gimmicks that I'd like to highlight:

  • Live updating heatmap
  • Mouse hover for stats
  • Expressions have truthy, falsy, and type stats
  • Functions show cumulative return value stats and other stats for key statements
  • Switches show case choice stats
  • Browser blocked status spinner
  • Exclude functions from stats
  • Focus on functions
  • File selection tabs
  • Minimap for navigation
  • Options -- Make stats relative to this file or whole project -- Pause refreshing the heatmap -- Enable code coverage mode -- Show line numbers column -- Auto start when refreshing -- Show list of most called functions (in this file) -- Show list of most called statements -- Show some JIT information (tentative)

Heatmap

heatmap

The heatmap will update as the stats are updated. It will continuously poll the localStorage or nodejs file for updates and adjust the heatmap accordingly.

The map might be a bit confusing at first, due to the granularity of the map and the limitations of html/css. Sometimes it might appear as if only a small part of an expression is executed, like foo(bar) will only allow you to highlight foo( for stats. But rest assured, that part does cover the entire foo(bar) call. The reason it is "cut short" is that you could otherwise not hover over bar for it's specific stats (without screwing up other things). I might fix this in some future... More difficult is the wrapper case ({a:x}) where only ( is highlight-able but where I would like it to highlight the entire range up to ).

You can click on the function keyword or the icon left of one to focus on that function only. All stats will be relative to this function. Similarly you can click on to exclude a function from the stats entirely.

The stats you see when hovering over various parts of the code can basically be split in three types:

Statements: Statements that don't start with an expression can only show the run count, since they do not return a value (so no type information).

Expressions: The value of expressions are also shown, either by an accumulated "truthy" or "falsy" value (T/F), or by the "typeof" result. It also includes a special case for NaNs.

Functions: For functions the accumulated T/F is shown for all returns, explicit or implicit. The "types" can also include implicit, for implicit returns. They could be a code smell.

It also shows you how many times certain statement types inside that function were executed, like loops and switches.

Function declarations also display the declaration count as a separate value from the call count. This is because a function might be declared but never invoked (due to hoisting or simply never being called).

Browser blocked spinner

The spinner at the top of the heatmap, shown only when running the code in the same tab as the heatmap, will show you when your code is blocking the browser UI thread (and thus preventing any scrolling or updating the heatmap visually).

It's an old trick.

File selection tabs

files

When running files or listening to a nodejs project you will get tabs in the top-right corner for each file that was profiled.

Each file has their own stats, and using the menu you can toggle showing the highlighting relative to the stats of all files or just to the file you are currently showing.

Minimap

minimap

An awesome feature is a code minimap that will be shown on the right of the heatmap (if the code spans more than the height of the page). This allows you to quickly navigate through your code. Just click and/or drag to the right place.

Pause refreshing

It's possible to pause the updating process by clicking the toggle. Stats are still gathered but the heatmap is not updated to reflect this.

Code coverage mode

codecoverage

Since code coverage is all about code that is or is not ran, a code coverage mode was fairly trivial to implement.

Note that this is an expression based code coverage! It's more thorough than statement based coverage, but less thorough than branch based coverage.

When this mode is active, red parts of the code have not been executed so far (their count will be 0).

Auto start

Sometimes you'll be busy on a project and just want to see the results as you go along.

To make this refresh process a bit easier you can toggle "auto start mode", which will immediately open the heatmap with the current settings when you refresh.

Function list

View on GitHub
GitHub Stars36
CategoryDevelopment
Updated16d ago
Forks4

Languages

JavaScript

Security Score

75/100

Audited on Mar 16, 2026

No findings