Erjang: Erlang on the JVM Kresten Krab Thorup Trifork Thursday, - - PowerPoint PPT Presentation

erjang erlang on the jvm
SMART_READER_LITE
LIVE PREVIEW

Erjang: Erlang on the JVM Kresten Krab Thorup Trifork Thursday, - - PowerPoint PPT Presentation

@drkrab Erjang: Erlang on the JVM Kresten Krab Thorup Trifork Thursday, May 12, 2011 Erjang: Goals Learn Erlang Discover Actor Programming Meet great people Thursday, May 12, 2011 What is Erjang? Erjang is an execution


slide-1
SLIDE 1

Erjang: Erlang on the JVM

Kresten Krab Thorup Trifork @drkrab

Thursday, May 12, 2011

slide-2
SLIDE 2

Erjang: Goals

  • Learn Erlang
  • Discover “Actor Programming”
  • Meet great people

Thursday, May 12, 2011

slide-3
SLIDE 3

What is Erjang?

  • Erjang is an execution engine for BEAM

byte code, written in Java.

  • JIT
  • Compiles BEAM to JVM byte code.
  • Runtime uses shared heap model.
  • BIFs and drivers are written in Java.

Thursday, May 12, 2011

slide-4
SLIDE 4

Your favorite OS BEAM Emulator Your Erlang Program OTP Framework

BEAM

BIFs

Thursday, May 12, 2011

slide-5
SLIDE 5

Java Virtual Machine Your favorite OS ERJANG Your Erlang Program OTP Framework

BEAM JVM

BIFs

Thursday, May 12, 2011

slide-6
SLIDE 6

Let’s see it in action...

Thursday, May 12, 2011

slide-7
SLIDE 7

Erlang ≠ Erjang

Shared heap ¬ Native drivers ¬ NIF

Thursday, May 12, 2011

slide-8
SLIDE 8

Why Java?

  • JVM is everywhere (from mobile to AS/400)
  • JVM has many libraries / integrations.
  • JVM has 500+ man-years of engineering
  • JVM is fast (for Java-ish programs).
  • ... and I know JVM pretty well, ...

Thursday, May 12, 2011

slide-9
SLIDE 9

These are experimenting...

StreamBase (CEP) Running Erlang-based FSMs on event streams ErlangIDE (Eclipse) Run compiler, type analysis, etc.

Thursday, May 12, 2011

slide-10
SLIDE 10

Erjang - Challenges

  • Tail-recursion
  • Interfacing to Java
  • Ultra Light-Weight Processes
  • Real-time Behavior
  • Arbitrary Precision Numbers
  • Erlang Drivers
  • JVM is safe, urgh!

Thursday, May 12, 2011

slide-11
SLIDE 11

JIT Compiler

BEAM Reader Type Analysis JVM Codegen ring.beam ring-2a149ada.jar

Thursday, May 12, 2011

slide-12
SLIDE 12

JIT Compiler

BEAM Reader Type Analysis JVM Codegen ring.beam ring-2a149ada.jar

erlang:load_module error_handler:undefined_function ClassLoader.loadClass(“erjang.m.ring”)

*

Thursday, May 12, 2011

slide-13
SLIDE 13

Erlang ⇒ JVM

  • Module ⇒ Class (+support in a “.jar”)
  • Function ⇒ Static Method + “EFun” object
  • Value ⇒ Object Instance

ETuple, EPair, EFun, ESmall, EBig, ...

Thursday, May 12, 2011

slide-14
SLIDE 14

Erlang ⇒ JVM

  • module(bar).

process([H | T], T2) -> process(T, foo(H, T2)); process([], T2) -> T2. foo(H, T) -> lists:reverse(H ++ T).

Thursday, May 12, 2011

slide-15
SLIDE 15

The BEAM Code

{function, process, {nargs,2}}. {label,264}. {test,is_nonempty_list,{else,265},[{x,0}]}. {get_list,{x,0},{x,0},{y,0}}. {call,2,foo}. {move,{x,0},{x,1}}. {move,{y,0},{x,0}}. {call_last,2,process,1}. {label,265}. {test,is_nil,{else,263},[{x,0}]}. {move,{x,1},{x,0}}. return. {label,263}. {func_info,{atom,appmon_bar},{atom,process},2}.

Thursday, May 12, 2011

slide-16
SLIDE 16

public static EObject process___2(EProc eproc, EObject arg1, EObject arg2) { ECons cons; ENil nil; tail: if((cons = arg1.test_nonempty_list()) != null) { // extract list EObject hd = cons.head(); EObject tl = cons.tail(); // call foo/2 EObject tmp = foo___2$call(eproc, hd, arg2); // self-tail recursion arg1 = tl; arg2 = tmp; goto tail; } else if ((nil = arg1.test_nil()) != null) { return arg2; } throw ERT.func_info(am_bar, am_process, 2); }

Thursday, May 12, 2011

slide-17
SLIDE 17

DEMO

  • c(foo).
  • c(foo).
  • foo:main().

Thursday, May 12, 2011

slide-18
SLIDE 18

Erlang ⇒ JVM

  • module(bar).

process([H | T], T2) -> process(T, foo(H, T2)); process([], T2) -> T2. foo(H, T) -> lists:reverse(H ++ T).

Thursday, May 12, 2011

slide-19
SLIDE 19

public static EObject foo__2(EProc p, EObject H, EObject T) { EObject r = foo__2$body(p,H,T); while (r == TAIL_MARKER) { r = p.tail.go(); } return r; }

foo(H, T) -> lists:reverse(H ++ T).

Thursday, May 12, 2011

slide-20
SLIDE 20

public static EObject foo__2$body(EProc p, EObject H, EObject T) { // Tmp = erlang:’++’(H,T) EObject tmp = erlang_append__2.invoke(p,H,T); // return lists:reverse(Tmp) p.tail = lists__reverse_1; p.arg1 = tmp; return TAIL_MARKER; }

foo(H, T) -> lists:reverse(H ++ T).

Thursday, May 12, 2011

slide-21
SLIDE 21

package erjang.m.bar; class bar extends ECompiledModule { @Import(module=“lists”, fun=“reverse”, arity=1) static EFun1 lists__reverse__1 = null; @Import(module=“erlang”, fun=“++”, arity=2) static EFun2 erlang__append__2 = null; ... }

foo(H, T) -> lists:reverse(H ++ T).

Thursday, May 12, 2011

slide-22
SLIDE 22

Interface to Java

  • Calling to JAVA from ERJANG
  • BIFs: special calling convention
  • Plain Java: Type conversions
  • Calling ERJANG from JAVA

Thursday, May 12, 2011

slide-23
SLIDE 23

Example BIF

// foo:bar(...) native Function package erjang.m.foo; class foo extends ENative { @BIF public static EObject bar(EProc proc, EObject arg1, arg2, ...) { } }

Thursday, May 12, 2011

slide-24
SLIDE 24

Example BIF

@BIF public static EObject spawn_link(EProc proc, EObject mod, EObject fun, EObject args) throws Pausable { EAtom m = mod.testAtom(); EAtom f = fun.testAtom(); ESeq a = args.testSeq(); if (m==null||f==null||a==null) throw ERT.badarg(mod, fun, args); EProc p2 = new EProc(proc.group_leader(), m, f, a); p2.link_to(proc); ERT.run(p2); return p2.self_handle(); }

Thursday, May 12, 2011

slide-25
SLIDE 25

demo() -> Map = 'java.util.HashMap':new(), Map:put('x', "4"), Map:put(1, 'foo'), print(Map). print([]) -> ok; print([{Key,Val}|Tail]) -> io:format("key=~p, value=~p~n", [Key,Val]), print(Tail).

Thursday, May 12, 2011

slide-26
SLIDE 26
  • new Thread() {
  • {
  • setDaemon(true);
  • start();
  • }
  • public void run() {
  • String[] ARGS = {
  • "-progname", "ej",
  • "-home", System.getProperty("user.home"),
  • "-root", "/Users/krab/Projects/OTP_R13B04",
  • "+A", "2",
  • "+S", "1",
  • "+e", "5.7.5",
  • "-s", "rpc", "erjang_started"
  • };
  • try {
  • erjang.Main.main(ARGS);
  • } catch (Exception e) {
  • e.printStackTrace();
  • }
  • };
  • };

Thursday, May 12, 2011

slide-27
SLIDE 27
  • //
  • // The -s rpc erjang_started argument

// makes the loader call rpc:erjang_started/0

  • // which is the trigger that will release

// 'wait_for_erjang_started'

  • //
  • System.err.println("did launch Erjang, ... waiting");
  • RPC.wait_for_erjang_started(60*1000L);
  • //
  • // Call erlang:display( ["Hello, Joe!~n", []] )
  • //
  • EString hello_str = EString.fromString("Hello, Joe!~n");
  • ESeq format_args = EList.make( hello_str, ERT.NIL );
  • RPC.call(am_erlang, am_display, (EObject)format_args );

Thursday, May 12, 2011

slide-28
SLIDE 28

Light-Weight Processes

  • Threads don’t cut it.
  • Erjang uses Kilim, a JVM byte code rewriter
  • Allows scheduling processes onto threads.

Thursday, May 12, 2011

slide-29
SLIDE 29

Kilim

!"#$% &'!%( )*%)+ ",,-&"&%. $#) /'&%( )-.% *%"! 0-.%1 2$-1"&2-, )*%)+ 345 &#",$6-#0 /'&%( )-.%

7212089%":%# ;":")

%<&%#,"1 ",,-&"&2-,$

http://www.malhar.net/sriram/kilim/

Thursday, May 12, 2011

slide-30
SLIDE 30

Kilim Rewriting

int execute() throws Pausable { msg = mbox.get(); return msg.size(); }

Thursday, May 12, 2011

slide-31
SLIDE 31

Kilim Rewriting

int execute() throws Pausable { throw KilimError(); } int execute(Fiber f) throws Pausable { msg = mbox.get(f); return msg.size(); }

Thursday, May 12, 2011

slide-32
SLIDE 32

Kilim Rewriting

int execute(Fiber f) throws Pausable { f.down(); msg = mbox.get(f); switch(f.up()) { case PAUSING|NO_STATE: f.setState(new State(locals)); case PAUSING|HAS_STATE: return 0; case RUNNING|HAS_STATE: locals = f.getState(); case RUNNING|NO_STATE: } return msg.size(); }

Thursday, May 12, 2011

slide-33
SLIDE 33

Kilim Rewriting

void execute(Fiber f) throws Pausable { switch (f.pc) { case 0: // default f.down(); mbox.get(f); switch(f.up()) { case PAUSING|NO_STATE: f.setState(new State(...locals...)); case PAUSING|HAS_STATE: return 0; case NORMAL|HAS_STATE: locals = f.getState(); case NORMAL|NO_STATE: } case 1: // default return msg.size(); } }

Thursday, May 12, 2011

slide-34
SLIDE 34

The ring!

Thursday, May 12, 2011

slide-35
SLIDE 35

Thursday, May 12, 2011

slide-36
SLIDE 36

Thursday, May 12, 2011

slide-37
SLIDE 37

Test Setup

erjang01.hosted.netic.dk

  • All run as JUnit tests (wrappers generated)
  • Comparison runs Module:test() Erjang vs

BEAM

  • Running TRIQ tests comparison/local
  • Run Erlang test_server based tests (single-

node mode)

  • Plain old JUnit tests

Thursday, May 12, 2011

slide-38
SLIDE 38

erl - boot time

Thursday, May 12, 2011

slide-39
SLIDE 39

erl - boot memory

Thursday, May 12, 2011

slide-40
SLIDE 40

EStones

Thursday, May 12, 2011

slide-41
SLIDE 41

Java 8

  • MethodHandle
  • Tail calls
  • Coroutines

Would not be surprised to see Erjang 10x speedup @drkrab

Thursday, May 12, 2011

slide-42
SLIDE 42

Erjang

  • It’s real
  • It’s fast
  • ... still lots to do.

@drkrab

Thursday, May 12, 2011

slide-43
SLIDE 43

Thursday, May 12, 2011