Fast & Functional

ideas from the roc compiler

Folkert de Vries

Roc

a fast, friendly, functional language

Performance Ceiling

x + 1

C

 

1 instruction

Python

 

>> 1 instruction

Memory

allocation

bookkeeping

representation

Platforms & Applications

roc applications run on a platform

 

a "domain-specific runtime"

the platform defines

shape of main

IO primitives

(de)allocation

allocation & the OS

malloc

free

don't bother freeing

a surprisingly OK solution for short-lived applications

Nea: never allocate

a webserver for roc that does not malloc/free

Idea

make memory allocation flexible

without bothering most users

problem: when is the application done with memory?

refcounting and reuse

drop-specialized

beans

perceus

refcounting: the papers

refcounting: the idea

rc

your actual data

inc and dec

m = "Hello Delft!" # rc == 1
# inc m 2          # rc == 3
t = (m , m)        # rc == 3
# ~ t gets used ~
# dec m            # rc == 2
# dec t.0          # rc == 1
# dec t.1          # rc == 0
# free t.1

breaking the cycle

RC  cannot break cycles

 

  • due to mutation, e.g. doubly-linked list
  • due to laziness, e.g. fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

opportunistic mutation

List.reverse = \list ->
    if refcount list == 1 then
		#reverseInPlace list
    else
   		#reverseInPlace (List.clone list)

idea

  • have no complex runtime system
  • exploit exclusive ownership

a function at runtime

f : (I64 -> I64) -> I64
f = \p -> p 12
     
main = 
    y = 42

    g = \x -> x + y

    f g

how do we turn this into C?

defunctionalization

better defunctionalization

from higher order to first

f : (I64 -[ G { y: I64 } ]-> I64) -> I64
f = \p -> p 12
     
main = 
    y = 42

    g = \x -> x + y

    f g 

from higher order to first

f : (I64 -[ G { y: I64 } ]-> I64) -> I64
f = \p -> p 12

g = \x, { y } -> x + y
     
main = 
    y = 42

    f ???

from higher order to first

f : [ G { y: I64 } ] -> I64
f = \G c -> g 12 c

g = \x, { y } -> x + y
     
main = 
    y = 42
    
    f (G { y })

from higher order to first

f : [ G { y : I64 }, H {} ] -> I64
f = \closure ->
    when closure is
        G c -> g 12 c 
        H c -> h 12 c 

g = \x, { y } -> x + y
h = \x, {} -> x + 1

main = 
    y = 42
    f (if a == b then G { y } else H {})

Future Work

 

 

Simplified inference of lambda sets

(session at POPL 2024)

 

RC borrow inference for List/Str

 

 

 

Memory

allocation

bookkeeping

representation

Links

Thanks

a fast, friendly, functional language

Ideas in the roc compiler

By folkert de vries

Ideas in the roc compiler

  • 44