Thursday, September 11, 2008

JNA: increasing performance with large Structures

If you're using very large structures and using them often, here's a tip that can boost performance by several orders of magnitude. Note that you should follow this tip *only* if you really need the performance boost; otherwise you may wind up obfuscating your code.

By default, when JNA makes a native call it will copy the full contents of a Java Structure to native memory prior to the call and read it all back after the call. If your Structure is very large, this can result in significant overhead reflecting all the fields of the Structure. The reflection dwarfs the actual native communication time.

If you're only reading or writing a single field, it's much faster (although somewhat less elegant) to use the readField(String) and writeField(String) methods to access the data, while disabling the normal read and write. Depending on the size of your structure, you may see two orders of magnitude or more improvement in the native function call time.

Here's an example of performing the same operation two different ways:

class Big extends Structure {
public int toNative;
public int fromNative;
// plus lots more fields
// the more, the bigger the difference in performance


class FastBig extends Big {
public void read() { }
public void write() { }

Big big = new Big();
big.toNative = 42;
System.out.println("Got " + big.fromNative);

Big fast = new FastBig();
fast.toNative = 42;
System.out.println("Got " + fast.readField("fromNative"));

If you wrap a loop and time these, you'll see what kind of difference it makes. On a test structure with 25 "int" fields, the fast version reduces time by a factor of 10.

Trivia: some other "struct" implementations (e.g. Javolution) use objects for all fields and require an explicit "write" or "set" on each. This reduces data transfer and/or reflection overhead, at the expense of simplicity of assignment and initialization.

s.field = 1;


Thursday, September 04, 2008

JNA win64 port

JNA now supports 64-bit windows. The the build is a bit nonstandard, but it's automatic and reproducible. I was hoping to use mingw-64, but that project is not yet sufficient for JNA's purposes. Fortunately, the MS has a free 64-bit cross compiler which does work.

Thanks to the fine folks at Aquafold (actually mostly Niels G. the CTO) for making it possible.

Thanks also to T. Heller of python's ctypes for the initial glue bits.

Sunday, August 10, 2008

Decorator Update

Thanks to some input from a few users, the AbstractComponentDecorator has been updated to fix a few visual and behavior artifacts.

Get the latest from Sourceforge SVN.

The decorator component allows you to apply arbitrary decorations to a component without affecting its layout or (necessarily) response to events.

This blog has many different examples of usage beyond simple decorations, including drag images and per-component input blocking.

Saturday, January 19, 2008

Embedding DLL File Version Information with mingw32/cygwin

If you look at the properties window for a DLL file in Windows, you'll see a few bits about the file version and copyright info. I couldn't find any information on the web about how to embed that information into a DLL. Not terribly surprising, since it's probably something MSVC inserts automatically, so why would any one need to know how it's done?

Well, I'm building a DLL with cygwin/mingw32, so I do need to know how it's done. Fortunately, Mumit Khan, author of mingw32, wrote a utility called "windres", which compiles w32 resources for use in an executable or DLL. It'll compile directly to object format, which you can simply add to your final link.

For example:

% windres -i version.rc -o version.o
So the only thing I needed to figure out was the version resource format (I really didn't want to go grok the resource spec and write it from scratch). Luckily, Java's main DLL (java.dll, what else) has version information in it, and windres can also conveniently dump an exe or dll back into text format.

The java.dll resource info looks like this:

% windres -i java.dll -O rc

// Type: version
// Name: 1
FILEVERSION 6, 0, 30, 5
BLOCK "StringFileInfo"
BLOCK "000004b0"
VALUE "CompanyName", "Sun Microsystems, Inc."
VALUE "FileDescription", "Java(TM) Platform SE binary"
VALUE "FileVersion", ""
VALUE "Full Version", "1.6.0_03-b05"
VALUE "InternalName", "java"
VALUE "LegalCopyright", "Copyright \251 2004"
VALUE "OriginalFilename", "java.dll"
VALUE "ProductName", "Java(TM) Platform SE 6 U3"
VALUE "ProductVersion", ""

With just a few tweaks to do a regexp replace on the new template and include the new obj in my build, my released dll now has visible version information (and in this case I'm perfectly happy having absolutely no clue what any of the resource file text actually means :).