Tail-Recursion Modulo...

24
TRMC ? Tweaking the Garbage-Collector Tail-Recursion Modulo Constructor Frédéric Bour Oct 27, 2014 Frédéric Bour Tail-Recursion Modulo Constructor

Transcript of Tail-Recursion Modulo...

Page 1: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

Tail-Recursion Modulo Constructor

Frédéric Bour

Oct 27, 2014

Frédéric Bour Tail-Recursion Modulo Constructor

Page 2: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

Plan

1 TRMC ?List.mapManual rewritingImplementation details

2 Tweaking the Garbage-Collector

Page 3: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

List.map

l e t rec map f = funct ion| [ ] −> [ ]| x : : x s −> f x : : map f xs

simple, elegant, useful, . . .but not tail-recursive: list constructed when returning.

Data accumulated on the stack is proportional to the length of thelist.

Frédéric Bour Tail-Recursion Modulo Constructor

Page 4: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

List.map

l e t rec map f = funct ion| [ ] −> [ ]| x : : x s −> f x : : map f xs

simple, elegant, useful, . . .but not tail-recursive: list constructed when returning.

Data accumulated on the stack is proportional to the length of thelist.

Frédéric Bour Tail-Recursion Modulo Constructor

Page 5: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

Quest for a tail-recursive List.map

Such implementations exist, for instance in Core.The resulting code is much more complex and unnatural.

Could the compiler do this job?Tail-recursion modulo constructor.

0001538: feature wish: tail recursion modulo consturn any constructor application with a recursive-call into atail-recursive call

A candidate:

f x : : map f xs

Frédéric Bour Tail-Recursion Modulo Constructor

Page 6: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

Quest for a tail-recursive List.map

Such implementations exist, for instance in Core.The resulting code is much more complex and unnatural.

Could the compiler do this job?Tail-recursion modulo constructor.

0001538: feature wish: tail recursion modulo consturn any constructor application with a recursive-call into atail-recursive call

A candidate:

f x : : map f xs

Frédéric Bour Tail-Recursion Modulo Constructor

Page 7: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

Quest for a tail-recursive List.map

Such implementations exist, for instance in Core.The resulting code is much more complex and unnatural.

Could the compiler do this job?Tail-recursion modulo constructor.

0001538: feature wish: tail recursion modulo consturn any constructor application with a recursive-call into atail-recursive call

A candidate:

f x : : map f xs

Frédéric Bour Tail-Recursion Modulo Constructor

Page 8: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

Intuition

Construct the resulting list before the recursive callPut a placeholder for the not-yet-computed tail of the listRewrite the function to take this result value as an argumentChange all return points to mutate this block instead ofreturning the value

Frédéric Bour Tail-Recursion Modulo Constructor

Page 9: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

Rewriting manually

l e t rec map f = funct ion| [ ] −> [ ]| x : : x s −> f x : : map f xs

; ;

Frédéric Bour Tail-Recursion Modulo Constructor

Page 10: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

Rewriting manually

l e t rec map f = funct ion| [ ] −> [ ]| x : : x s −> f x : : map f xs

and map_1 r e s u l t f = funct ion| [ ] −> r e s u l t . 1 <− [ ]| x : : x s −> l e t nex t = f x : : _ in

r e s u l t . 1 <− nex t ;map_1 next f x s (∗ t a i l c a l l ! ∗)

; ;

Frédéric Bour Tail-Recursion Modulo Constructor

Page 11: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

Rewriting manually

l e t rec map f = funct ion| [ ] −> [ ]| x : : x s −> l e t r e s u l t = f x : : _ in

map_1 r e s u l t f x s ;r e s u l t

and map_1 r e s u l t f = funct ion| [ ] −> r e s u l t . 1 <− [ ]| x : : x s −> l e t nex t = f x : : _ in

r e s u l t . 1 <− nex t ;map_1 next f x s (∗ t a i l c a l l ! ∗)

; ;

Frédéric Bour Tail-Recursion Modulo Constructor

Page 12: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

Implementation details

Done at lambda-level rather than surface language.Code is duplicated for each position that can be mutated.Rewrite only what appears syntactically as a TRMC-call (notfollowing let-bindings, etc).Impact on the semantic:

actual evaluation order of arguments is affected (TRMCevaluated last), this is allowed in OCamlprograms that would fail with a stack overflow might nowsucceed. . . or consume all available memory.

Frédéric Bour Tail-Recursion Modulo Constructor

Page 13: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

What breaks

Potential multicore GCs. Fields non-mutable at the typed-levelare now the results of some mutationsDelimCC, Hansei. . .

Frédéric Bour Tail-Recursion Modulo Constructor

Page 14: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

Sketch of the rewriting pass

1 Traverse lambda-code,2 For each recursive let-bindings {f , g , . . .},3 For each function f ,4 For each leaf that is a TRMC-call:

identify field index igenerate a function fireplace call by a placeholderbind the value constructed to a variablecall fi with the original arguments & the fresh variablereturn the variable

Frédéric Bour Tail-Recursion Modulo Constructor

Page 15: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

Generating derived functions

For generating fi :

1 Start from f definition2 Add an additional parameter r3 For each leaf in tail-position:

if it is a tail-rec call to g , rewrite to giif it is a trmc call to g ,

identify field index i ′

replace call by a placeholderbind the value constructed to a variablestore value in ith field of rcall gi′ , the call is in tail-position

otherwise, directly store the result of the computation in ithfield of r

Frédéric Bour Tail-Recursion Modulo Constructor

Page 16: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

List.mapManual rewritingImplementation details

Performance

1000 10000 100000 1000000 10000000

Length of list

0,001

0,01

0,1

1

10

100

Tim

e pe

r ru

n (m

illis

econ

ds)

NaiveTRMC

Frédéric Bour Tail-Recursion Modulo Constructor

Page 17: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

Plan

1 TRMC ?List.mapManual rewritingImplementation details

2 Tweaking the Garbage-Collector

Page 18: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

Reminder about OCaml-GC

Heap is split in a fixed size minor heap and a growing majorheap.Allocations are done in minor-heap.

When minor heap is full, it is collected independently.This is correct if there is no reference from major heap tominor heapThis can’t always be guaranteed, so OCaml keeps track of allmutations which might break this invariant: that’s the writebarrier, candidates are stored in the remembered set.Collection is done starting from roots ∪ this set.

Frédéric Bour Tail-Recursion Modulo Constructor

Page 19: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

Reminder about OCaml-GC

Heap is split in a fixed size minor heap and a growing majorheap.Allocations are done in minor-heap.When minor heap is full, it is collected independently.This is correct if there is no reference from major heap tominor heapThis can’t always be guaranteed, so OCaml keeps track of allmutations which might break this invariant: that’s the writebarrier, candidates are stored in the remembered set.

Collection is done starting from roots ∪ this set.

Frédéric Bour Tail-Recursion Modulo Constructor

Page 20: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

Reminder about OCaml-GC

Heap is split in a fixed size minor heap and a growing majorheap.Allocations are done in minor-heap.When minor heap is full, it is collected independently.This is correct if there is no reference from major heap tominor heapThis can’t always be guaranteed, so OCaml keeps track of allmutations which might break this invariant: that’s the writebarrier, candidates are stored in the remembered set.Collection is done starting from roots ∪ this set.

Frédéric Bour Tail-Recursion Modulo Constructor

Page 21: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

Observations about TRMC-mutations

Mutation will happen (ignoring exceptions)Mutation will happen only once (ignoring delim-cc)

A reference from major-heap to minor-heap will be createdonly if a minor-collection was done since the beginning ofTRMC recursion.

Frédéric Bour Tail-Recursion Modulo Constructor

Page 22: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

Observations about TRMC-mutations

Mutation will happen (ignoring exceptions)Mutation will happen only once (ignoring delim-cc)A reference from major-heap to minor-heap will be createdonly if a minor-collection was done since the beginning ofTRMC recursion.

Frédéric Bour Tail-Recursion Modulo Constructor

Page 23: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

Special handling of TRMC-mutations

Idea:

use a distinguished value t for the placeholdersnever go through the write barrier during TRMC-mutationduring collection, if a field being moved to major-heap is equalto t, place the field in the remembered set.

Frédéric Bour Tail-Recursion Modulo Constructor

Page 24: Tail-Recursion Modulo Constructorgallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf · Tail-Recursion Modulo Constructor FrédéricBour Oct27,2014 Frédéric Bour

TRMC ?Tweaking the Garbage-Collector

Performance improvements

1000 10000 100000 1000000 10000000

Length of list

0,001

0,01

0,1

1

10

100

1000

Tim

e pe

r ru

n (m

illis

econ

ds)

NaiveTRMCTRMC-GCCore

Frédéric Bour Tail-Recursion Modulo Constructor