jvmcsp
play

JVMCSP Approaching Billions of Processes on a Single-Core JVM Cabel - PowerPoint PPT Presentation

JVMCSP Approaching Billions of Processes on a Single-Core JVM Cabel Shrestha & Ma; B. Pedersen Last Time (CPA 2014) We presented ProcessJ (Process-Oriented Language) HandcraEed JVM runFme: LiteProc (proof of concept) ~


  1. JVMCSP ì Approaching Billions of Processes on a Single-Core JVM Cabel Shrestha & Ma; B. Pedersen

  2. Last Time … (CPA 2014) We presented • ProcessJ (Process-Oriented Language) • HandcraEed JVM runFme: LiteProc (proof of concept) • ~ 95,000,000 concurrent processes

  3. This Time … (CPA 2016) ì An implemented code generator in ProcessJ ì New improved runFme ì Faster ì Handles more processes

  4. From ProcessJ to Java Bytecode ì ProcessJ compiler produces Java source code. ì Compiled with Javac. ì Instrumented with ASM byte code manipulaFon tool. ì Jar’d together with runFme

  5. Runtime (Scheduler) ì User-level scheduler ì CooperaFve, non-preempFve. Queue<Process> processQueue; ... // enqueue one or more processes to run while (!processQueue.isEmpty()) { Process p = processQueue.dequeue(); if (p.ready()) p.run(); if (!p.terminated()) processQueue.enqueue(p); }

  6. Essential Questions ì How does a procedure yield? ì When does a procedure yield and who decides? ì How is a procedure restarted aEer yielding? ì How is local state maintained? ì How are nested procedure calls handled when the innermost procedure yields?

  7. How does a procedure yield? When does it yield and who decides? CPA 2014 version JVMCSP ì Yields by calling return ì Yields by calling return ì Procedures voluntarily ì Procedures voluntarily give up the CPU at give up the CPU at synchronizaFon points synchronizaFon points Reads, writes, barrier syncs, alts, Fmer operaFons: procedure returns to scheduler (Bytecode: return)

  8. How is a procedure restarted? CPA 2014 JVMCSP ì Procedure is simply ì Procedure is simply recalled by scheduler recalled by scheduler ì How do we ensure that local state survives? ì How do we avoid restart from the top of the code?

  9. Preservation of Local State CPA 2014 JVMCSP ì An acFvaFon record ì All locals and fields have structure was used to been converted to store locals. fields. ì Each procedure is a class ì Each procedure is a with an acFvaFon stack. class.

  10. Correct Resumption CPA 2014 JVMCSP ì Insert an empty switch ì Insert an empty switch statement at the top of statement at the top of the code to hold jumps. the generated code (source) to hold jumps. ì Instrument (by hand in decompiled bytecode) ì Instrument (by using jumps to the correct ASM) jumps to the resume points. correct resume points. A resume point counter (called runlabel ) is kept for each process to remember where to conFnue.

  11. Correct Resumption (Abstract) ì Each synchronizaFon point is a yield point: L1: 
 .. synchronize (read, sync etc) 
 if (succeeded) 
 yield(L2); // return to L2 when resumed else 
 yield(L1); // return to L1 when resumed 
 L2:

  12. Correct Resumption (Generated Code) ì Each synchronizaFon point is a yield point: label(1); 
 .. synchronize (read, sync etc) 
 if (succeeded) 
 yield(2); else 
 yield(1); 
 label(2); yield(i) will set the runlabel for the process object to i .

  13. Correct Resumption (ASM Instrumentation) label(1); 
 61: aload_0 
 .. synchronize 
 62: iconst_1 
 if (succeeded) 
 63: invokevirtual label/(I)V 
 yield(2); 
 66: ... 
 else 
 ... yield(1); 
 label(2); 61: nop 
 62: nop 
 63: nop 
 Dummy invocaFons 64: nop 
 are removed. 65: nop 
 66: ... 
 ...

  14. Correct Resumption (ASM Instrumentation) ì This address (61) is associated with runlabel 1. ì Upon resumpFon, the code must jump to address 61 if the runlabel is 1. 61 : nop 
 62: nop 
 63: nop 
 64: nop 
 65: nop 
 66: ... 
 ...

  15. Correct Resumption (Generated Code) Generated Java Code (top of the code) Equivalent Java Bytecode 0: aload 0 
 switch (runlabel) { 
 1: getfield runLabel 
 case 0: resume(0); 
 4: tableswitch // 0 to 2 
 break ; 
 0: 32 
 1: 35 
 case 1: resume(1); 
 2: 43 
 break ; 
 default: 48 
 32: goto 48 
 ... 
 35: aload 0 
 case k: resume(k); 
 36: iconst 1 
 break ; 
 37: invokevirtual resume/(I)V 
 40: goto 48 
 } 
 ...

  16. Correct Resumption (ASM Instrumentation) 0: aload 0 
 0: aload 0 
 1: getfield runLabel 
 1: getfield runLabel 
 4: tableswitch // 0 to 2 
 4: tableswitch // 0 to 2 
 0: 32 
 0: 32 
 1: 35 
 1: 35 
 2: 43 
 2: 43 
 default: 48 
 default: 48 
 32: goto 48 
 32: goto 48 
 35: aload 0 
 35: nop 
 Runlabel 1 36: iconst 1 
 36: nop 
 @ of runlabel 1 37: invokevirtual resume/(I)V 
 37: goto 61 
 40: goto 48 
 40: goto 48 
 ... ... Placeholder code replaced by nop instrucFons and gotos adjusted to the correct label addresses

  17. Correct Suspension yield(2); 
 78: aload_0 
 79: iconst_2 
 80: invokevirtual yield/(I)V 
 Becomes 83: goto 100 
 ... 100: return Shared return point yield(2) sets the runLabel field.

  18. From ProcessJ to Java proc void foo(pt 1 pn 1 , ..., tp n pn n ) { 
 ... lt 1 ln 1 ; Locals ... lt m ln m ; ... statements ... Code }

  19. 
 From ProcessJ to Java public class A { 
 public void run() { 
 public static class foo 
 switch (runlabel) { 
 extends PJProcess { 
 case 0: resume(0); 
 pt 1 pn 1 ; 
 break ; 
 pt 2 pn 2 ; 
 case 1: resume(1); 
 ... 
 break ; 
 lt 1 ln 1 ; 
 ... 
 ... 
 case k: resume(k); 
 lt m ln m ; break ; 
 } 
 public foo(pt 1 pn 1 , ..., 
 ... Statements 
 tp n pn n ) { 
 } 
 this .pn 1 = pn 1 ; 
 } 
 ... 
 } this .pn n = pn n ; 
 } Process foo lives in a file called A.pj

  20. 
 From ProcessJ to Java public class A { 
 public void run() { 
 public static class foo 
 switch (runlabel) { 
 extends PJProcess { 
 case 0: resume(0); 
 pt 1 pn 1 ; 
 break ; 
 Parameters pt 2 pn 2 ; 
 case 1: resume(1); 
 ... 
 break ; 
 lt 1 ln 1 ; 
 ... 
 locals ... 
 case k: resume(k); 
 lt m ln m ; break ; 
 } 
 ... Statements 
 } 
 } 
 } Locals and Parameters are turned into fields

  21. 
 From ProcessJ to Java public class A { 
 public void run() { 
 public static class foo 
 switch (runlabel) { 
 extends PJProcess { 
 case 0: resume(0); 
 pt 1 pn 1 ; 
 break ; 
 pt 2 pn 2 ; 
 case 1: resume(1); 
 ... 
 break ; 
 lt 1 ln 1 ; 
 ... 
 ... 
 case k: resume(k); 
 lt m ln m ; break ; 
 } 
 public foo(pt 1 pn 1 , ..., 
 Constructor ... Statements 
 tp n pn n ) { 
 } 
 this .pn 1 = pn 1 ; 
 } 
 ... 
 } this .pn n = pn n ; 
 } Constructors set the parameters

  22. 
 From ProcessJ to Java Run method public class A { 
 public void run() { 
 public static class foo 
 switch (runlabel) { 
 extends PJProcess { 
 case 0: resume(0); 
 pt 1 pn 1 ; 
 break ; 
 pt 2 pn 2 ; 
 case 1: resume(1); 
 ... 
 break ; 
 lt 1 ln 1 ; 
 ... 
 ... 
 case k: resume(k); 
 lt m ln m ; break ; 
 } 
 public foo(pt 1 pn 1 , ..., 
 ... Statements 
 tp n pn n ) { 
 } 
 this .pn 1 = pn 1 ; 
 } 
 ... 
 } this .pn n = pn n ; 
 } run method is called by the scheduler

  23. 
 From ProcessJ to Java public class A { 
 public void run() { 
 public static class foo 
 switch (runlabel) { 
 extends PJProcess { 
 case 0: resume(0); 
 pt 1 pn 1 ; 
 break ; 
 pt 2 pn 2 ; 
 case 1: resume(1); 
 ... 
 break ; 
 Jump switch lt 1 ln 1 ; 
 ... 
 ... 
 case k: resume(k); 
 lt m ln m ; break ; 
 } 
 public foo(pt 1 pn 1 , ..., 
 ... Statements 
 tp n pn n ) { 
 } 
 this .pn 1 = pn 1 ; 
 } 
 ... 
 } this .pn n = pn n ; 
 } resume() calls replaced by jumps to label() s

  24. 
 From ProcessJ to Java public class A { 
 public void run() { 
 public static class foo 
 switch (runlabel) { 
 extends PJProcess { 
 case 0: resume(0); 
 pt 1 pn 1 ; 
 break ; 
 pt 2 pn 2 ; 
 case 1: resume(1); 
 ... 
 break ; 
 lt 1 ln 1 ; 
 ... 
 ... 
 case k: resume(k); 
 lt m ln m ; break ; 
 } 
 public foo(pt 1 pn 1 , ..., 
 ... Statements 
 tp n pn n ) { 
 } 
 this .pn 1 = pn 1 ; 
 } 
 ... 
 } this .pn n = pn n ; 
 } Code is translated ProcessJ + generated primiFves

  25. Yielding in Nested Calls CPA 2014 JVMCSP ì Maintain a complex ì Calls of procedures acFvaFon stack. that may yield ì Constant creaFon and destrucFon of acFvaFon f(x) becomes records. ì ResumpFons started from par { 
 the outermost procedure and worked its way in f(x) 
 }

  26. JVMCSP Runtime Componenets ì PJProcess represents a process. ì PJPar represents a par block. ì PJChannel represetns a channel. ì PJOne2OneChannel, PJOne2ManyChannel, PJMany2OneChannel, PJMany2ManyChannel ì PJBarrier represents a barrier. ì PJTimer represents a Fmer. ì PJAlt represents an alt.

  27. Par Blocks final PJPar par1 = new PJPar(2, this); 
 par { 
 ( new A.f(8) { 
 f(8); 
 public void finalize() { 
 par1.decrement(); 
 g(9); 
 } 
 } }).schedule(); 
 ( new A.g(8) { 
 public void finalize() { 
 par1.decrement(); 
 becomes } 
 }).schedule(); 
 setNotReady(); 
 yield(1); 
 label(1);

  28. Par Blocks Create new PJPar object final PJPar par1 = new PJPar(2, this); 
 with 2 processes ( new A.f(8) { 
 public void finalize() { 
 par1.decrement(); 
 } 
 }).schedule(); 
 ( new A.g(8) { 
 public void finalize() { 
 par1.decrement(); 
 } 
 }).schedule(); 
 setNotReady(); 
 yield(1); 
 label(1);

Recommend


More recommend