hazel
hazel copied to clipboard
Move evaluation to web worker
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
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.
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.
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?