The js implementation uses ~15% cpu, and my Elm implementation uses ~90% cpu.
(Cpu stats taken from the Chrome task manager.)
Steps I have taken to improve the performance is to pre-calculate all the lines (this is also done in the js version) in the init function – and I’m using Html.Lazy to prevent unnecessary DOM updates.
I also implemented rendering to svg (can be enabled on line 64), but that is even slower than the canvas tree.
Is there anything that can be done to improve the performance any further of either the canvas or svg tree?
Have you tried subscribing to Time.every instead of Event.onAnimationFrame?
To be honest I’m not sure if it’ll be enough on its own but it’s worth a shot. The Elm runtime only updates the DOM on requestAnimationFrame anyway. So it could cut down on some unnecessary work.
You’ll see a lot of slow down when running on Ellie-app as it always has the debugger enabled.
But running this locally I still see high CPU utilization.
Looking at the Chrome performance tab it looks like the major cost is the JSON encoding of the canvas commands by the elm-canvas toHtml function. You can pre-calculate some of this by storing a List Canvas.Renderable in your Model instead of the List LineSegment.
But toHtml still does a lot of JSON encoding and doesn’t provide a way to pre-calculate that.
Thanks for good suggestions!
I got the cpu usage down to ~30% (from 90%) by storing the output of the view functions in the model.
type alias Model =
{ ...
, renderedViews : Dict Int View
}
type View
= SvgView (Svg Msg)
| CanvasView (Html Msg)
I guess this is not a technique that can be used in an interactive app, but it works in this case
I also changed to Time.every instead of onAnimationFrame – that actually increased the cpu usage a bit, but is more true to the js implementation and simplifies the update function.