Mario Donkey Kong · Distribution, distances, concurrency, commodity, scale: all these are reasons...

Preview:

Citation preview

MarioMariovs.

Donkey Kong

…oh, Pardon…

Erlang/OTPvs.

Enterprise Java

PavloBaron

www.pbit.orgwww.pbit.org

pb@pbit.org

@pavlobaron@pavlobaron

Why am I talking Why am I talking about it

Do you think it’s about heart?

Or is there another reason?

I DON‘TLIKELIKE

JAVA!

The world of IT, as we knew it, has knew it, has changed…

Instead of huge cabinets…

…we can now use lots of cheap commodity hardware

Physics has hit the wall…

…and we must think parallel

Our physically Our physically huge globe…

s

…became a tiny electronic ball. It‘s completely wired

Spontanuous requirements…

…can be covered by the fog (aka cloud)

So what?

We must accept some things…

Functional languages much better suit parallel programming

Extrem scenarios require require

technologies allowing extrem scalability – no scalability – no

forced standards

Application types have pretty much changed

Data became more different, more different, bigger, more fine-grained and more and more frequent

High availability High availability counts for many among must-have parameters

Distribution, distances, concurrency,concurrency,commodity,scale: all these are reasons why parts reasons why parts of a system can anytime crash

Share-nothing approaches scale best

Tell me something new –

Enterprise Java Enterprise Java solves it all. Where does Erlang/OTP Erlang/OTP

come into play?

Exactly!Let‘s take a Let‘s take a look at it

Language

List<Integer> l = Arrays.asList(1, 2, 3, 4, 5);

Java: list processing

List<Integer> l = Arrays.asList(1, 2, 3, 4, 5);List<Integer> r = new ArrayList<Integer>();for (int i : l) {

if (i % 2 == 0) {r.add(i);

}}}

Erlang: list comprehensions

[X || X <- lists:seq(1, 5), X rem 2 == 0].

Where is more boilerplate?boilerplate?

synchronized (this) {if (!crawledSites.contains(site)) {

linkedSites.add(site);}

}

Java:„concurrency“

public class CountingSemaphore {private int signals = 0;public synchronized void take() {

this.signals++;this.notify();

}

„concurrency“

public synchronized void release()throws InterruptedException {

while (this.signals == 0) wait();this.signals--;

}}

Java concurrency: like two boxers alternating the gloves, thus hitting sequentially

Java concurrency: like a Java concurrency: like a goalkeeper telling the forwards to wait while he takes a pull on a battle

Erlang: functional

Erlang: single assignment

Erlang: single assignment

1> A = 5.52> A = 10.** exception error: no match of right hand side value 103>

Enterprise Java: why not pick „more modern“ weapons?..

Erlang: Share-nothing

-record(state, {start,player1,

Erlang: message passing with state externalization

player1,player2

}).

..

State = #state{start=0}Pid ! {self(), State},Pid ! {self(), State},

receive{Pid, NewState} ->

…end,

import kilim.Mailbox;import kilim.Pausable;import kilim.Task;

public class SimpleTask extends Task {static Mailbox<String> mb = new Mailbox<String>();

Java: „actor model“ This package comes with a bytecode transformation tool called Weaver (package: kilim.tools.Weaver) that post-processes .class fileslooking for the "throws Pausable" annotation.

When a task needs to pause, it

public static void main(String[] args) throws Exception {new SimpleTask().start();Thread.sleep(10);mb.putnb("Hello ");mb.putnb("World\n");mb.putnb("done");

}

public void execute() throws Pausable {while (true) {

When a task needs to pause, it unwinds its stack, squirrels away all state that it'll need later on resumption. This unwinding and rewinding the stack is automatically performed by the code introduced by the Weaver.(Debug information is adjusted so that the transformed code can be debugged inside eclipse) This is identical to what a

while (true) {String s = mb.get();if (s.equals("done")) break;

System.out.print(s);}

System.exit(0);}

}

is identical to what a programmer would havewritten

Erlang: actor based

register(serv, spawn(?MODULE, loop, []))serv ! {self(), “Hello there!”},receive

Spawn, loop, register und message passing

receive{_Pid, Msg} ->

…end.

loop() ->receive

{From, Txt}…loop();

So what?In Java, I have

standards for standards for everything. And parallel systems I can solve with I can solve with Scala and Akka

Exactly!Let‘s take a look at this as look at this as well

Java: is it really the ultimate ultimate answer to everything?

Enterprise Java: tries to standardize the half world

This somehow reminds of…

When Enterprise Java?

When not Enterprise Java?

Enterprise Java: suffers Swiss Army knife syndrome

Java: application orientedoriented

Java: especially concurrency and low level technology have generally never been to the fore

Erlang/OTP: strong specialization

Erlang: technology rather than application oriented. „Massive parallel“ from the beginning

-define(IP_VERSION, 4).

Erlang: example of bitstring processing

-define(IP_VERSION, 4).-define(IP_MIN_HDR_LEN, 5).

DgramSize = byte_size(Dgram),case Dgram of

<<?IP_VERSION:4, HLen:4, SrvcType:8, TotLen:16, ID:16, Flgs:3, FragOff:13,TTL:8, Proto:8, HdrChkSum:16,SrcIP:32,DestIP:32, RestDgram/binary>> when HLen>=5, 4*HLen=<DgramSize ->DestIP:32, RestDgram/binary>> when HLen>=5, 4*HLen=<DgramSize ->OptsLen = 4*(HLen - ?IP_MIN_HDR_LEN),<<Opts:OptsLen/binary,Data/binary>> = RestDgram,

...end.

When Erlang/OTP?

Network components controlNetwork components controlExtreme servers

Messaging middlewareDistributed systems

Systems for big data processingBulk calculation systemsBulk calculation systems

Critical systemsEvent control and processing

Bitstream processing

When not Erlang/OTP?

UI-heavy applications

Application / business logic

Number crunchingNumber crunching

Scala devotes itself primarily to… exactly, Scala!

Scala doesn’t have an own VM und lives off the JVM

JVM is by far not established in every IT in the world

Scala‘s basis code inherits Java diseasesinherits Java diseases

Akka development concentrates primarily on Scala

Scala and Akka took over lots of Erlang concepts ☺

Doesn’t matter!Enterprise Java platform is platform is proved, reliable, fault tolerantand optimal and optimal suitable for all situations!

Exactly!Let‘s take a look at this, look at this, too

Java: fault tolerancepublic static void main(String[] args) {

PathDasher dasher = new PathDasher(null); }

# A fatal error has been detected by the Java Runtime Environment:## EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000006da97783, pid=4772, tid=3416### JRE version: 6.0_15-b03# Java VM: Java HotSpot(TM) 64-Bit Server VM (14.1-b02 mixed mode windows-amd64 )# Problematic frame:# V [jvm.dll+0x207783]

Java: JNI crash will crash the whole JVM

Erlang: fault tolerance

1> self().<0.31.0>

Erlang: fault tolerance

<0.31.0>2> 5/0.** exception error: bad argument in an arithmetic expression

in operator '/'/2called as 5 / 0called as 5 / 0

3> self().<0.34.0>4>

Erlang:supervisor trees

-module(dr_supervisor).-behaviour(supervisor).

Erlang: supervisor tree

-behaviour(supervisor).-export([start_link/1]).-export([init/1]).

start_link(Args) ->supervisor:start_link({local, ?MODULE}, ?MODULE, Args).

init(Args) ->{ok, {{one_for_one, 2, 10}, [{ok, {{one_for_one, 2, 10}, [

{session, {dr_session, start_link, [Args]}, transient, 2000, supervisor, [dr_session]}]}}.

-module(dr_session).-behaviour(supervisor).

-export([start_link/1]).

Erlang: supervisor tree

-export([start_link/1]).-export([init/1]).

start_link(Args) ->supervisor:start_link({local, ?MODULE}, ?MODULE, Args).

init(Args) ->error_logger:info_report("session started"),{ok, {{one_for_one, 2, 10}, [{ok, {{one_for_one, 2, 10}, [{server, {dr_session_server, start_link, [Args]}, transient, 2000, worker,

[dr_session_server]},{state, {dr_session_state, start_link, [Args]}, transient, 2000, worker,

[dr_session_state]},{vm, {dr_session_vm, start_link, [Args]}, transient, 2000, worker,

[dr_session_vm]}]}}.

import org.gridgain.grid.*;import org.gridgain.grid.gridify.*;import org.gridgain.grid.gridify.aop.spring.*;

public final class GridifyHelloWorldSessionExample {private GridifyHelloWorldSessionExample() { //ensure singleton}

@Gridify(taskClass = GridifyHelloWorldSessionTask.class, timeout = 3000)public static int sayIt(String phrase) {

System.out.println(phrase);

Java: distribution

System.out.println(phrase);return phrase.length();

}

public static void main(String[] args) throws GridException {if (args.length == 0) {

GridFactory.start();}else {

GridFactory.start(args[0]);}

To use other AOP implementations (such as JBoss AOP, or Spring AOP), refer to AOP Configuration documentation.The following configuration needs to be applied to enable AspectJ byte code weaving.JVM configuration should include:

try {

int phraseLen = sayIt("Hello World");

System.out.println(„number of characters is '" + phraseLen + "'.");}finally {

GridFactory.stop(true);}

}}

-javaagent:[GRIDGAIN_HOME]/libs/aspectjweaver-1.5.3.jar

Erlang: distributed

Erlang: example of multicall for code reload

%% Find object code for module Mod

{Mod, Bin, File} = code:get_object_code(Mod),

%% and load it on all nodes including this one

{ResL, _} = rpc:multicall(code, load_binary, [Mod, Bin, File,], 5000),{ResL, _} = rpc:multicall(code, load_binary, [Mod, Bin, File,], 5000),

%% and then maybe check the ResL list.

QueueConnectionFactory connFactory = new QueueConnectionFactory();QueueConnection conn = connFactory.createQueueConnection();QueueSession session = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);Queue q = new Queue("world");

Java: message exchange

Queue q = new Queue("world");QueueSender sender = session.createSender(q);TextMessage msg = session.createTextMessage();msg.setText("Hello there!");sender.send(msg);

QueueReceiver receiver = session.createReceiver(q);conn.start();Message m = receiver.receive();if (m instanceof TextMessage) {

TextMessage txt = (TextMessage) m;TextMessage txt = (TextMessage) m;}

session.close();conn.close();

Boilerplate?Even with Spring still symptom still symptom treatment

Erlang: message oriented

Erlang: message passing

Pid ! {self(), “Hello there!”},receive

{Pid, Txt} ->…

end,

VM

JVM threads are too “heavy”. Context switching is extremely expensive to have many thousands of them. Only hacks thousands of them. Only hacks such as CPS simulation over byte code manipulation provide a remedy und illusion of a remedy und illusion of lightweight threads

import kilim.Mailbox;import kilim.Pausable;import kilim.Task;

public class SimpleTask extends Task {static Mailbox<String> mb = new Mailbox<String>();

Java: „concurrency“This package comes with a bytecode transformation tool called Weaver (package: kilim.tools.Weaver) that post-processes .class fileslooking for the "throws

public static void main(String[] args) throws Exception {new SimpleTask().start();Thread.sleep(10);mb.putnb("Hello ");mb.putnb("World\n");mb.putnb("done");

}

public void execute() throws Pausable {while (true) {

looking for the "throws Pausable" annotation.

When a task needs to pause, it unwinds its stack, squirrels away all state that it'll need later on resumption. This unwinding and rewinding the stack is automatically performed by the code introduced by the Weaver.(Debug information is adjusted while (true) {

String s = mb.get();if (s.equals("done")) break;

System.out.print(s);}

System.exit(0);}

}

(Debug information is adjusted so that the transformed code can be debugged inside eclipse) This is identical to what a programmer would havewritten

Java: instance-wide garbage collector

Erlang: concurrent.Hunderts of Hunderts of thousends of lightweight VM processes per node processes per node instead of „native“ threads-> own scheduler

Erlang: heap per process -> garbage collected per process

Hot swapping

Java: ClassLoadertrees can be trees can be complex and unpredictable.Middlewareoften causesoften causeslib conflicts

Java: OSGi is invasive and imports a middleware

Java: app server fatigue is a common phenomenon after

frequent application redeploymentredeployment

Java: zero downtime systems are possible only with human support

% hot_swap:sum(Num) addiert 1 dazu1> c(hot_swap).{ok,hot_swap}

Erlang: live code upgrade

{ok,hot_swap}2> hot_swap:sum(1).2...%hot_swap.erl wurde modifiziert. Jetzt% addiert es 2 dazu……3> c(hot_swap).{ok,hot_swap}4> hot_swap:sum(1).35>

Erlang: non-stop systems arepossible and implemented

Come on!Come on!Enterprise Java offers even more scalabilityscalability

Exactly!This should also be also be considered

Java doesn‘t scale as originally expected

Hacks

Scala & Co.

Java

EnterpriseJava

Erlang: scaling

From sequential program to world-wide distribution

MulticoreProgramming

DistributedProgramming

SequentialErlang

FunctionalErlang

Frameworks

Java: Framework-itis(like others, too ☺)

Erlang: generic behaviors

Erlang/OTP: behaviors

-module(dr_session_state).-behaviour(gen_fsm).-behaviour(gen_fsm).

-export([start_link/1]).-export([init/1]).

start_link(Args) ->gen_fsm:start_link({local, ?MODULE}, ?MODULE, Args, []).

init(_Args) ->init(_Args) ->error_logger:info_report("state started"),{ok, waiting1, []}.

Erlang/OTP:behaviors

-module(dr_session_server).-behaviour(gen_server).

-export([start_link/1]).-export([init/1]).-export([code_change/3]).-export([handle_call/3]).-export([handle_cast/2]).-export([handle_cast/2]).-export([handle_info/2]).-export([terminate/2]).

-record(state, {start,player1,player2

}).

start_link(Args) ->gen_server:start_link({local, ?MODULE}, ?MODULE, [Args], []).

init(_Args) ->error_logger:info_report("server started"),process_flag(trap_exit, true),{ok, #state{}}.

Erlang/OTP: behaviors

-module(dr_gen_vm).-export([behaviour_info/1]).

behaviour_info(callbacks) ->[{init,1}];

behaviour_info(_Other) ->undefined.undefined.

NoSQL DSs made in Java don‘t implement Java standards for data access because they are impractical, and use open impractical, and use open standards instead

NoSQL DSs made in Erlangreceive many things as a gift…

Erlang: big data storage possibilities

Erlang: Dets = Disk Erlang Term Storage

{_,D} = dets:open_file(„example“), dets:delete_all_objects(D),dets:insert(D, {mama, mia}),dets:insert(D, {here, we}),dets:insert(D, {go, again}),dets:insert(D, {go, again}),dets:close(D),

Erlang: Mnesia = dets + transactions, quiries and

distributionmnesia:create_schema([node()]),mnesia:start(),mnesia:start(),mnesia:create_table(album,

[ {disc_copies, [node()] },{attributes,

record_info(fields, album)} ]),Insert = fun() ->

mnesia:write(#album{ index=A_Index,#album{ index=A_Index,

artist=A_Artist,title=A_Title } ) end,

{atomic, Result} = mnesia:transaction(Insert),…

Really? ButEnterprise Java Enterprise Java integrates everything in the world!world!

Exactly!Let‘s see…Let‘s see…

Java prefers to integrate non-natively, from afar –natively, from afar –for example per web service. In a pinch JNI will do –at own risk.at own risk.

Erlang: integrated

Erlang: ways to integration

Erlang node Pseudo-OTP

Erlang program

PortPort

OTPnode with the externalprogram

Binary data

Linked-inDriver

Externalprogram

Binary data

Erlang: example JInterfaceimport com.ericsson.otp.erlang.*;

...

OtpNode self = new OtpNode("pseudo@test");OtpNode self = new OtpNode("pseudo@test");OtpMbox mbox = self.createMbox("pingpong");OtpErlangObject o;OtpErlangTuple msg;OtpErlangPid from;

while (true) {try {o = mbox.receive();if (o instanceof OtpErlangTuple) {

msg = (OtpErlangTuple)o;msg = (OtpErlangTuple)o;from = (OtpErlangPid)(msg.elementAt(0));mbox.send(from, msg.elementAt(1));

}catch (Exception e) {...

}}

Erlang: example JInterface

-module(pongclient).-export([pong/0]).

pong() ->{pingpong, "pseudo@test“} ! {self(), "ball"},receive

Result ->io:format("What comes back is : ~p~n", [Result])

end.

And even I can do web services these days ☺

Stop!Stop!I am constrained to the JVM!Period.Period.

BEAM is not an option for every IT

Erjang – Erlang on the JVM. It can already

boot some big Erlangsystems. It’s under systems. It’s under

development.I do help ☺

Right tool for the job

Thank you

Recommended