Skip to content

What I’d like to Know about JavaScript Programs

October 31, 2011

The final goal of my thesis is to find ways make programs written in dynamic programming languages (like JavaScript) run faster. One way to do this is to exploit regularities in the behavior of the said programs. Dynamic languages appear to make it possible to redefine (almost) everything while a program is running. Programmers, can, for example, redefine global variables (including function bindings), add and remove properties to objects, or even call the (in)famous eval function to redefine the value of local variables. This makes analysis and optimization of such programs difficult.

It makes sense to think however, that the dynamic features of JavaScript are not used in an unrestricted way. Programs are implementations of algorithms. They manipulate structured data in a way that makes sense to programmers. As such, the programs themselves should exhibit some predictable, regular structure in their behavior. An optimizing Just-In-Time (JIT) compiler can exploit this in multiple ways, such as predicting what a program will do next based on past behavior, and restricting the generality of the code it generates based on the extend of the dynamic behaviors exhibited by programs.

At the beginning of my Ph.D., I worked with Marc Feeley on instrumenting the WebKit JavaScript interpreter (JavaScriptCore) to gather some information about the dynamic behavior of programs. The goal was to eventually use this information to better guide our attempts at optimizing JavaScript code. This effort showed promising results, but was unfortunately abandoned mid-way because of technical difficulties: JavaScriptCore is very hard to instrument thoroughly. There are many things we simply couldn’t do. There was much data we didn’t have access to.

Thanks to a combined effort by Marc Feeley and Bruno Dufour, we now have a system that allows us to re-write JavaScript souce code directly in order to instrument it. Combined with a web proxy system, we believe that we may finally be able to get the information we want. This tool will (hopefully) be working reasonably soon, and so I have decided to begin gathering a list of metrics to profile in real-world JavaScript applications. These will be useful in guiding my optimization efforts.

I would like to know:

  1. What is the distribution of the length (in lines of code) of JS functions?
  2. How often are program and library functions executed?
    1. What proportion of functions are never executed?
    2. What proportion are executed only once?
    3. More than K times (with K ~ 10 to 100)?
  3. What proportion of functions have loops?
    1. What is the average loop nesting depth, for functions that have loops?
    2. What is the distribution of the number of loop iterations?
  4. What types are low-level operations usually applied to?
    1. What is the percentage of multiplications/additions on int64 int32, int30, uint32, floating-point values?
    2. How often is the addition operator used for arithmetic vs. string concatenation?
    3. How often are bitwise operators applied to non-integer values?
  5. The percentage of branches always going the same way.
  6. How stable are the types of variables?
    1. How stable are function arguments, function return types?
    2. How stable are function return types, for a given fixed input type string?
    3. How stable are local variable types? What if argument types are fixed?
    4. How stable are global variable and closure variable types?
    5. How often do global variable types change?
    6. How often are global functions redefined (if ever?)
  7. How are objects typically used?
    1. How many objects are allocated per function call, on average?
    2. How many fields do objects end up having?
    3. What proportion of allocated objects do not escape their allocating function?
    4. What proportion property accesses use dynamically generated string as keys?
    5. The frequencies of object property read/write/deletes per allocated object.
  8. How is eval typically used?
    1. The frequency of eval calls.
    2. The frequency of eval calls redefining local/global variables.
I should specify that when I say “type” I don’t just mean what would be returned by the JavaScript “typeof” operator. I mean the low-level type (number, array, object, function, string, boolean, null, undefined, etc.) as well as other information we may find useful in an optimizing compiler, such as whether a given value is a specific constant, whether numbers are integers, floating-point, and information about the types of properties, in the case of objects. The goal is to capture information about the nature of values which may be useful to an optimizing compiler.
Leave a Comment

Leave a comment