SkillAgentSearch skills...

Kojak

A Simple JavaScript Performance Profiler

Install / Use

/learn @theironcook/Kojak
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

##Kojak: A simple JavaScript performance profiler Build Status

####What is Kojak? Kojak is a simple utility that can help you figure out which of your JavaScript functions are running too slow. It tracks when your functions are called, how often they are called, how much time they are taking, how the functions were called. It can also track your ajax calls and help figure out how fast they are. (Kojak was a <a href="http://en.wikipedia.org/wiki/Kojak">tv show detective</a>)

####Why Kojak? I've found that Chrome's developer tools or Firebug have too much noise to make much sense of my own code. My current project is a 200k line single page app. I needed a tool that would remove all of the noise and clutter. I wanted a tool that was easy to configure and didn't force me to inject hooks all over my code. Kojak helps you focus on the performance of your own code and eliminate the clutter. It's helped me / my project to significantly speed up our JavaScript code. Hopefully it can help you and your projects.

####Dependencies The core of Kojak has no external dependencies. I've worked hard to avoid using any other libraries so that the tool is light weight and easy to use. You need a modern browser such as Chrome, Firefox or IE 10+ (It works OK on IE 9). If you want to profile ajax network requests you will need to include jQuery.

<br> ####How to use it (the short version) To use Kojak copy/download the Kojak.min.js file. Include it in the browser code you want to profile. You can include it with a normal `script` tag or you can also just copy and paste the contents of the Kojak.min.js file directly into a running browser console. You can actually profile code in any web site as long as you know what the code root pakage names are.

Kojak expects that your code is accessible via the window object. A simple application might be assembled like this:

var myProject = {models: {}, views: {}, controllers: {}, utils: {}};
myProject.models.ModelA = function(){};
myProject.models.ModelA.prototype.modelAFunc = function(){};
myProject.utils.sharedUsefulFunction = function(){};

Kojak expects that the code lives somewhere under the window object. In the example above, the code lives under window.myProject.

If you're using something like requireJS that hides your code, you will probably need to expose your modules to Kojak with a quick shim. Here is an example of how to hook up requireJS. You can copy the same pattern with almost any module style code.

<br> To get an idea of how Kojak works type you can quickly test this in a browser console: ```` // First copy this into the browser console: var myProject = {models: {}, views: {}, controllers: {}, utils: {}}; myProject.models.ModelA = function(){}; myProject.models.ModelA.prototype.modelAFunc = function(){}; myProject.utils.sharedUsefulFunction = function(){};

// Copy the Kojak.min.js content into the browser console: // https://github.com/theironcook/Kojak/blob/master/Kojak.min.js

// this tells Kojak what code it should care about kConfig.setIncludedPakages(['myProject']);

// this will root recursively through all the code, starting with the included packages and wrap every // single function it finds to keep track of all of the function's runtime information kInst.instrument();

// See which functions have been instrumented in your application kRep.instrumentedCode({verbose: true});

// Now you would normally do something with your application that does not include a full page refresh // Run this as a simple example myProject.utils.sharedUsefulFunction(); (new myProject.models.ModelA()).modelAFunc();

// Now see the function performance stats.
// This only includes the instrumented functions. // In this example, you can see that the functions were both called once kRep.funcPerf({sortBy: 'CallCount'});


<br>
I have  added some examples of how to use Kojak with different frameworks using the <a href="https://github.com/tastejs/todomvc">Todo MVC app</a> from Addy Osmani and company.

<a href="https://github.com/theironcook/Kojak/wiki/Using-Kojak-to-Profile-the-Backbone-MVC-App">Backbone TODO MVC Example</a>

<a href="https://github.com/theironcook/Kojak/tree/master/example/TodoMVC_Angular">Angular TODO MVC Example</a>. (check the index.html file)

I spent a few hours with the Ember Todo MVC example but could not get it working with Kojak.  Ember looks like a pretty cool framework
(I've spent a total of 3 hours with it) but it appears to be a bit too clever for Kojak to follow.  With Ember, many functions do not exist under the prototype until the
prototype's function is actually invoked.  It's unrealistic to execute the entire code base so it exists to be able to instrument it.
Maybe some Ember expert out there can show me how it's done :)

Other examples might follow.


Kojak has a lot of other features that I'll explain later, but first I need to explain how Kojak makes sense of JavaScript.

<br>
####Supported code formats

<i>If this section is confusing I would recommend reading <a href="http://www.amazon.com/Secrets-JavaScript-Ninja-John-Resig/dp/193398869X/ref=sr_1_1?s=books&ie=UTF8&qid=1382038307&sr=1-1&keywords=secrets+of+the+javascript+ninja">chapters 1-6</a>.</i>

Kojak recognizes 3 types of data structures in your code
* `Pakage`
* `Clazz`
* `function`

A `Pakage` is anything that might contain your code. A `Pakage` might be a Plain Old JavaScript Object (POJO) that looks like {}.
A `Pakage` might also be a `Clazz` that contains other `Clazzes` or `Pakages`.
In the example below, myProject, myProject.models, myProject.views, myProject.models.ModelA and myProject.models.ModelA.NestedModelB are all considered Pakages:

var myProject = {models: {}, views: {}}; myProject.models.ModelA = function(){}; myProject.models.ModelA.NestedModelB = function(){};


A `Clazz` is a function that is expected to be used with the `new` operator.  `Clazzes` are expected to be named starting
with an upper case character. In the previous example ModelA and NestedModelB are both `Clazzes`.

A `function` is just a normal JavaScript function that Kojak does not think is a `Clazz` because it is not referenced with a string that starts
with an upper case character.  Kojak looks for functions in `Pakages`, `Clazzes` or under the `Clazz`.`prototype` object.

For example, Kojak will profile the functions `packageFunction`, `classLevelFunction` and the `prototypeLevelFunction`:

myProject.packageFunction = function(){}; myProject.models.ModelA = function(){}; myProject.models.ModelA.classLevelFunction = function(){}; myProject.models.ModelA.prototype.prototypeLevelFunction = function(){};


It's important for Kojak to understand when a function will be invoked with the `new` operator and to avoid wrapping
those type of functions directly.  If Kojak finds <b>any</b> reference to a function that starts with an upper case it will
assume the function is a `Clazz`.

The example below shows this:

myProject.models.ModelA = function(){}; myProject.someCodePackage = { refToModelA: myProject.models.ModelA };


In the example above, ModelA is also referenced with the name refToModelA.  Kojak understands that ModelA and refToModelA both
reference the same function and that one of those references looks like a Clazz.  In that situation, Kojak will assume
all references should behave as a Clazz.  If Kojak accidentally wraps a function and the function is invoked with the
`new` operator Kojak will throw a runtime exception with a message explaining which function was instrumented incorrectly
as a function instead of a Clazz. You can either rename the Clazz reference to an uppercase, create a dummy duplicate reference
to the Clazz that starts with an upper case letter or you can tell Kojak to ignore that Clazz/function using kConfig.setExcludedPaths.

<br>
####How to use it (the long version)
Kojak needs to be told what code it is supposed to profile.  You tell Kojak via the command:
````kConfig.setIncludedPakages(['packageA', 'packageB'])````

Kojak will use these package names as entry points to find all of the code that you probably care about.

You can also tell Kojak to exclude functions or packages with this command:
```` kConfig.setExcludedPaths(['packageA.SomeClass.funcA', 'packageA.SomeClass.funcB']); ````

Kojak will then ignore funcA and funcB.  The excluded paths can be fully qualified function paths or namespaces etc.

There are several other options in `kConfig` that are discussed in a later section.  All options set with `kConfig` are persisted
automatically in the browser's local storage.  So, the next time you refresh a page etc. your Kojak options are saved.

<br>
After you've told Kojak what it should care about and what to exclude you need to run this command:
```` kInst.instrument(); ````

The `instrument` function will locate every single `Pakage`, `Clazz` and `function` that can be found recursively through
what you specified in the kConfig. Kojak will inject a `_kPath` string in each `Pakage` and `Clazz` that is the fully qualified
path to the `Package` or `Clazz` so that they can be self aware of where they live.

The `instrument` function replaces each `function` it finds with a wrapper function.  The wrapper function helps Kojak to
track everything that happens with that function. The new wrapper function contains a `_kFProfile` property.  The `_kProfile`
property keeps track of all of the information of what is a happening with the function.

You can check which functions have been instrumented with this command:
```` kRep.instrumentedCode(); ````

If you want more details you can run this command:
```` kRep.instrumentedCode({verbose: true}); ```

<br>
After you have told Kojak to instrument your code y
View on GitHub
GitHub Stars186
CategoryDevelopment
Updated5mo ago
Forks17

Languages

JavaScript

Security Score

92/100

Audited on Oct 13, 2025

No findings