hazel icon indicating copy to clipboard operation
hazel copied to clipboard

Move evaluation to web worker

Open mirryi opened this issue 1 year ago • 3 comments

Try here.

Closes #638.

Remaining items for this:

  • [x] Memoizing evaluation requests on the main thread side, to avoid unnecessary serialization
  • [x] Handling exceptions on the worker thread and printing the corresponding errors (currently in Update.re), or explicitly passing exceptions back to the main thread; exceptions aren't bubbled back to the main thread
  • [x] ~~Not sure why the fonts and images aren't getting copied over when deploying~~ (fixed this in another PR)

Leaving for haz3l work:

  • UI indicators for when evaluation is pending or timed out
  • Potentially, a configurable timeout and worker pool capacity

mirryi avatar Jul 12 '22 19:07 mirryi

Basic functionality is pretty much working, with the following caveats:

  • Model updating isn't working completely right quite yet, since updating selected hole instances requires comparing the new evaluation result with the previous one. Haven't implemented this yet.
  • For some reason, the built-in data copying that messaging with the web worker does isn't sufficient (we get some weird errors in both directions), so we have to do our own serialization (currently via s-expressions)
  • Doesn't really alleviate the cases observed in #536 and such, since the evaluation result experiences blow-up in size that makes serialization/deserialization slow. We really need #586 for this.
  • Doesn't truly alleviate the case of dead loops. It prevents the UI from freezing, but evaluation continues indefinitely in the web worker, it seems. Also some cases (e.g. this one) where the evaluation result display doesn't properly change when changing the final expression to something else.

Left to do:

  • Loading indicator when evaluation is pending
  • Associating results with corresponding program in the model; or, memoization of requests
  • Worker thread cancellation; currently we only have cancellation on the main thread side. Adding this might be able to reduce some copying, but I'm not too clear on how Lwt's cancellation works. Also, cancellation doesn't really cancel the evaluator; to do that we need some sort of way to interrupt the evaluator.

mirryi avatar Jul 13 '22 22:07 mirryi

Implemented a worker pool (WebWorkerPool) via a generic Lwt pool with timeout functionality (TimedLwtPool), whose implementation is based on that of lwt's built-in Lwt_pool.

I've set an arbitrary setting of 5 workers in the pool and a 2000 ms timeout for evaluation. If an evaluation request doesn't meet the timeout, the worker is discarded. Evaluation requests use available workers, or create new ones if they're all busy, or wait for one to free up if worker capacity is reached.

mirryi avatar Jul 19 '22 17:07 mirryi

Remaining items for this:

  • [ ] UI indicator for when evaluation is pending
  • [ ] Memoizing evaluation requests on the main thread side, to avoid unnecessary serialization
  • [ ] Handling exceptions on the worker thread and printing the corresponding errors (currently in Update.re); exceptions aren't bubbled back to the main thread
  • [ ] More testing overall, playing with the settings to see what works best
  • [ ] Potentially, a configurable timeout and worker pool capacity
  • [ ] Not sure why the fonts and images aren't getting copied over when deploying?

mirryi avatar Jul 20 '22 19:07 mirryi