Use direct bytebuffers

A coworker referred me to your blog post (http://imranrashid.com/posts/profiling-bytebuffers/). I commented there about the possibility of using direct bytebuffers for increased performance, still I was a bit curious myself.

Here are the result of the original code:

```
Benchmark for raw arrays (300 calls in 4.452 s)
  Time:    14.71 ms   95% CI 14.12 ms - 15.31 ms   (n=20)
result = 1.19841533E14
Benchmark for byte buffer (20 calls in 2.244 s)
  Time:    107.7 ms   95% CI 102.6 ms - 112.8 ms   (n=19)
  Garbage: 0 ns   (n=1 sweeps measured)
result = 1.19841533E14
Benchmark for float buffer (60 calls in 2.402 s)
  Time:    40.19 ms   95% CI 38.25 ms - 42.13 ms   (n=20)
result = 1.19841533E14
```

And using direct bytebuffers:

```
Benchmark for raw arrays (140 calls in 2.074 s)
  Time:    14.30 ms   95% CI 13.59 ms - 15.02 ms   (n=20)
result = 1.19841533E14
Benchmark for byte buffer (140 calls in 2.609 s)
  Time:    18.05 ms   95% CI 17.02 ms - 19.08 ms   (n=19)
result = 1.19841533E14
Benchmark for float buffer (140 calls in 2.082 s)
  Time:    14.61 ms   95% CI 13.98 ms - 15.24 ms   (n=20)
result = 1.19841533E14
```

Endianness didn't since to influence the results that much, but I consistently got better results using native byteorder by a small margin (across 5 runs). 

Direct byte buffers are also pretty good if you're interacting with C code (through JNI), since you can avoid copying buffers.

Cheers!