Post on 16-Dec-2015
Implementation and Evaluation of a Safe Runtime
in Cyclone
Matthew FluetCornell University
Daniel WangPrinceton University
Introduction
Web-based applications• Written in high-level, safe languages
• C#, Java, Perl, PHP, Python, Tcl
• Automatic memory management
Application servers• Written in unsafe languages
• Host applications via interpreters (written in C)
Introduction
Long-term goal: a complete web-application server written in a safe language
Short-term goal: a complete interpreter written in a safe language• Implementing the core of an interpreter is not
in itself a significant challenge
• Implementing the runtime system is a challenge
Outline
A Scheme interpreter in Cyclone• Why Scheme
• Key Features of Cyclone
• Core Scheme Interpreter
• Garbage Collector
Performance Evaluation Conclusion
Why Scheme?
Ease of implementation• Core interpreter loop is only ~500 lines
• Rely on an external Scheme front-end to expand the full Scheme language into a core Scheme subset
• Features desirable for web programming
Key Features of Cyclone
Safe, C-like language• Static type- and control-flow analysis
Intended for systems programming• Data representation
• Resource management
Region-based memory management• Static, lexical, dynamic, heap, unique, …
Simple Copying Collector
From-space and To-space• Natural correspondence with regions
• LIFO discipline of lexical regions insufficient
• Dynamic regions appear to be sufficient
Forwarding pointers
Dynamic Regions
Non-nested lifetimes Manual creation and deallocation Represented by unique pointer (key)
Unique pointer ≡ Capability• Access the region
Dynamic Regions
Operations• new: create a fresh dynamic region
• Produces unique key
• open: open a dynamic region for allocation• Temporarily consumes key
• free: deallocate a dynamic region• Permanently consumes key
GC and Dynamic Regions
. . .// create the to-space’s keylet NewDynamicRegion {<`to> to_key} = new_ukey();state_t<`to> = to_state;// open the from-space’s key{ region from_r = open_ukey(from_key); // open the to-space’s key { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } }// free the from-spacefree_ukey(from_key);. . .
GC and Dynamic Regions
. . .// create the to-space’s keylet NewDynamicRegion {<`to> to_key} = new_ukey();state_t<`to> = to_state;// open the from-space’s key{ region from_r = open_ukey(from_key); // open the to-space’s key { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } }// free the from-spacefree_ukey(from_key);. . .
GC and Dynamic Regions
. . .// create the to-space’s keylet NewDynamicRegion {<`to> to_key} = new_ukey();state_t<`to> = to_state;// open the from-space’s key{ region from_r = open_ukey(from_key); // open the to-space’s key { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } }// free the from-spacefree_ukey(from_key);. . .
GC and Dynamic Regions
. . .// create the to-space’s keylet NewDynamicRegion {<`to> to_key} = new_ukey();state_t<`to> = to_state;// open the from-space’s key{ region from_r = open_ukey(from_key); // open the to-space’s key { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } }// free the from-spacefree_ukey(from_key);. . .
GC and Dynamic Regions
. . .// create the to-space’s keylet NewDynamicRegion {<`to> to_key} = new_ukey();state_t<`to> = to_state;// open the from-space’s key{ region from_r = open_ukey(from_key); // open the to-space’s key { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } }// free the from-spacefree_ukey(from_key);. . .
Forwarding Pointers
What is the type of a forwarding pointer?
A pointer to a Value in To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space
Forwarding Pointers
What is the type of a forwarding pointer?
A pointer to a Value in To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space, …
Dynamic Region Sequences
Introduce a new type constructor mapping region names to region names
typedef _::R next_rgn<ρ::R>
Although the region names ρ and next_rgn<ρ> are related, the lifetimes of their corresponding regions are not
Dynamic Region Sequences
Operations• new, open, free: as for dynamic regions
• next: create next_rgn<ρ> from ρ
Dynamic Region Sequences
Operations• next: create next_rgn<ρ> from ρ
Have an infinite supply of region names• next will create a fresh dynamic region key
Need a linear supply of keys• Use Cyclone’s unique pointers
Dynamic Region Sequences
Operations• next: create next_rgn<ρ> from ρ
A dynamic region sequence is a pair• key: a dynamic region key
• gen: a unique pointer Unique pointer ≡ Capability
• Produce the next_rgn<ρ> key and gen
• Consumed by next
Dynamic Region Sequences
Operations• new: create a fresh dynamic region sequence
• Produces unique key and gen
• next: creates next dynamic region sequence• Produces unique key and gen
• Permanently consumes gen
GC and Dynamic Region Sequences
gcstate_t doGC(gcstate_t gcs) { // unpack the gc state let GCState{<`r> DRSeq {from_key, from_gen}, from_state} = gcs; // generate the to-space let DRSeq{to_key, to_gen} = next_drseq(from_gen); state_t<next_rgn<`r>> to_state; // open the from-space { region from_r = open_ukey(from_key); // open the to-space { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } // pack the new gc state gcs = GCState{DRSeq{to_key, to_gen}, to_state}; } // free the from space free_ukey(from_key); return gcs;}
GC and Dynamic Region Sequences
gcstate_t doGC(gcstate_t gcs) { // unpack the gc state let GCState{<`r> DRSeq {from_key, from_gen}, from_state} = gcs; // generate the to-space let DRSeq{to_key, to_gen} = next_drseq(from_gen); state_t<next_rgn<`r>> to_state; // open the from-space { region from_r = open_ukey(from_key); // open the to-space { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } // pack the new gc state gcs = GCState{DRSeq{to_key, to_gen}, to_state}; } // free the from space free_ukey(from_key); return gcs;}
GC and Dynamic Region Sequences
gcstate_t doGC(gcstate_t gcs) { // unpack the gc state let GCState{<`r> DRSeq {from_key, from_gen}, from_state} = gcs; // generate the to-space let DRSeq{to_key, to_gen} = next_drseq(from_gen); state_t<next_rgn<`r>> to_state; // open the from-space { region from_r = open_ukey(from_key); // open the to-space { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } // pack the new gc state gcs = GCState{DRSeq{to_key, to_gen}, to_state}; } // free the from space free_ukey(from_key); return gcs;}
GC and Dynamic Region Sequences
gcstate_t doGC(gcstate_t gcs) { // unpack the gc state let GCState{<`r> DRSeq {from_key, from_gen}, from_state} = gcs; // generate the to-space let DRSeq{to_key, to_gen} = next_drseq(from_gen); state_t<next_rgn<`r>> to_state; // open the from-space { region from_r = open_ukey(from_key); // open the to-space { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } // pack the new gc state gcs = GCState{DRSeq{to_key, to_gen}, to_state}; } // free the from space free_ukey(from_key); return gcs;}
GC and Dynamic Region Sequences
gcstate_t doGC(gcstate_t gcs) { // unpack the gc state let GCState{<`r> DRSeq {from_key, from_gen}, from_state} = gcs; // generate the to-space let DRSeq{to_key, to_gen} = next_drseq(from_gen); state_t<next_rgn<`r>> to_state; // open the from-space { region from_r = open_ukey(from_key); // open the to-space { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } // pack the new gc state gcs = GCState{DRSeq{to_key, to_gen}, to_state}; } // free the from space free_ukey(from_key); return gcs;}
GC and Dynamic Region Sequences
Comparison with type-preserving GCs• Interpreter can be written in a trampoline
style, rather than continuation passing style
• Intuitive typing of forwarding pointers
Performance Evaluation
Interpreter Runtime
Cyclone (Safe GC)
Safe Safe
Cyclone (BDW GC)
Safe Unsafe
SISC (Sun JVM)
Safe Unsafe
MzScheme (BDW GC)
Unsafe Unsafe
Performance Evaluation
Normalized Execution Times
0
0.5
1
1.5
2
tak deriv puzzle fft traverse
Cyclone (Safe GC)
Cyclone (BDW GC)
SISC
MzScheme
Performance Evaluation
Maximum Working Set
0
1000
2000
3000
4000
5000
6000
tak
deriv
puzzle fft
trave
rse
Vir
tual
Pag
es Cyclone (Safe GC)
Cyclone (BDW GC)
SISC
MzScheme
Size of Unsafe Code
Interpreter
(lines of code)
Runtime System
(lines of code)
Cyclone
(Safe GC)0 1800
Cyclone
(BDW GC)0 9000
SISC
(Sun JVM)0 229,100
MzScheme
(BDW GC)31,000 9000