Thursday, February 26, 2015

Nim and Java and C++


This single markdown file, nim_java.md mixes: Nim, Java, and C++. The output is a single executeable that includes the Nim code translated to C, the Nim C runtime, Rusthon code translated to C++, and links to the JVM. This allows you to call Nim and Java functions from Rusthon, and manage passing data between them. For how to load a JAR library, see here.

#backend:c++

import nim
import jvm
jvm.namespace('mymod')

@jvm
class PointSubclass( Point ):
 def __init__(self, x:int, y:int):
  self.set(x,y)

 def show(self):
  print self.getx()
  print self.gety()


def main():
 nim.main()
 p1 = jvm( PointSubclass(1,2) )
 p2 = jvm( PointSubclass(10,20) )
 p1.show()
 p2.show()
 p2.scale( nim_sum(100, 1000) )
 p2.show()

Mixing Nim, Java and C++ in a single binary would normally require some complex build, and running a wrapper generator like Nimrod-Java. But Nimrod-Java has not been updated in a year, and calling JNI through Nim is going to complicate threading.

Nim and Rusthon


Nim is a new language with some very powerful features. Nim's weakness is interfacing with C++ and external threads, Hankiewicz has a good article on some of these issues here. Nim and Rusthon integration helps solve this problem, allowing you to call Nim functions from C++. This works by including your Nim program in the same markdown file along with a Rusthon program. The embedded Nim program is parsed and wrappers are generated for Nim functions that export to C. During the build Rusthon will use Nim to translate the program to C, and GCC is called to compile a staticlib without a main. The static C library is then linked to the final C++ executeable.


markdown source code

nim

proc my_nim_function(a:cint,b:cint,s:cstring): cint {.cdecl, exportc.} =
 echo("calling my_nim_function")
 echo(s)
 echo("a:", a)
 echo("b:", b)
 result = a+b

rusthon

You need to import nim and in your main function call nim.main() before calling any Nim functions.
#backend:c++
import nim

def main():
 nim.main()
 print 'calling nim function'
 s = 'mymessage to nim'
 msg = my_nim_function( 10, 20, cstr(s) )
 print msg
 print 'ok'

program output

running: /tmp/rusthon-c++-bin
calling nim function
calling my_nim_function
mymessage to nim
a:10
b:20
30
ok

Saturday, February 21, 2015

Subclass from Java


You can subclass from a Java class in Rusthon using the C++11 backend. JNI wrappers are generated using Giws and automatically compiled with the final exe by putting the Giws XML inside your markdown project.

Giws only supports regular and class methods, and basic types. Constructors and properties of Java classes are not exposed, and require extra wrapping by hand. Hopefully this will get fixed soon, github issues: constructors, properties

source code: https://github.com/rusthon/Rusthon/blob/master/examples/giws_subclass.md

java

package mymod;

public class A{
 public A(){}
 public void foo(){
  System.out.println("A.foo from java.");
 }
}

public class B extends A{
 public int y;
 public B(){ this.y=420; }
 public void bar(int i){
  System.out.println("B.bar from java.");
  this.y = i;
 }
}

rusthon

The example below shows how the property y (defined in the Java class) is exposed to Rusthon with inlined C++ that directly uses JNI calls. This is not actually the best way to do this, it would be better to write getter/setter functions in Java, and wrap those normally with Giws XML. This way of going direct with inlined JNI is only useful if you were loading a JAR and did not have access to the original Java source code to add the getter/setters.

import jvm
jvm.namespace('mymod')

@jvm
class C(B):
 def __init__(self, x:int):
  self.x = x

 def get_y(self) ->int:
  inline('''
  auto env = getCurrentEnv();
  auto fid = env->GetFieldID(this->instanceClass, "y", "I");
  return env->GetIntField(this->instance, fid);
  ''')

 def hey(self):
  print('hey from rusthon')

c++ output of C

using namespace mymod;
class C:  public B {
  public:
 std::string __class__;
 int  x;
 C* __init__(int x);
 int get_y();
 void hey();
 C(JavaVM* _jvm) : B(_jvm) {__class__ = std::string("C");}
 std::string getclassname() {return this->__class__;}
};
 int C::get_y() {
  auto env = getCurrentEnv();
  auto fid = env->GetFieldID(this->instanceClass, "y", "I");
  return env->GetIntField(this->instance, fid);
 }
 void C::hey() {
  std::cout << std::string("hey from rusthon") << std::endl;
 }

 C* C::__init__(int x) {
  this->x = x;
  return this;
 }

When creating an instance of C you still need to wrap it with the special jvm call so that the Java proxy object is also created.

def main():
 c = jvm( C(999) )
 print c.x  ## x can be used directly, prints 999
 print c.get_y()  ## prints 420
 c.foo()
 c.bar( 100 )     ## sets y to 100
 print c.get_y()  ## prints 100
 c.hey()

Thursday, February 19, 2015

Java Frontend with Giws


The Java Frontend has been updated to work with the Giws JNI wrapper generator, this lets you create Java objects and call their methods from C++, and also from Rusthon when using the C++ backend. Giws supports all of Java's primitive types like numbers, strings, and arrays; one problem is class constructors see this git hub issue.

The new syntax is documented in the wiki, here. Java source that you embed in the markdown is compiled with javac, xml source in the markdown that is marked with @giws will run giws and generate the c++ wrappers. In rusthon code using import jvm will link the final exe to libjvm.so and also create an instance of the JavaVM.

Jython Hello World

source code: giws_jython.md

See the source code in giws_jython.md to see the xml wrapper code the exposes Jython's PythonInterpreter, this simple example only wraps the exec method.

rusthon input

import jvm
jvm.load( 'jython.jar' )
jvm.namespace('org.python.util')

def main():
 interp = jvm( PythonInterpreter() )
 script = "print 'hello world'"
 interp.__exec__(cstr(script))

c++ output

using namespace org_python_util;
int main() {
 auto interp = std::make_shared(__javavm__);
 auto script = std::string("print 'hello world'");
 interp->exec(cstr(script));
 return 0;
}

Similar projects that allow Java to be used in CPython: Py4J, and Jpype.

Tuesday, February 17, 2015

C++11 Weak Pointers


C++11 introduces std::shared_ptr and std::weak_ptr to manage shared memory with reference counting and weak references. Weak references are used by children in a tree structure to reference their parent, and break the reference cycle. Methods of the child class need to take extra care with the parent pointer (the weak pointer), to promote it to a shared pointer, and only use it if the pointer is still alive.

Rusthon detects when you have a reference cycle between two classes and automatically uses weak references to break the cycle. The parent class must contain a list of child objects, then when the parent is set on the child it becomes a weak pointer. For more info, check out the wiki page.

rusthon input

The line below par = self.parent promotes the weak pointer to a reference counted shared pointer that could also be null if the parent has been deleted, so you need to check if it is None before it can be used. The last line c1.bar() will crash with a segmentation fault because it is used after the parent has been deleted, and the bar function is not checking if self.parent is not None.

class Parent:
 def __init__(self, children:[]Child ):
  self.children = children

class Child:
 def __init__(self, parent:Parent ):
  self.parent = parent

 def foo(self) ->int:
  par = self.parent
  if par is not None:
   return 1
  else:
   print('parent is gone..')

 def bar(self):
  print self.parent.children

def make_child(p:Parent) -> Child:
 c = Child(p)
 p.children.push_back(c)
 return c


def main():
 children = []Child()
 p = Parent( children )
 c1 = make_child(p)
 c2 = make_child(p)
 print c1.foo()
 c1.bar()
 del p
 print c1.foo()
 #uncomment to segfault##c1.bar()

c++11 output

class Parent {
  public:
 std::string __class__;
 std::shared_ptr<std::vector< std::shared_ptr<Child> >>  children;
 void __init__(std::shared_ptr<std::vector<std::shared_ptr<Child>>> children);
 Parent() {__class__ = std::string("Parent");}
 std::string getclassname() {return this->__class__;}
};
class Child {
  public:
 std::string __class__;
 std::weak_ptr<Parent>  parent;
 void __init__(std::shared_ptr<Parent> parent);
 int foo();
 void bar();
 Child() {__class__ = std::string("Child");}
 std::string getclassname() {return this->__class__;}
};

 void Parent::__init__(std::shared_ptr<std::vector<std::shared_ptr<Child>>> children) {
  this->children = children;
 }

 void Child::__init__(std::shared_ptr<Parent> parent) {
  this->parent = parent;
 }


 int Child::foo() {
  auto par = this->parent.lock();
  if (( par ) != nullptr) {
   return 1;
  } else {
   std::cout << std::string("parent is gone..") << std::endl;
  }
 }

 void Child::bar() {
  std::cout << this->parent.lock()->children << std::endl;
 }

std::shared_ptr<Child> make_child(std::shared_ptr<Parent> p) {
 Child  _ref_c = Child{};_ref_c.__init__(p);
 std::shared_ptr<Child> c = std::make_shared<Child>(_ref_c);
 p->children->push_back(c);
 return c;
}

int main() {

 std::vector<std::shared_ptr<Child>> _ref_children = {};
 std::shared_ptr<std::vector<std::shared_ptr<Child>>> children = std::make_shared<std::vector<std::shared_ptr<Child>>>(_ref_children);
 Parent  _ref_p = Parent{};_ref_p.__init__(children);
 std::shared_ptr<Parent> p = std::make_shared<Parent>(_ref_p);
 auto c1 = make_child(p);
 auto c2 = make_child(p);
 std::cout << c1->foo() << std::endl;
 c1->bar();
 p.reset();
 std::cout << c1->foo() << std::endl;
 return 0;
}

Thursday, February 12, 2015

Java Frontend


https://github.com/rusthon/java2python

Mixing languages, generated bindings, it makes development hard. Calling a Java function from C++ or Python through an FFI, converting types and objects, things quickly break apart. An alternative way to integrate with Java is with a frontend that converts it into another language, and completely bypass the JVM and Java compiler.

Java was supposed to run everywhere, but there is no official support for it on iOS, and you need to use a transpiler of some kind like Tom's j2objc to convert it to Objective-C. Rusthon's Java frontend can be used in a similar way, by converting Java into Rusthon syntax, and then translating that with the C++ backend, you have portable C++ that could be then compiled on iOS.

source code hello_java.md


Java Input

hand written java code example program with two class methods, foo takes a string.
public class HelloWorld {
    public static void test() {
        System.out.println("Hello, World test");
    }

    public static void foo(String msg) {
        System.out.println(msg);
    }

}

Rusthon Output

output from java2python in rusthon syntax.

class HelloWorld(object):
    @classmethod
    def test(cls:object):
        print("Hello, World test")

    @classmethod
    def foo(cls:object, msg:string):
        print(msg)

C++ Output

final translation to c++11
class HelloWorld {
  public:
 std::string __class__;
 static void test();
 static void foo(std::string msg);
 HelloWorld() {__class__ = std::string("HelloWorld");}
 virtual std::string getclassname() {return this->__class__;}
};
 void HelloWorld::test() {
  std::cout << std::string("Hello, World test") << std::endl;
 }

 void HelloWorld::foo(std::string msg) {
  std::cout << msg << std::endl;
 }

Wednesday, February 11, 2015

5X more Pystones than CPython


Two versions of Pystone are used, untyped pystone.py and typed pystone-typed.py. Taking a look at those files will show you most of what you need to know for porting code to Rusthon. This benchmark was done on 64bit linuxmint, 2Ghz. Command to run this bench:

cd Rusthon/regtests
./run.py ./bench/pystone.py
./run.py ./bench/pystone-typed.py


above pystones per-second.

Tuesday, February 10, 2015

Rusthon C++11 Backend


These are the first benchmarks testing the new C++ backend of Rusthon. As we would expect, its faster than CPython and the JavaScript backend. And, with one extra line of code, that enables raw pointers and noexcept, Rusthon can out perform PyPy.

This benchmark is short and straight to the point, less than 50 lines, it is testing object allocation/deallocation, calling methods, and adding integers. The outer loop iterates, 1000 times, and the inner loop iterates 100 times.

source code: add.py

The only surprising result from above is the big difference in performance between NodeJS and NodeWebkit. Both are using Rusthon's JavaScript backend with the same options, the JavaScript is the same. NodeJS is more than twice as slow as NodeWebkit, most likely because my version of NodeJS is older, and must not have been compiled with as many optimizations as NodeWebkit. This may show that while V8 is super fast, it's speed many vary alot depending on version and compilation options.

Optimized Version

Here is the same benchmark as above, but with one extra line at the top with (pointers, noexcept):, this makes rusthon use real pointers, and functions do not throw exceptions. Most of the performance gain comes from changing from reference counted std::shared_ptr to a real pointers. Using direct pointers requires more care in how your code is written, and how memory will be automatically and manually be free'ed, in the future we will provide an option for something faster than std::shared_ptr but safer than real pointers, using arena management or multi-core cleanup.

source code: add-opt.py

from time import clock

with (pointers, noexcept):
 class A:
  def __init__(self, x:int,y:int,z:int):
   self.x = x; self.y = y; self.z = z
  def add(self, other:A) ->A:
   a = A(self.x+other.x, self.y+other.y, self.z+other.z)
   return a
  def iadd(self, other:A):
   self.x += other.x
   self.y += other.y
   self.z += other.z

 class M:

  def f2(self, step:int, a:A, b:A, c:A, x:int,y:int,z:int) ->A:
   s = A(0,0,0)
   for j in range(step):
    u = A(x,y,z)
    w = a.add(u).add(b).add(c)
    s.iadd(w)
   return s

  def f1(self, x:int, y:int, a:A, b:A, c:A ) -> A:
   w = A(0,0,0)
   flip = False
   for i in range(x):
    if flip:
     flip = False
     w.iadd(self.f2(y, a,b,c, 1,2,3))
    else:
     flip = True
     w.iadd(self.f2(y, a,b,c, 4,5,6))
   return w

 def main():
  m = M()
  xsteps = 1000
  ysteps = 100
  start = clock()
  n = -1000000
  a = A(n,n+1,n)
  b = A(n,n+2,n)
  c = A(n,n+3,n)
  w = m.f1(xsteps, ysteps, a,b,c)
  print(clock()-start)

Sometimes people complain my benchmarks are unfair because Rusthon is static while Python and PyPy are dynamic. Or the fact that CPython has an entire ecosystem of 3rd party libraries. First of all, those 3rd party libraries are most often wrappers around a C or C++ library, and it is always a worry if they are being maintained. It is better to use C/C++ libraries directly, because Rusthon is translated to C++, there is no need for FFI, it can simply link-in and directly call into another C++ library. Rusthon is not dynamic, and static is a good thing. Do you really want to ship a Python interpreter with your application? The PyPy interpreter is over 100MB. Rusthon gives you a tiny statically linked exe, this benchmark exe is just 28KB. This lets you compile and run your application anywhere where C++ can be compiled, like mobile platforms where CPython and PyPy can not be used.

c++ output (pointers and noexcept)

class A {
  public:
 std::string __class__;
 int  y;
 int  x;
 int  z;
 A* __init__(int x, int y, int z) noexcept;
 A* add(A* other) noexcept;
 void iadd(A* other) noexcept;
 A() {__class__ = std::string("A");}
 virtual std::string getclassname() {return this->__class__;}
};
A* A::__init__(int x, int y, int z) noexcept {
 this->x = x;
 this->y = y;
 this->z = z;
 return this;
}
A* A::add(A* other) noexcept {
 A  _ref_a = A{};
 _ref_a.__init__((this->x + other->x), (this->y + other->y), (this->z + other->z));
 A* a = &_ref_a;
 return a;
}

void A::iadd(A* other) noexcept {
 this->x += other->x;
 this->y += other->y;
 this->z += other->z;
}

class M {
  public:
 std::string __class__;
 A* f2(int step, A* a, A* b, A* c, int x, int y, int z) noexcept;
 A* f1(int x, int y, A* a, A* b, A* c) noexcept;
 M() {__class__ = std::string("M");}
 virtual std::string getclassname() {return this->__class__;}
};
A* M::f2(int step, A* a, A* b, A* c, int x, int y, int z) noexcept {
  A  _ref_s = A{};_ref_s.__init__(0, 0, 0);
  A* s = &_ref_s;
  auto j = 0;
  auto j__end__ = step;
  while (( j ) < j__end__) {
   A  _ref_u = A{};
   _ref_u.__init__(x, y, z);
   A* u = &_ref_u;
   auto w = a->add(u)->add(b)->add(c);
   s->iadd(w);
   j ++;
  }
  return s;
}
A* M::f1(int x, int y, A* a, A* b, A* c) noexcept {
  A  _ref_w = A{};_ref_w.__init__(0, 0, 0);
  A* w = &_ref_w;
  auto flip = false;
  auto i = 0;
  auto i__end__ = x;
  while (( i ) < i__end__) {
   if (flip==true) {
    flip = false;
    w->iadd(this->f2(y, a, b, c, 1, 2, 3));
   } else {
    flip = true;
    w->iadd(this->f2(y, a, b, c, 4, 5, 6));
   }
   i ++;
  }
  return w;
}

int main() noexcept {

 M  _ref_m = M{};M* m = &_ref_m;
 auto xsteps = 1000;
 auto ysteps = 100;
 auto start = __clock__();
 auto n = -1000000;
 A  _ref_a = A{};_ref_a.__init__(n, (n + 1), n);
 A* a = &_ref_a;
 A  _ref_b = A{};_ref_b.__init__(n, (n + 2), n);
 A* b = &_ref_b;
 A  _ref_c = A{};_ref_c.__init__(n, (n + 3), n);
 A* c = &_ref_c;
 auto w = m->f1(xsteps, ysteps, a, b, c);
 std::cout << (__clock__() - start) << std::endl;
 return 0;
}

Sunday, February 1, 2015

Downtown Sacramento Meetup


I have started a new meetup, the "High Performance Computing Club" for hackers in the Sacramento area to meetup everyday at lunch time, and talk about writing fast programs that run on the CPU and specialized FPGA hardware. Rusthon has a new SystemVerilog backend that I will be demoing. The meetup is free, join here.