Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ppx to rewrite Lwt.return foo to an allocation-less form. #94

Closed
wants to merge 1 commit into from

Conversation

Drup
Copy link
Member

@Drup Drup commented Oct 20, 2014

It started of as a joke, but @whitequark told me it was a good idea.

I blame @avsm for giving me the idea. :p

It's disabled by default, because I personally think this is not a good idea.

@whitequark
Copy link
Contributor

I actually think this could be enabled by default. If your code breaks because of that, it was already broken before.

@Drup
Copy link
Member Author

Drup commented Oct 20, 2014

The argument is very simple: this is a ridiculous optimization than matter for almost nobody except very expert users, it abuses ppx and can break code that you wouldn't expect to break. Hence, tt's disabled by default.

(I'm not even convinced it should be merged to begin with ...)

@ghost
Copy link

ghost commented Oct 20, 2014

There is a solution that requires no preprocessing and would allow Lwt.return expr to be preallocated whenever expr is a constant. With 4.02 this would make the Lwt.wait allocate more, but not with trunk!

@Drup
Copy link
Member Author

Drup commented Oct 20, 2014

@diml Now I'm curious, what in 4.02 allows that ?

@ghost
Copy link

ghost commented Oct 20, 2014

Well it's not 4.02 specifically, let's say with OCaml <= 4.02

@whitequark
Copy link
Contributor

@diml What solution? Some kind of inlining?

@ghost
Copy link

ghost commented Oct 20, 2014

No, just by changing the Lwt.t type.

This is (almost) the lwt type:

type 'a state =
  | Return of 'a
  | Fail of exn
  | Sleep of 'a sleeper
  | Repr of 'a repr

and 'a repr = { mutable state : 'a state }

type 'a t = 'a repr

let return x = { state = Return x }
let wait () = { state = Sleep (new_sleeper ()) }

You can instead define it as:

type 'a t = 'a state

let return x = Return x
let wait () = Repr { state = Sleep (new_sleeper ()) }

return x is no more a mutable value so it can be shared.

But this create 1 more indirection for the wait. However with trunk you can do this:

type 'a state =
  | Return of 'a
  | Fail of exn
  | Sleep of 'a sleeper
  | Repr of { mutable state : 'a state }

To avoid some assert false you can even do this:

type ('a, 'which) state =
  | Return : 'a -> ('a, [> `Return ]) state
  | Fail : exn -> ('a, [> `Fail ]) state
  | Sleep : 'a sleeper -> ('a, [> `Sleep ]) state
  | Repr : { mutable state : 'a state } -> ('a, [> `Repr ]) state

type 'a t = ('a, [ `Return | `Fail | `Repr ]) state

@whitequark
Copy link
Contributor

It was inlining after all, just of data, not code :p

@Drup
Copy link
Member Author

Drup commented Nov 25, 2014

If someone wants to revive that, be my guest. :p

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants