Date post: | 13-Jul-2015 |
Category: |
Technology |
Upload: | antoniogarrote |
View: | 2,031 times |
Download: | 0 times |
Kilim-Clojure integration
Message Passing Concurrency in Clojure usingKilim
Antonio Garrote
Forward
November 7, 2011
Kilim-Clojure integration
Clojure’s Concurrency Model
JVM thread basic autonomous work unit
Java shared memory explicit communication primitives
Immutable data structures + implicit coordinationmechanisms (STM, Refs)
Kilim-Clojure integration
Message Passing Communication
1 % Termite Scheme benchmarks r i n g . e r l2 make r e l a y ( Next ) −>3 r e c e i v e4 K when K > 0 −>5 Next ! K − 1 ,6 make r e l a y ( Next ) ;7 K −>8 Next ! K9 end .
1011 loop (K, Current , N) when N > 1 −>12 loop (K, spawn ( r i ng , make re l ay , [ Cu r r en t ] ) ,N − 1 ) ;1314 loop (K, Current , ) −>15 s e l f ( ) ! K,16 make r e l a y ( Cu r r en t ) .1718 % N = number p r o c e s s e s19 % K = number o f message exchanges20 r i n g (N, K) −>21 loop (K, s e l f ( ) , N) .
Kilim-Clojure integration
Message Passing Communication
1
5
3
N2
4 6
K
N = 100K ,K = 0518ms, 5µs process creation
N = 100K ,K = 1M759ms, 0.76µs local msg . send .
Kilim-Clojure integration
Message Passing Communication
How does Erlang do it?
User level processes executing recursive functions
VM preemptive scheduling
One heap/stack per process, no global heap
Tail call optimisation
More predictable GC behaviour
Kilim-Clojure integration
Efficient implementation of message passing concurrency in theJava Virtual Machine?
Kilim-Clojure integration
Kilim
“Kilim is a message-passing framework for Java that providesultra-lightweight threads and facilities for fast, safe, zero-copymessaging between these threads”
https://github.com/kilim/kilim
2006 Sriram Srinivasan, Opera Group Cambridge University
Current version 0.72
Kilim-Clojure integration
Kilim Tasks
1 p u b l i c c l a s s ExampleTask ex t end s Task {23 p u b l i c vo i d e x e cu t e ( ) throws Pausab l e {4 doS tu f f ( ) ;5 p u s a b l e S t u f f ( ) ; // throws Pausab l e6 moreStu f f ( ) ;7 }89 }
Task
Worker
Thread
Scheduler
notify
execute
Kilim-Clojure integration
Kilim Weaving: Bytecode Transformation
Additional step after compilation
Transforms pausable methods
Creates a custom class to store the task state
Associates a Fiber object, tracks task’s stack
Transformed code returns immediately if the task is paused
Worker threads can resume the execution of paused stacksunwinding the associated fiber stack
Kilim-Clojure integration
Kilim Weaving: Bytecode Transformation
1 p u b l i c vo i d e x e cu t e ( F i b e r f i b e r ) throws Pausab l e {2 sw i t ch ( f i b e r . pc ) {3 ca se 0 : goto START;4 ca se 1 : goto PAUSABLE CALL ;5 }6 START:7 doS tu f f ( ) ;8 PAUSABLE CALL :9 f i b e r . down ( ) ;
10 p u s a b l e S t u f f ( f i b e r ) ; // throws Pausab l e11 f i b e r . up ( ) ;12 sw i t c h ( f i b e r . s t a t u s ) {13 case NOT PAUSING NO STATE :14 goto RESUME;15 ca se NOT PAUSING HAS STATE :16 r e s t o r e s S t a t e ( s t a t e ) ;17 goto RESUME;18 ca se PAUSING NO STATE :19 c ap t u r eS t a t e ( s t a t e ) ;20 r e t u r n ;21 ca se PAUSING HAS STATE :22 r e t u r n ;23 }24 RESUME:25 moreStu f f ( ) ;26 }
Kilim-Clojure integration
Kilim Tasks: Execution
Pausable()
Fiber Pausable()
Fiber Pausable()
down()
down()
StateObj.(1)
StateObj.(2)
StateObj.(3)
Fiber.stack
currentState
currentState
currentState
Pause Normal Return
up()
Kilim-Clojure integration
Kilim Messages
Buffered mailboxes
Allows asynchronous communication between tasks
Blocking / not blocking interface
Polling interface
Kilim-Clojure integration
Kilim-Clojure Integration (first attempt)
Modified version of Clojure’s compiler
Clojure’s functions executed as Kilim’s tasks
Weaving performed at run-time
https://github.com/antoniogarrote/clojure/tree/kilim
Kilim-Clojure integration
Kilim-Clojure Integration (second attempt)
Clojure library
[clj-kilim ”0.2.0-SNAPSHOT”]
Doc: http://antoniogarrote.github.com/clojure kilim/
Source: https://github.com/antoniogarrote/clojure kilim
Kilim-Clojure integration
Introduction
Java Class
Clojure Compiler
Compiles bytecode
clj-kilim
Java instrumentation
Kilim Weaver
Bytecode Transformation
Class Loader
Weaved Java Class
Bytecode Transformation
Kilim-Clojure integration
Kilim-Clojure Integration: API
1 ( def−pausab le y i e l d i n g− f n [ mbox ]2 (mbox−get−pausable mbox ) )345 ( def−pausab le task− fn1 [ ]6 . . .7 ( c a l l−pau sab l e y i e l d i n g− f n ambox )8 . . . )9
10 ( de f task− fn2 ( pau sab l e [ ] . . . ) )111213 ( t a sk− s t a r t task− fn1 )14 ( t a sk− s t a r t task− fn2 )
Kilim-Clojure integration
Kilim-Clojure Integration
Demo
Kilim-Clojure integration
Performance
Kilim-Clojure integration
Ring example again1 ( de fn ˆ{ : p au sab l e t r u e} make−relay [ ˆ k i l i m . Mai lbox s e l f2 ˆ k i l i m . Mai lbox next3 ˆ k i l i m . Mai lbox f i n a l ]4 ( l oop [ k ( r e c e i v e s e l f ) ]5 ( i f (> k 0)6 ( do7 ( ! nex t ( dec k ) )8 ( r e c u r ( . ge t s e l f ) ) )9 ( do
10 ( ! nex t ( dec k ) )11 (when ( not ( n i l ? f i n a l ) )12 ( ! f i n a l t r u e ) ) ) ) ) )131415 ( de fn make−loop [ n k ]16 ( l e t [ ˆ k i l i m . Mai lbox f i r s t−ma i l b o x ( k i l i m . Mai lbox . )17 ˆ k i l i m . Mai lbox f i n a l−ma i l box ( k i l i m . Mai lbox . ) ]18 ( l oop [ c u r r e n t f i r s t−ma i l b o x19 n n ]20 ( i f (> n 1)21 ( r e c u r22 ( spawn ( pau sab l e [ ˆ k i l i m . Mai lbox s e l f ]23 ( make−relay s e l f c u r r e n t n i l ) ) )24 ( dec n ) )25 ( do ( spawn ( pau sab l e [ ˆ k i l i m . Mai lbox ]26 ( make−relay f i r s t−ma i l b o x c u r r e n t f i n a l−ma i l box ) ) )27 ( ! f i r s t−ma i l b o x k )28 ( . getb f i n a l−ma i l box ) ) ) ) ) )
Kilim-Clojure integration
Performance
N = 100K ,K = 01264ms, 12µs process creation
N = 100K ,K = 1M3276ms, 3µs local msg . send .
Kilim-Clojure integration
Conclusions
Efficient message passing possible in the JVM thanks to Kilim
Clojure can be a nice match for Kilim (immutable messages,run-time weaving)
Benefits of asynchronous evented code with a nicer interface
Limitations: non-preemptive
Way to go?
Improve performanceAdd distribution