Home

C@MBIO!

Posted on February 11th, 2008 in Cuba, The Art of Computer Programming, Human Rights by Jorge Luis

Scary Code

Posted on February 6th, 2008 in The Art of Computer Programming by Jorge Luis

unixrulz: Nothing more scary than a sysadm who starts programming.

javadude: lol. I know. That’s how we got perl!

unixrulz: rotfl!

Write Once. Socialize Everywhere.

Posted on October 31st, 2007 in The Art of Computer Programming by Jorge Luis

Looks like Google intends to become the Java of the web social networking space. It plans to release a generic API for building applications that run on social networking sites, sort of a generic Facebook API. OpenSocial would allow developers to write their social applications once and deploy them on various social-networking platforms supporting the API.

An Inconvenient Turf

Posted on October 31st, 2007 in The Art of Computer Programming by Jorge Luis

Predicting Java on OS X is now akin to predicting the weather. Tropical Storm Leopard was expected to be a 6 on the Java scale but actually turned out to be barely a 5. Experts at the National Office for Write-Once-Run-Everywhere Computing predict an additional Java 6 storm over the next eleven months. In the meantime, Java developers plan to relocate from what’s become a rather inconvenient turf. Sports at 11.

Code Smells

Posted on June 14th, 2007 in The Art of Computer Programming by Jorge Luis

Programming is like farting.  Everyone likes his own brand.

Primitives vs. Autoboxing Speed Test

Posted on May 27th, 2007 in The Art of Computer Programming by Jorge Luis

What executes faster, a calculation involving unwrapped primitives or one that uses autoboxed values? The answer is not as straight-forward as you might expect.

A quick review.

Autoboxing is the automatic wrapping of primitive values into their object-oriented class wrappers, a convenience feature introduced with Java 5. So, whereas before Java 5, you’d have to write code such as this
Double pi = new Double(3.14);
with autoboxing, the wrapping of a double primitive into its wrapper class (right-hand side) is done for you, i.e.,
Double pi = 3.14;
is equivalent to the above expression.

However, in this expression
double pi = 3.14;
the right hand side remains a primitive double.

Autounboxing is also provided, converting a wrapped value into its primitive form.
double pi = new Double(3.14);
A hypothesis

Since autoboxed expressions imply the creation of an object behind the scenes, you might expect that the overhead of object creation would make them execute more slowly than expressions involving primitive values only. In fact, chapter 1 of Java 2 v5.0 Tiger New Features warns that abusing the autoboxing feature can lead to performance degradation. A simple unit test should demonstrate this expectation.

We will race two implementations of the hypotenuse formula, one implemented with primitive doubles, the other with autoboxed doubles:

package com.jluix.lab.unit.learning.autoboxing;

public class AutoboxDouble
    {
    public double hypotenusePrimitive()
        {
        return Math.sqrt(this.a * this.a + this.b * this.b);
        }

    public Double hypotenuseBoxed()
        {
        return Math.sqrt(this.aBoxed * this.aBoxed + this.bBoxed * this.bBoxed);
        }

    public AutoboxDouble(double a, double b)
        {
        this.a = a;
        this.b = b;
        this.aBoxed = a;
        this.bBoxed = b;
        }

    private double a;
    private double b;
    private Double aBoxed;
    private Double bBoxed;
    }

The signature for Math.sqrt is public double java.lang.Math.sqrt(double value). It takes and returns a primitive double. That means hypotenuseBoxed involves both autounboxing and autoboxing.

The expression

this.aBoxed*this.aBoxed + this.bBoxed*this.bBoxed

has to evaluate to a primitive double. So the wrapped Double aBoxed and Double aBoxed are coverted to their primitive forms. Furthermore, since hypotenuseBoxed() returns Double, the primitive value returned by

return Math.sqrt(this.aBoxed*this.aBoxed + this.bBoxed*this.bBoxed);

is autoboxed into its wrapper form. If all goes well, this should turn out to be a pretty inefficient implementation of the hypotenuse formula.

double hypotenuseUnboxed() involves nothing but simple primitive doubles and does not carry any object-creation overhead, theoretically making it faster than its autoboxing counterpart.

Off to the races!

The following unit test executes both hypotenuse calculations and compares their execution times, asserting that the primitive calculation should run faster.

package com.jluix.lab.unit.learning.autoboxing;

import junit.framework.TestCase;

/**
 * Demonstrates autoboxing and autounboxing doubles.
 * Based on discussion in ch 1 of Java 2 v5.0 Tiger New Features, by Herber Schildt
 */
public class TestAutoboxDouble extends TestCase
    {
    /**
     * Executes autoboxed/autounboxed and primitive-only calculations and compares their execution times.
     */
    public void testPrimitivesFasterThanAutoboxedWrappers()
        {
        long boxedTime     = runBoxed();
        long primitiveTime = runPrimitive();
        assertRunTime(boxedTime, primitiveTime);
        }

    /**
     * Executes hypotenuse implemntation that involves autoboxing and autounboxing the triangle sides.
     * @return execution time
     */
    private long runBoxed()
        {
        long startBoxed = System.nanoTime();
        this.autoboxDouble.hypotenuseBoxed();
        long boxedTime = System.nanoTime() - startBoxed;
        return boxedTime;
        }

    /**
     * Executes hypotenuse implementation that involves primitive double triangle sides.
     * @return execution time
     */
    private long runPrimitive()
        {
        long startPrimitive = System.nanoTime();
        this.autoboxDouble.hypotenusePrimitive();
        long primitiveTime = System.nanoTime() - startPrimitive;
        return primitiveTime;
        }

    /**
     * Asserts that the excecution time for an autoboxed/autounboxed calculation is slower than the execution time for
     * a calcuation involving primitives only.
     *
     * @param boxedTime execution time of autoboxed/autounboxed calculation
     * @param primitiveTime execution time of primitive calculation
     */
    private void assertRunTime(long boxedTime, long primitiveTime)
        {
        System.out.println("(boxed time: " + boxedTime + " ns), (primitive time: " + primitiveTime + " ns)");
        assertTrue("Autoboxed/unboxed calculation (" + boxedTime +
                   ") should run slower than purely primitive calculation (" + primitiveTime + ").",
                   primitiveTime < boxedTime);
        }

    public TestAutoboxDouble(String name)
        {
        super(name);
        }

    /**
     * Set up the fixture before every test method call.
     */
    protected void setUp() throws Exception
        {
        this.autoboxDouble = new AutoboxDouble(5,7);
        }

    /**
     * Tear down the fixture after every test method call.
     */
    protected void tearDown() throws Exception
        {
        this.autoboxDouble = null;
        }

    private AutoboxDouble autoboxDouble;
    }

As expected, the primitive calculation runs much faster than the autoboxed calculation, 15.5 times faster, 2000 ns and 31,000 ns, respectively.

Primitives faster than wrappers?

But of course, that’s not the end of the story. You may have noticed that the autoboxed calculation in this unit test runs before the primitive calculation.


long boxedTime = runBoxed();
long primitiveTime = runPrimitive();

What happens if we simply reverse the call order, as does the unit test below? Would you expect a different result? If you had to wager a guess, on which side would you bet?

   /**
     * Executes autoboxed/autounboxed and primitive-only calculations and compares their execution times.  Runs the
     * primitive calculation first.
     */
    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirst()
        {
        long primitiveTime = runPrimitive();
        long boxedTime     = runBoxed();
        assertRunTime(boxedTime, primitiveTime);
        }

Surprisingly, this simple change causes the autoboxed implementation to run faster, 4000 ns and 20,000 ns or 5 times faster. This happens consitently, test run after test run.

Primitives first

Perhaps the run-time is optimizing these almost identical implementations, maybe using the same bytecode for both. But that’s just a guess. If it were the case, you’d think the times would be identical.

To try and shed some light into this behavior, let’s see what happens when the primitive calculation is run again, a second time, as in

    /**
     * What's going on in testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirst?  Some sort of vm
     * optimization?
     */
    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstRepeat()
        {
        long primitiveTime = runPrimitive();
        long boxedTime     = runBoxed();
             primitiveTime = runPrimitive();
        assertRunTime(boxedTime, primitiveTime);
        }

Once more, the primitive calculation wins out, consistently over many test runs.

primitiveboxedprimitive.jpg

So, what would happen if both calculations are executed multiple times in one test run? This test runs them 100 times and then compares their execution times.

 public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoop()
        {
        long primitiveTime = 0;
        long boxedTime   = 0;
        for (int i=0; i<100; i++)
            {
            primitiveTime = runPrimitive();
            boxedTime   = runBoxed();
            }
        assertRunTime(boxedTime, primitiveTime);
        }

Results vary over test runs. Here’s one sequence of 10 runs.

Run Boxed Time (ns) Primitive Time (ns)
1 1000 0
2 1000 0
3 1000 0
4 2000 0
5 1000 0
6 1000 1000
7 1000 0
8 1000 1000
9 1000 1000
10 1000 0

It looks like the vm may optimize, but not every time. The same time behavior occurs when the calculations are run using different triangle sides, as in

public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoopDiffFixtures()
        {
        long primitiveTime = 0;
        long boxedTime     = 0;
        for (int i=0; i<100; i++)
            {
            primitiveTime = runPrimitive();
            boxedTime   = runBoxed();
            this.autoboxDouble = new AutoboxDouble(i*2, i*5);
            }
        assertRunTime(boxedTime, primitiveTime);
        }

Putting all these unit tests together, this is what it looks like when all unit tests are run.

All 1

All 2

All 3

All 4

If you repeat the tests enough times, you’ll see all combinations, primitive calculations taking less, the same, and more time than the autoboxed counterpart.

Conclusion

So what is the answer to the original question? Are primitives always faster than autoboxed values? This brief experiment demonstrates that a good deal of the time they are faster. However, the ultimate answer seems to depend on what optimizations the vm performs at run time.

Full source code

AutoboxDouble.java

package com.jluix.lab.unit.learning.autoboxing;

/**
 * User: jorge
 * Date: Apr 29, 2007
 * Time: 9:37:08 PM
 */
public class AutoboxDouble
    {
    public double hypotenusePrimitive()
        {
        return Math.sqrt(this.a * this.a + this.b * this.b);
        }

    public Double hypotenuseBoxed()
        {
        return Math.sqrt(this.aBoxed * this.aBoxed + this.bBoxed * this.bBoxed);
        }

    public AutoboxDouble(double a, double b)
        {
        this.a = a;
        this.b = b;
        this.aBoxed = a;
        this.bBoxed = b;
        }

    private double a;
    private double b;
    private Double aBoxed;
    private Double bBoxed;
    }

TestAutoboxDouble.java

/**
 * User: jorge
 * Date: Apr 29, 2007
 * Time: 9:35:35 PM
 */
package com.jluix.lab.unit.learning.autoboxing;

import junit.framework.TestCase;

/**
 * Demonstrates autoboxing and autounboxing doubles.
 * Based on discussion in ch 1 of Java 2 v5.0 Tiger New Features, by Herber Schildt
 */
public class TestAutoboxDouble extends TestCase
    {
    public TestAutoboxDouble(String name)
        {
        super(name);
        }

    /**
     * Set up the fixture before every test method call.
     */
    protected void setUp() throws Exception
        {
        this.autoboxDouble = new AutoboxDouble(5,7);
        }

    /**
     * Tear down the fixture after every test method call.
     */
    protected void tearDown() throws Exception
        {
        this.autoboxDouble = null;
        }

    /**
     * Executes autoboxed/autounboxed and primitive-only calculations and compares their execution times.  Runs the
     * primitive calculation first.
     */
    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirst()
        {
        long primitiveTime = runPrimitive();
        long boxedTime     = runBoxed();
        assertRunTime(boxedTime, primitiveTime);
        }

    /**
     * What's going on in testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirst?  Some sort of vm
     * optimization?
     */
    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstRepeat()
        {
        long primitiveTime = runPrimitive();
        long boxedTime     = runBoxed();
             primitiveTime = runPrimitive();
        assertRunTime(boxedTime, primitiveTime);
        }

    /**
     *  What would happen if both calculations are executed multiple times in one test run?  This test runs them 100
     *  times then compares their execution times.
     */
    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoop()
        {
        long primitiveTime = 0;
        long boxedTime   = 0;
        for (int i=0; i<100; i++)
            {
            primitiveTime = runPrimitive();
            boxedTime   = runBoxed();
            }
        assertRunTime(boxedTime, primitiveTime);
        }

    /**
     *  What would happen if both calculations are executed multiple times in one test run using different fixtures?
     *  This test runs them 100 times, creating a different triangle each time, and then compares their execution times.
     */
    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoopDiffFixtures()
        {
        long primitiveTime = 0;
        long boxedTime     = 0;
        for (int i=0; i<100; i++)
            {
            primitiveTime = runPrimitive();
            boxedTime   = runBoxed();
            this.autoboxDouble = new AutoboxDouble(i*2, i*5);
            }
        assertRunTime(boxedTime, primitiveTime);
        }

    /**
     * Executes autoboxed/autounboxed and primitive-only calculations and compares their execution times.
     */
    public void testPrimitivesFasterThanAutoboxedWrappersRunWrappersFirst()
        {
        long boxedTime     = runBoxed();
        long primitiveTime = runPrimitive();
        assertRunTime(boxedTime, primitiveTime);
        }

    /**
     * Executes hypotenuse implemntation that involves autoboxing and autounboxing the triangle sides.
     * @return execution time
     */
    private long runBoxed()
        {
        long startBoxed = System.nanoTime();
        this.autoboxDouble.hypotenuseBoxed();
        long boxedTime = System.nanoTime() - startBoxed;
        return boxedTime;
        }

    /**
     * Executes hypotenuse implementation that involves primitive double triangle sides.
     * @return execution time
     */
    private long runPrimitive()
        {
        long startPrimitive = System.nanoTime();
        this.autoboxDouble.hypotenusePrimitive();
        long primitiveTime = System.nanoTime() - startPrimitive;
        return primitiveTime;
        }

    /**
     * Asserts that the excecution time for an autoboxed/autounboxed calculation is slower than the execution time for
     * a calcuation involving primitives only.
     *
     * @param boxedTime execution time of autoboxed/autounboxed calculation
     * @param primitiveTime execution time of primitive calculation
     */
    private void assertRunTime(long boxedTime, long primitiveTime)
        {
        System.out.println("(boxed time: " + boxedTime + " ns), (primitive time: " + primitiveTime + " ns)");
        assertTrue("Autoboxed/unboxed calculation (" + boxedTime +
                   ") should run slower than purely primitive calculation (" + primitiveTime + ").",
                   primitiveTime < boxedTime);
        }

    private AutoboxDouble autoboxDouble;
    }

Refactored source code

AutoboxDouble.java

package com.jluix.lab.unit.learning.autoboxing;

/**
 * User: jorge
 * Date: Apr 29, 2007
 * Time: 9:37:08 PM
 */
public class AutoboxDouble
    {
    /**
     * Computes the hypotenuse of a right triangle.  Not a good control for comparing primitive vs. autoboxing
     * performance as it relies on the Math.sqrt function which very likely performs parameter-based caching.
     */
    public static final Command HYPOTENUSE_COMMAND = new Command()
    {

    public double computePrimitive(double a, double b)
        {
        return Math.sqrt(a * a + b * b);
        }

    public Double computeBoxed(Double a, Double b)
        {
        return Math.sqrt(a * a + b * b);
        }

    public String getName()
        {
        return "HYPOTENUSE";
        }
    };

    /**
     * Computes the area of a rectangle.  Less likely to involve paramter-based caching, but still a possiblity.
     */
    public static final Command RECTANGULAR_AREA_COMMAND = new Command()
    {

    public double computePrimitive(double a, double b)
        {
        return a * b;
        }

    public Double computeBoxed(Double a, Double b)
        {
        return a * b;
        }

    public String getName()
        {
        return "RECTANGULAR_AREA";
        }
    };

    /**
     * Simply returns one of the sides passed.  Any run-time optimization involved?  Probably not.
     */
    public static final Command SINGLE_SIDE_COMMAND = new Command()
    {

    public double computePrimitive(double a, double b)
        {
        return a;
        }

    public Double computeBoxed(Double a, Double b)
        {
        return (double) a;//unbox, then re-box
        }

    public String getName()
        {
        return "SINGLE_SIDE";
        }
    };

    public double computePrimitive()
        {
        return this.command.computePrimitive(this.a, this.b);
        }

    public Double computeBoxed()
        {
        return this.command.computeBoxed(this.aBoxed, this.bBoxed);
        }

    public String getCommandName()
        {
        return this.command.getName();
        }

    public AutoboxDouble(double a, double b, Command command)
        {
        if (command == null)
            {
            throw new IllegalArgumentException("command cannot be null.");
            }
        this.command = command;

        this.a = a;
        this.b = b;
        this.aBoxed = a;
        this.bBoxed = b;
        }

    private double a;
    private double b;
    private Double aBoxed;
    private Double bBoxed;
    private Command command;
    }

TestAutoboxDouble.java

/**
 * User: jorge
 * Date: Apr 29, 2007
 * Time: 9:35:35 PM
 */
package com.jluix.lab.unit.learning.autoboxing;

import junit.framework.TestCase;

/**
 * Demonstrates autoboxing and autounboxing doubles.
 * Based on discussion in ch 1 of Java 2 v5.0 Tiger New Features, by Herber Schildt
 */
public class TestAutoboxDouble extends TestCase
    {
    public TestAutoboxDouble(String name)
        {
        super(name);
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstHypotenuse()
        {
        this._setUp(AutoboxDouble.HYPOTENUSE_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirst();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstRepeatHypotenuse()
        {
        this._setUp(AutoboxDouble.HYPOTENUSE_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstRepeat();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoopHypotenuse()
        {
        this._setUp(AutoboxDouble.HYPOTENUSE_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoop();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoopDiffFixturesHypotenuse()
        {
        this._setUp(AutoboxDouble.HYPOTENUSE_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoopDiffFixtures();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstAvoidArgCachingHypotenuse()
        {
        this._setUp(AutoboxDouble.HYPOTENUSE_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstAvoidArgCaching();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunWrappersFirstHypotenuse()
        {
        this._setUp(AutoboxDouble.HYPOTENUSE_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunWrappersFirst();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstRectangularArea()
        {
        this._setUp(AutoboxDouble.RECTANGULAR_AREA_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirst();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstRepeatRectangularArea()
        {
        this._setUp(AutoboxDouble.RECTANGULAR_AREA_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstRepeat();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoopRectangularArea()
        {
        this._setUp(AutoboxDouble.RECTANGULAR_AREA_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoop();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoopDiffFixturesRectangularArea()
        {
        this._setUp(AutoboxDouble.RECTANGULAR_AREA_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoopDiffFixtures();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstAvoidArgCachingRectangularArea()
        {
        this._setUp(AutoboxDouble.RECTANGULAR_AREA_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstAvoidArgCaching();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunWrappersFirstRectangularArea()
        {
        this._setUp(AutoboxDouble.RECTANGULAR_AREA_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunWrappersFirst();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstSingleSide()
        {
        this._setUp(AutoboxDouble.SINGLE_SIDE_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirst();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstRepeatSingleSide()
        {
        this._setUp(AutoboxDouble.SINGLE_SIDE_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstRepeat();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoopSingleSide()
        {
        this._setUp(AutoboxDouble.SINGLE_SIDE_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoop();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoopDiffFixturesSingleSide()
        {
        this._setUp(AutoboxDouble.SINGLE_SIDE_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoopDiffFixtures();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstAvoidArgCachingSingleSide()
        {
        this._setUp(AutoboxDouble.SINGLE_SIDE_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstAvoidArgCaching();
        }

    public void testPrimitivesFasterThanAutoboxedWrappersRunWrappersFirstSingleSide()
        {
        this._setUp(AutoboxDouble.SINGLE_SIDE_COMMAND);
        this._testPrimitivesFasterThanAutoboxedWrappersRunWrappersFirst();
        }

    /**
     * Tear down the fixture after every test method call.
     */
    protected void tearDown()
        {
        this.autoboxDouble = null;
        this.command = null;
        }

    /**
     * Set up the fixture before every test method call.
     */
    private void _setUp(Command command)
        {
        this.a = 5;
        this.b = 7;
        this.command = command;
        this.autoboxDouble = new AutoboxDouble(this.a, this.b, this.command);
        }

    /**
     * Executes autoboxed/autounboxed and primitive-only calculations and compares their execution times.  Runs the
     * primitive calculation first.
     */
    private void _testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirst()
        {
        long primitiveTime = runPrimitive();
        long boxedTime = runBoxed();
        assertRunTime(boxedTime, primitiveTime);
        }

    /**
     * What's going on in testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirst?  Some sort of vm
     * optimization?
     */
    private void _testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstRepeat()
        {
        long primitiveTime = runPrimitive();
        long boxedTime = runBoxed();
        primitiveTime = runPrimitive();
        assertRunTime(boxedTime, primitiveTime);
        }

    /**
     * What would happen if both calculations are executed multiple times in one test run?  This test runs them 100
     * times then compares their execution times.
     */
    private void _testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoop()
        {
        long primitiveTime = 0;
        long boxedTime = 0;
        for (int i = 0; i < 100; i++)
            {
            primitiveTime = runPrimitive();
            boxedTime = runBoxed();
            }
        assertRunTime(boxedTime, primitiveTime);
        }

    /**
     * What would happen if both calculations are executed multiple times in one test run using different fixtures?
     * This test runs them 100 times, creating a different triangle each time, and then compares their execution times.
     */
    private void _testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstLoopDiffFixtures()
        {
        long primitiveTime = 0;
        long boxedTime = 0;
        this.autoboxDouble = new AutoboxDouble(this.a, this.b, this.command);
        for (int i = 0; i < 100; i++)
            {
            primitiveTime = runPrimitive();
            boxedTime = runBoxed();
            this.autoboxDouble = new AutoboxDouble(i * 2, i * 5, this.command);
            }
        assertRunTime(boxedTime, primitiveTime);
        }

    /**
     * Avoid possible argument-based caching by providing each implemenation with different arguments.
     */
    private void _testPrimitivesFasterThanAutoboxedWrappersRunPrimitivesFirstAvoidArgCaching()
        {
        long primitiveTime = 0;
        long boxedTime = 0;
        for (int i = 0; i < 100; i++)
            {
            this.autoboxDouble = new AutoboxDouble(i * 2, i * 5, this.command);
            primitiveTime = runPrimitive();
            this.autoboxDouble = new AutoboxDouble(i * 7, i * 4, this.command);
            boxedTime = runBoxed();
            assertRunTime(boxedTime, primitiveTime);
            }
        }

    /**
     * Executes autoboxed/autounboxed and primitive-only calculations and compares their execution times.
     */
    private void _testPrimitivesFasterThanAutoboxedWrappersRunWrappersFirst()
        {
        long boxedTime = runBoxed();
        long primitiveTime = runPrimitive();
        assertRunTime(boxedTime, primitiveTime);
        }

    /**
     * Executes calculation implementation that involves autoboxing and autounboxing the triangle sides.
     *
     * @return execution time
     */
    private long runBoxed()
        {
        long startBoxed = System.nanoTime();
        this.autoboxDouble.computeBoxed();
        long boxedTime = System.nanoTime() - startBoxed;
        return boxedTime;
        }

    /**
     * Executes calculation implementation that involves primitive double triangle sides.
     *
     * @return execution time
     */
    private long runPrimitive()
        {
        long startPrimitive = System.nanoTime();
        this.autoboxDouble.computePrimitive();
        long primitiveTime = System.nanoTime() - startPrimitive;
        return primitiveTime;
        }

    /**
     * Asserts that the excecution time for an autoboxed/autounboxed calculation is slower than the execution time for
     * a calcuation involving primitives only.
     *
     * @param boxedTime     execution time of autoboxed/autounboxed calculation
     * @param primitiveTime execution time of primitive calculation
     */
    private void assertRunTime(long boxedTime, long primitiveTime)
        {
        System.out.println(this.autoboxDouble.getCommandName() + " (boxed time: " + boxedTime + " ns), (primitive time: " + primitiveTime + " ns)");
        assertTrue("Autoboxed/unboxed calculation (" + boxedTime + ") should run slower than purely primitive calculation (" + primitiveTime + ").", primitiveTime < boxedTime);
        }

    private double a;
    private double b;
    private AutoboxDouble autoboxDouble;
    private Command command;
    }

Command.java

package com.jluix.lab.unit.learning.autoboxing;

/**
 * Provide two implementations of the same calculation, one involving primitives and the other autoboxing/autounboxing.
 *
 * @author jorge
 * @version $Revision:  $
 * @created May 29, 2007 9:14:36 PM
 * @since 1.0
 */
public interface Command
    {
    double computePrimitive(double a, double b);

    Double computeBoxed(Double a, Double b);

    String getName();
    }

Web Mob

Posted on May 2nd, 2007 in The Art of Computer Programming by Jorge Luis

This may be a first for the web, the first cyber-riot. The digg.com community revolted when the site operators deleted a story revealing the decoding key for HD-DVD. So, all it takes for a “web 2.0″ community to become a “web 2.0″ mob is for the community to vociferously complain?

South Florida Software Symposium

Posted on April 26th, 2007 in The Art of Computer Programming by Jorge Luis

I’ll be attending the first South Florida Software Symposium, a No Fluff Just Stuff presentation. I won a pass at the March MJUG meeting. Local and free, that’s hard to top.

There are more than a few worthy topics. My top picks thus far are:

  1. The Busy Java Developer’s Guide to ClassLoaders
  2. The Busy Java Developer’s Guide to Debugging and Monitoring
  3. The Busy Java Developer’s Guide to Java Platform Security
  4. Annotation Hammer
  5. OSGi: A Well Kept Secret
  6. The Busy Java Developer’s Guide to Reflection
  7. Acegi (Spring Security)
  8. Java Memory, Performance and the Garbage Collector
  9. Introduction to Hibernate. My Hibernatese is rusty.
  10. Effective Hibernate or Practices of an Agile Developer. I saw a preview at the April MJUG meeting, which left me wanting to hear the entire talk.
  11. Advanced Hibernate

It’s great to have a NFJS event just down the road from my office. I hope it’s a great success.

Management for Geeks

Posted on April 19th, 2007 in Small Talk, The Art of Computer Programming by Jorge Luis

JavaScript Hijacking

Posted on April 19th, 2007 in The Art of Computer Programming by Jorge Luis

A recent report demonstrates a security vulnerability to which AJAX applications are susceptible, JavaScript Hijacking. The vulnerability has already been exploited, GMail being one of the first victims.

Google was serving the current GMail users’ contacts in unprotected JavaScript, so an attacker could steal the contact list using JavaScript Hijacking.

It also turns out that mashups are inherently susceptible to such attacks, as the very techniques that make mashups possible enable JavaScript Hijacking, which can be thought of as a malicious mashup.

An application can be mashup-friendly or it can be secure, but it cannot be both.

H/T: Ted Neward

Next Page »