sun.misc.Unsafe : not worth it

Remembering the benchmarks in the thread http://www.java-gaming.org/forums/index.php?topic=15659.0, I decided to do a test with the Sega Y-Board driver in JEmu2. I converted the zooming sprite and layer rotation emulation to use sun.misc.Unsafe to avoid array bounds checks and hopefully get a nice performance boost like the benchmarks showed was possible.
This part of the Y-Board emulator is the main bottleneck, and there’s HUGE amounts of random array access in there so this seemed a good real life test.

Since using this internal class requires a really ugly hack, I thought I’d post the results, because I found that in the end it’s not worth the trouble.
I got a performance boost which is hardly noticable (less than 5%) and when I use the server VM (latest 1.6), it actually seems counter productive (using normal arrays was actually a tiny bit faster than sun.misc.Unsafe, strange but true).

So, save yourself the trouble of using a kind of dangerous, non-standard class, just stick to normal arrays (or buffers if needed).

Unsafe works with 64 bit pointers, the JVM works with 32 bit pointers. You might want to try to run the driver on a x64 machine on a 64 bit OS, and run the benchmarks again. I’m very interested.

On a sidenote:
doing things like this:

long pointer = …;
int offset = …;
unsafe.getFloat(pointer + offset)

is slower than making the ‘offset’ a long in the first place. Lots of this ‘little facts’ found by trial and error can bump the performance quite a bit.

I don’t have access to a 64bit machine, so I can’t really test this…
I have to admit my implementation using Unsafe can be improved a bit, maybe I could ultimately get to a possible 5-10% performance gain. However I’m still not sure if even 10% performance gain is worth the trouble…
The thing is, even if I can get the whole emulator to gain 15% performance (which might be possible if I convert all arrays to Unsafe and optimize accordingly, which is a huge undertaking), I’ll be using something non-standard so I’m bound to run into troubles as some JVM’s might not have this class, I’ll be running in C like crashes if I make a mistake, and who knows the JVM will be able to optimize standard arrays better in the future…

Of course I could rewrite stuff so that the actual array and Unsafe implementations will be abstracted away so that I can check if Unsafe can be used by the JVM, but that will probably defeat the purpose because that has a cost too.
I guess I’ll just don’t bother too much and accept the fact that if I wanted the emulator to be blazingly fast, Java is not the best option and I might as well go back to at least C.

Surely it’s only got to be as fast as the original hardware?

Cas :slight_smile:

Yes of course, but with Y-Board hw, I’m getting slowdowns and I’m even cheating big time.

Consider the original hardware is running 3x 16Mhz CPU’s + 1x 4Mhz CPU, 6 math chips, a layer with numerous scaled sprites supporting alpha blending, a text layer, the whole sprite layer can be rotated, it has an FM synthesizer and a 16 channel PCM chip.
It’s really a lot to emulate so I need some serious performance to have it running at full speed.

I’m currently using Unsafe for structs only (not mapped objects). Not so much to have more performance, but to be able to work with compact data the way I like. The moment I need a ton of Int/Float/…-Buffers to be able to thread a memory-region as bytes, shorts, ints, floats, etc it simply gets annoying. I made a wrapper-class around Unsafe that checks all pointers (when the DEBUG flag is set) which helps me get rid of the pointer-errors.

I generally don’t gain much performance either, due to the 64-bit additions (pointer+offset) I guess.

If you need structs, Unsafe is the way to go. And you are freed from the max-direct-heap, you can easily do Unsafe.allocateMemory(512 * 1024 * 1024), just don’t forget to set the bits to zero :o)

For that I suppose using Unsafe can be useful, just as long as you keep in mind it’ll probably only work on the Sun JRE and then only until they decide to change things.