Truffle

From APIDesign

Jump to: navigation, search

I have spent last two years designing Truffle A set of APIs to build own language interpreter that gets special treatment by Graal (alternative version of HotSpot VM). As a result a well written interpreter can run faster than generated native code at the end.

Truffle is using sort of AsmJs approach: rather than complicating the JVM (like it was done with invokeDynamic instruction), it creates additional Java APIs that dynamic language vendors may use. The API patterns are then recognized by the enhanced HotSpot compiler to emit more effective code. All of that without modification to the JVM spec.

Truffle Ruby implementation is ten times faster than pure JRuby (which was based on invokeDynamic).

Contents

Speeding Ruby Up: Ten times!

Ruby was always known to be very slow language. Even when the hype around Rails was on - e.g. around 2006, there was nobody who could make the language fast. The great news is that OracleLabs decided to demonstrate the power of their Truffle framework on Ruby and are working on a fast Ruby implementation. OracleLabs claim that their implementation is ten times faster than the standard Ruby.

I wanted to verify such claim. One thing is being faster in a benchmark, the other thing is to speed up real programs. That is why I decided to write my first Ruby program - the Sieve of Eratosthenes and as following video demonstrates, Truffle based Ruby is really faster:

Is Truffle based Ruby ten times faster? The video shows that standard Ruby can compute about 5000 of prime numbers in 20s on my computer. The Truffle version was able to compute 17000 of primes. For a while I believed that this implies three times speed up. Not bad, but far less than the claim of being ten times faster.

However once, while showing the demo, I forgot to kill the standard Ruby version. After three minutes I noticed that and to my surprise the standard version was still fighting with 15000th prime number - e.g. it takes at least 180s to compute what Truffle Ruby can in 20s. The explanation is easy - computing first thousands of primes is way easier that finding the next thousands ones. The sieve of Eratosthenes algorithm isn't linear. Only comparing the time to compute the same amount of primes makes sense. However such time comparison actually shows ten times speed up!

class Natural
  def initialize
    @x = 2
  end
 
  def next
    return @x += 1
  end
end
natural = Natural.new
 
class Filter
  def initialize(number, filter)
    @number = number
    @filter = filter
  end
 
  def number
    @number
  end
 
  def filter
    @filter
  end
 
  def accept(n)
    filter = self
    loop do
      if (n % filter.number) == 0
        return false
      end
      filter = filter.filter;
      break if filter == nil
    end
    return true;
  end
end
 
class Primes
  def initialize(natural)
    @natural = natural
    @filter = nil;
  end
 
  def next
    loop do
      n = @natural.next
      if (@filter == nil || @filter.accept(n))
        @filter = Filter.new(n, @filter)
        return n;
      end
    end
  end
end
primes = Primes.new(natural)
 
puts "Press Ctrl-D to start..."
$stdin.read
 
start = Time.now
cnt = 0
res = ""
puts "Working..."
loop do
  p = primes.next
  res << "#{p}\n"
  cnt += 1
  if cnt % 1000 == 0
    puts res
    puts "Computed #{cnt} primes in #{Time.now - start} s"
    res = ""
  end
end


Truffle gives Ruby the speed it always needed.

Get It for Free

When designing new language, one usually starts with an AST interpreter. When the language is ready for use, users find out it is great, but slow. So one starts to design a bytecode to speed things up. That helps, but still the execution is slow.

Truffle vision is different: write your AST interpreter using Truffle nodes API and we make it fast!

In addition to that we also give you a debugger for free! The following picture shows a debugger stopped in middle of simple language (an artificial language used for demo purposes) method. The IDE knows nothing about simple language (that is why syntax coloring is missing), but as it is easy to understand the general Truffle AST, the IDE can still provide enough valuable information in the debugger.

Image:TruffleDebugger.png

Please note that the name of the method is properly recognized and shown on top of the stack. Variables a and b and their values are properly shown as well.

Designing your own language? Do you want to spend time writing a debugger? If not, use Truffle and you'll get your debugger for free!

Debugger in NetBeans 8.1

NetBeans 8.1 and newer ships with support for debugging of Truffle languages. Here is a promotional video demonstrating how to use such feature, but you can try that too! Just get the most recent build of NetBeans, install the Truffle Debugging Support module and get the sources:

Installing Maven Bits and Working with Sources

Assuming your GraalVM is installed in directory $GRAAL_VM, continue by installing essential Truffle binaries into your local Maven repository:

$ $GRAAL_VM/bin/maven_install_graalvm

and then you can work with the sources. First of all obtain them and switch to the correct (known to work at present time) revision:

$ hg clone http://source.apidesign.org/hg/truffledebugdemo/
$ cd truffledebugdemo
$ hg up -C GraalVM-0.9

With the sources you can now use the command line or the IDE to work with them:

# compile:
$ JAVA_HOME=$GRAAL_VM mvn clean install
# execute
$ JAVA_HOME=$GRAAL_VM mvn exec:exec
factorial(5) = 120

The sample prints out value of factorial for five computed in four different (Java, Ruby, JavaScript and our testing simple language) languages.

Debugging from NetBeans

Make sure NetBeans is running on the GraalVM:

$ /netbeans8.1/bin/netbeans --jdkhome $GRAAL_VM

Open the project sources in the IDE (File/Open Project, select the truffledebugdemo directory). Open MixLanguages.java source file. Put breakpoint to MixLanguages.java line 37 that invokes the global factorial symbol and debug the project (Debug/Debug Project or press Ctrl-F5). Once the breakpoint is hit, you can step-into (F7), you'll be in JavaScript. If you continue stepping in you'll get into simple language and then also into Ruby. Values of local variables will be available. Enjoy:

Personal tools