2008-04-17

JavaScript Reminder - Always Declare Your Variables

Having been developing in Java for some time, the practice of declaring variables (e.g. writing var n = 0; instead of just n = 0; for the first use of the variable n) comes quite naturally. Naturally, that is, except for when initialising a for-loop. Somehow, after getting into trouble with the browser a few times for writing code like for (int i = 0; i < n; i++) out of habit, i gradually fell into writing just for (i = 0; i < n; i++) instead, omitting the int (or var) altogether. After spending quite an amount of time looking at a rather nasty bug earlier, i would just like to remind everyone the importance of the var.

This is a fragment of what i wrote:

function outerFunction()
{
    for (i = 0; someCondition; i++)
    {
        // Do Something
    }
}

function MyObject()
{
    var object = new Object();
    
    object.innerFunction = function()
    {
        // Do Something
        
        for (i = 0; i < n; i++)
        {
            outerFunction();
            
            // Do Something
        }
    };
    
    return object;
}


Upon calling MyObject().innerFunction();, my browser froze, and after a while, came back with a suggestion to terminate the script. Peppering the code with plenty of alerts led to the discovery that the value of i in the inner function's loop would "reset" back to a smaller value after the call to the outer function, and hence never reaching the value of n.

More time spent staring at the code later, i realised that the problem, and hence the solution, was just staring me in the face:

function outerFunction()
{
    for (var i = 0; someCondition; i++)
    {
        // Do Something
    }
}

function MyObject()
{
    var object = new Object();
    
    object.innerFunction = function()
    {
        // Do Something
        
        for (var i = 0; i < n; i++)
        {
            outerFunction();
            
            // Do Something
        }
    };
    
    return object;
}


Remember your vars!

2008-04-10

JavaScript - Absolute Position of an Element

i was in the midst of some HTML coding when i needed to be able to find out the absolute position of an element using JavaScript and HTML DOM. After looking through some online and offline references, and trying out some possibilities, i found that there is no element method or property that would give me the values that i needed. (The element.style.top and element.style.left attributes will only return what has been set beforehand, either through script or CSS, and even so, will only be useful for this purpose if the element.style.position attribute has been set to absolute.)

After some searching on the net, i came across a great piece of code (from QuirksMode.org) that does exactly what i needed:

function findPos(obj)
{
    var curleft = curtop = 0;
    
    if (obj.offsetParent)
    {
        do
        {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        }
        while (obj = obj.offsetParent);
    }
    return [curleft, curtop];
}


The site where the code snippet was taken from - QuirksMode.org - provides detailed explanations on why it works that way. To use the function above to, for example, find the absolute position of an element called div, you would just have to call

var pos = findPos(div);

The returned variable, pos, would then be an array whose first element (pos[0]) is the number of pixels between the div element and the left edge of the page, and second variable (pos[1]) is the number of pixels from the top of the page.

2008-04-02

Tuning Java Garbage Collection

The Java virtual machine automatically handles garbage collection of objects that are no longer referenced, and you would normally not have to change or tweak the default garbage collection settings. That is, unless you are dealing with a long-running application (e.g. a web application), or if performance is of great importance. For those cases, i have found a few basic steps which provide a good starting point in tweaking those settings.

In order to tune the garbage collector, you would first have to know how it is currently behaving and performing. This can be achieved enabling detailed garbage collection logging, and then monitoring the log file. You can get a useful garbage collection log output by appending the options

-verbose:gc -Xloggc:gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails

to the java command when starting up your Java application. So your application start up command would end up looking something like:

java -classpath some/path:some_jarfile.jar -verbose:gc -Xloggc:gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails your.main.Application

After your application has run for some time, you would see lines like these in the garbage collection log file (gc.log in the example):

3779.257: [GC 3779.257: [DefNew: 308160K->9280K(308160K), 0.3048983 secs] 700726K->425258K(2087872K), 0.3050826 secs]

and

3788.365: [Full GC 3788.366: [Tenured: 415978K->237898K(1779712K), 3.5419520 secs] 689157K->237898K(2087872K), [Perm : 81663K->81663K(81664K)], 3.5421538 secs]

A very basic explanation of those two lines are as follows:

Line 1: A minor collection took place at time T + 3779.259 seconds (3779.259 seconds after the application was started up). Memory usage in the young space was brought down from 308,160 KB to 9,280 KB while on the whole, 275,468 KB was recovered from the Java heap (from 700,726 KB to 425,258 KB). The collection took 0.3050826 seconds.

Line 2: A full collection took place at time T + 3788.365 seconds. 178,080 KB was recovered from the tenured space, 451,259 KB from the Java heap overall. The collection took 3.5421538 seconds.

Now, with that logging in place, it is possible to spot a few basic performance-related issues with memory and garbage collection.

Memory Leaks

If the figure representing the total used memory after collection (e.g. 425,258 KB in the first case) continuously increases for a relatively long amount of time, a memory leak situation may be occurring. Profiling the application for a period of time and monitoring objects which increase endlessly in count and size could help tremendously in hunting down the source of the leak. From my personal experience, memory leaks are most commonly caused by continuously adding objects to a static or long living collection (e.g. a cache) and neglecting to remove them.

Barely Sufficient Heap Size

If the figure representing the total used memory after collection (e.g. 425,258 KB in the first case) is close to the total available heap size (e.g. 2,087,872 KB in the first case) before a significant amount of time has even passed, the set heap size may be insufficient and may need to be increased. If heap usage continues to increase with time, trashing may eventually take place (i.e. the application spends almost all its time doing only garbage collection), with the occasional java.lang.OutOfMemoryError causing havoc. Even in the case where memory usage is already stable, application performance may still benefit from increasing the heap size, as it would then perform garbage collection at less regular intervals.

Young Generation Guarantee

Typically, most of the collections occurring should by minor collections (first line in example above). If full collections (second line) happen for the majority of the time, memory usage due to long living objects may too high and the young generation guarantee can never be met. One possible solution for this would be to set the size of the new space to a smaller number (thus allowing more space in the tenured generation). This is likely to happen in applications which rely heavily on caching (for performance, somewhat ironically), and the symptoms can be easily spotted from the garbage collection logs. A simple tweak in the new size setting usually results in significant performance improvements.

Garbage Collection Strategy

Depending on factors such as the physical configuration of your server (e.g. number of processors), the type of application (e.g. online transaction or batch processing), and the memory usage pattern (e.g. heavy caching), it may even be worthwhile to explore alternative garbage collection strategies. In one of my previous projects, an online transaction application running on a server with multiple processors, we experienced a significant performance boost by switching from the default strategy to the concurrent low pause collector with parallel minor collections.

Reference: http://java.sun.com/docs/hotspot/gc1.4.2/