Just another Java JNA HelloWorld Performance

Posted On
While searching for an easier way to interact with JXcore (for Java developers) I've wanted to give an another shot to JNA (Java Native Access). JNA, in a few words; "provides Java programs an easy access to native shared libraries without writing anything but Java code - no JNI or native code is required."


Let's Start Coding! Our first Java code (HelloWorld.java) -

import com.sun.jna.Library;
import com.sun.jna.Native;

public class HelloWorld {
  public interface CTest extends Library {
    public int dummy(int x, int y);
    public int dummy2();
  }

  static public void main(String argv[]) {
    CTest ctest = (CTest) Native.loadLibrary("test", CTest.class);

    long q = 0;

    for (int y = 0; y < 2000; y++) {
      for (int x = 0; x < 1000; x++) {
        q += ctest.dummy(x, y);
        q %= 998;
      }
    }

    System.out.println("Total: " + q);
  }
}

We need a basic c file to test (test.c) -

#include <stdio.h>

int n = 0;

int dummy(int x,  int y) {
    return x + y;
}

int dummy2() {
  n++;
  n%=1000;
  return n;
}

This very first case is intended to measure the performance of calling a basic C method with two integer parameters. (2M times!)

In order to try it, I've used below list of command lines on OSX (for linux systems you may want to change dylib extension to so and remove lib from the name).
gcc -o libtest.dylib -shared test.c
javac -classpath jna.jar HelloWorld.java
time java -classpath jna.jar:. HelloWorld

Result:
real 0m3.998s
user 0m4.215s
sys 0m0.085s

The first result definitely doesn't look promising. Thankfully JNA has a second 'fast' option that we can register the native methods.

Update the HelloWorld.java file with the sources below;
import com.sun.jna.Library;
import com.sun.jna.Native;

public class HelloWorld {
  static public void main(String argv[]) {
    HelloJNA ctest = new HelloJNA();
    long q = 0;

    for (int y = 0; y < 2000; y++) {
      for (int x = 0; x < 1000; x++) {
        q += ctest.dummy(x, y);
        q %= 998;
      }
    }

    System.out.println("Total: " + q);
  }
}

class HelloJNA
{
  public native int dummy(int x, int y);
  public native int dummy2();

  static
  {
    Native.register("test");
  }
}

Compile this new Java file using the previous terminal commands.
Result:
real 0m0.515s
user 0m0.526s
sys 0m0.034s


Up to 8 times faster! Indeed it's amazing to see how discovery etc. takes this much time. I should warn you though since I tried a complex native printf scenario with the second register option and it didn't went well. What I'm trying to say is that the second option is fast but in case the types etc. are a little bit complicated you need the first option anyways.

If you look closer to the sources, you will see that there is a second dummy method without any parameter. I have to say that this version of dummy works as fast as the one with register option. I think it's clear where JNA loses the horse power.

I believe the performance with register option is sufficient enough for an application that embeds JXcore to run Node.JS applications. (257 nano seconds per call on an i7 2.4 Ghz core)
[Read more]

JavaScript, Node.JS and IOT

Posted On
Most of you know the old school approach on IOT and JavaScript (node.js etc.) that you can connect to a device using a serial port, wifi etc. from your computer and send the instructions. 

This is no longer the best solution for the next gen products.  As some of you already know, JXcore wraps the IO around the popular JavaScript engines and provides node.js application interface on many platforms. It's not that hard to expect JavaScript will be taking it's first citizen place on next gen smart products.

I'm personally a mini / tiny board collector and I do not see any reason not to run most of the logic / IO on the board instead having a need of external computer that uses the target device as a puppet.

Let's start with the mini boards. Some weeks ago, I received my new Raspberry Pi 2 with 4 cores in it's new cute box. Pi is one of the lots of other mini boards I have been buying last years. I do really appreciate the mini boards. They control my home media, central backup and I use them to develop apps on every possible screen and environment. 

I have to admit that the new Pi 2 has an amazing performance comparing to similar price boards (with a similar level of stability!). It didn't took much time compiling whole JXcore right from the beginning and I'm able to run my media server node.js app multi-threaded thanks to JXcore's multi-tasking capabilities and Pi 2's quad cores. I've to tell that it works really fast!

Raspberry Pi 2 cost me around 35-40 USD including the box, adapter etc. (no battery included) I feel like it's a reasonable price knowing the market range nowadays.  However, smart phones are also entering into the same price range with the mini boards and they do offer even more features. Most of the time, you don't even need to buy a smart phone to develop something though. Almost every single person around has a smart phone in their pockets, and probably a year or two old at their home. Even more, you can find a basic smart phone for 43 USD. It has a camera, touch screen, battery and more. There you have a fully featured IoT starter unit for a very small price. 

I was talking to Ugur (my partner from Nubisa Inc.) about the future of JavaScript, JXcore (node.js) and IoT's. As some of you already know, JXcore wraps the IO around the popular JavaScript engines and provides node.js application interface on many platforms including Android and iOS. Yes, you can run node apps on mobile devices and mini boards!

There you have your device for 40 USD that you can hack using JavaScript. JXcore works standalone on all the devices so the app you develop can perform many tricky tasks without requiring any connection to network or any external puppeting.  

How about the tiny boards?  i.e. An Arduino board with only 256KB or less flash memory. Check DukTape JavaScript engine for a starter. JXcore can work with multiple JavaScript engines. Although it's not just about the underlying JavaScript engine, still having a node.js framework with multiple JavaScript engine capabilities and a suitable engine for the task is a good start. I already took lots of hours of Sami (the creator of DukTape) and feel like we are in the good direction. I do see JXcore running on tiny boards.   

Intel's Edison brought lots of horse-power into tiny board concept. This horse power is more than enough to run JXcore entirely. Hopefully they will start advertising their horse power instead old school puppeting approaches. 

I do appreciate Microsoft will be offering Windows 10 on Pi 2 for free. Moreover, Qualcomm will be offering a very powerful board for Windows ARM. You will be running JavaScript node apps on Windows ARM using JXcore. No puppeting, no external dependencies. Isn't it nice ?

Stick with JavaScript, Node.JS, and JXcore!

[Read more]

Node.JS truly on Android and iOS

Posted On
Finally we've managed to put sample projects on Github for Android, and iOS. Android sample is a standalone 'hello world' project for Eclipse IDE. iOS sample is an actual Cordova/Phonegap plugin. Soon we are going to add Android support to this plugin too.

We are not planning to put an application designer etc. in front of JXcore. Indeed we are going to make the Cordova plugin as usable/stable as we can. Then, we leave it up to mobile developers and mobile platform owners to develop solutions using JXcore. We envision and design JXcore to be technology embeddable to any other solution while you can develop your mobile applications. 

Making Node.js run on mobile devices was a long and tricky process. The general opinion is 'Node.js' runs on Android because it has V8. V8 is Google, Google is Android... The fact is, yes, it's technically possible and you can even make it work after patching it at some level but Node.js's design is not suitable for embedding into another app. Node.js was initially considered for server environment as a standalone application. As a result, if you are planning to embed Node.js into your precious Android solution (or any other), the list below might give you an idea on what is awaiting you;

- Something went wrong with JavaScript, node instance ... Restart your App!
- Node.JS doesn't cleanup the memory on exit (why should it do that, it's a standalone process)
- Node.JS tends to exit 'process' for many situations. (your whole app!)
- You can not have more than a single instance of Node.JS
- It doesn't provide anything to interact with your JavaScript files under APK
- Are you a JNI expert ?

This list goes on. I'm not criticizing node.js. It perfectly does what it's designed to do. That's why JXcore exists and handles everything else for node.js on mobile.

On our journey, some people told us, don't use 'SpiderMonkey' go with 'JavascriptCore', while many others were supporting our decision. Why SpiderMonkey is the best choice available;

- It's as fast as V8 
- ASM.JS 
- Amazing support from SpiderMonkey team (which is a life saver)
- To make the whole node.js work, you need to patch the underlying JS engine, if you patch JavascriptCore, you should use it as a dynamic library (LGPL). Unfortunately, App Store doesn't allow you to do that!

We are at the beginning. There are lots of possibilities ahead of us.

Visit JXcore's Github repository and start hacking!
[Read more]

Now ASM.JS is available for Node.JS Applications

Posted On
ASM.JS, an extraordinarily optimizable, low-level subset of JavaScript. Now it's available for Node applications. The latest JXcore (Github) embeds SpiderMonkey in addition to V8 JavaScript engine. As you might know V8 was able to run ASM.JS codes without much problem but there was no optimization or performance gain in place (actually it is even slower). As a result, it never made any sense to use ASM.JS code on a Node.JS application.

Since JXcore has SpiderMonkey in place (in addition to V8), now it's time to show a basic sample.

Save the JavaScript lines below into asmjs.js file


function AsmJSFibonacci() {
  "use asm";

  function fib(n) {
    n = n | 0;
    var value = 1;
    var prev = 1;
    var i = 1;
    var t = 0;
    for (;
      (i | 0) < (n | 0); i = (i + 1) | 0) {
      t = prev;
      prev = value;
      value = (value + t) | 0;
    }
    return value | 0;
  }

  function many_fib(n) {
    n = n | 0;
    var i = 1;
    var total = 0;
    var calc = 0;
    var z = 0;
    var limit = 2000;
    for (; (z | 0) < (limit | 0); z = (z + 1) | 0) {
      for (; (i | 0) < (n | 0); i = (i + 1) | 0) {
        calc = fib((i | 0)) | 0;
        total = ((total | 0) + (calc | 0)) | 0;
        total = (total - 452433) | 0;
      }
      i = 1 | 0;
    }

    return total | 0;
  }

  return many_fib;
}

var asm_fib = AsmJSFibonacci();


var nfib = function (numMax) {
  var x;
  for (var i = 0, j = 1, k = 0; k < numMax; i = j, j = x, k++) {
    x = i + j;
  }

  return x;
};

var normal_fib = function (n) {
  var total = 0;
  var calc = 0;
  for (var z = 0; z < 2000; z++) {
    for (var i = 1; i < n; i++) {
      calc = nfib(i);
      total += calc;
      total -= 452433;
    }
  }

  return total;
};

var start = process.hrtime();
var res = asm_fib(34);
start = process.hrtime(start);
console.log("ASMJS Time", start, res);

start = process.hrtime();
res = normal_fib(34);
start = process.hrtime(start);
console.log("NORMAL Time", start, res);

And Run!
(you can run it with 'nodejs' or 'jxcore' using V8 engine though. But you should build 'jxcore' with 'spidermonkey' from the sources in order to see how it behaves with a proper ASM.JS support.

jxcore-spidermonkey build:
ASMJS Time [ 0, 1213238 ] 122000
NORMAL Time [ 0, 1909488 ] 122000

jxcore-v8 build:
ASMJS Time [ 0, 7572855 ] 122000
NORMAL Time [ 0, 2347491 ] 122000

Looks like ASM.JS & SpiderMonkey is the winner for the above sample. This is not a performance comparison indeed. There are already many performance comparisons available on ASM.JS performance.

You may want to ask 'what the heck is "require.withAsmJS" ? SpiderMonkey requires "compileAndGo" option enabled for an ASM.JS script. This is not a case for a normal Node.JS JavaScript since "compile" and "go" are two separate steps. For this reason, JXcore has a new addition to "require" interface for JavaScript files with ASM.JS Luke Wagner from SpiderMonkey told me this is no longer an issue. JXcore is updated accordingly. Simple 'require' works now. (sample code is also updated)
[Read more]