Bug 471371 - Lambda and closure optimisation
Summary: Lambda and closure optimisation
Status: NEW
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Golo (show other bugs)
Version: unspecified   Edit
Hardware: PC Mac OS X
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: investigate, performance
Depends on:
Blocks:
 
Reported: 2015-06-29 16:04 EDT by Julien Ponge CLA
Modified: 2016-05-25 10:27 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Julien Ponge CLA 2015-06-29 16:04:37 EDT
(from https://github.com/golo-lang/golo-lang/issues/284)



Currently, code like this:

function main = |args| {
  let inc1 = |x| -> x + 1
  let inc2 = |v| -> v + 1

  let add = |x, y| -> x + y
  let addcurry = |x| -> |y| -> x + y

  let foo = |x| -> "Foo: " + x
  let bar = |x| -> "Bar: " + x
  let applyFoo = |x| -> foo(x)
  let applyBar = |x| -> bar(x)
}

expends to something similar to:

function main = |args| {
  let inc1 = ^__$$_closure_0
  let inc2 = ^__$$_closure_1
  let add = ^__$$_closure_2
  let addcurry = ^__$$_closure_3
  let foo = ^__$$_closure_5
  let bar = ^__$$_closure_6
  let applyFoo = ^__$$_closure_7: insertArguments(0, foo)
  let applyBar = ^__$$_closure_8: insertArguments(0, bar)
  return null
}

local function __$$_closure_0 = |x| {
  return x + 1
}

local function __$$_closure_1 = |v| {
  return v + 1
}

local function __$$_closure_2 = |x, y| {
  return x + y
}

local function __$$_closure_3 = |x| {
  return ^__$$_closure_4: insertArguments(0, x)
}

local function __$$_closure_4 = |x, y| {
  return x + y
}

local function __$$_closure_5 = |x| {
  return "Foo: " + x
}

local function __$$_closure_6 = |x| {
  return "Bar: " + x
}

local function __$$_closure_7 = |foo, x| {
  return foo(x)
}

local function __$$_closure_8 = |bar, x| {
  return bar(x)
}

May be it would be desirable to instead expand to:

function main = |args| {
  let inc1 = ^__$$_closure_0
  let inc2 = ^__$$_closure_0
  let add = ^__$$_closure_1
  let addcurry = ^__$$_closure_2
  let foo = ^__$$_closure_3
  let bar = ^__$$_closure_4
  let applyFoo = ^__$$_closure_5: insertArguments(0, foo)
  let applyBar = ^__$$_closure_5: insertArguments(0, bar)
  return null
}

local function __$$_closure_0 = |x| {
  return x + 1
}

local function __$$_closure_1 = |x, y| {
  return x + y
}

local function __$$_closure_2 = |x| {
  return ^__$$_closure_1: insertArguments(0, x)
}

local function __$$_closure_3 = |x| {
  return "Foo: " + x
}

local function __$$_closure_4 = |x| {
  return "Bar: " + x
}

local function __$$_closure_5 = |foo, x| {
  return foo(x)
}

that is, reuse identical closures and lambda if possible. This is probably doable by comparing IR representations of closure in a given module. This could reduce the bytecode size, and (maybe) add a slight improvement in lookup time. Some points are probably not trivials (e.g. arguments and variables with same role but differents names).

Does it worth the pain (or the fun :smile:)?

---- Julien Ponge:

Sounds like a cool thing to investigate!

---- Yannick Loiseau:

We can also let the developer create an explicit function to make this optimisation by hand, since we value explicitness :smile:

---- Julien Ponge:

True :smile:

---- Sylvain Desgrais:

Hi mates,
I think that the JVM/JIT already do this kind of optimizations at native code generation level. I don't know if it worth the pain just for reduce the bytcode size and the callsite installation time.
However code blocs canonicalisation (symbols?) is a fun idea :wink:

---- Julien Ponge:

In terms of perf you have more chances of avoiding profile pollution with many methods :-)