Actually, Html.Lazy also saves the differ the task of comparing the
subtrees when laziness saves us from work, so it can be a big win if UI
updates are a significant chunk of the work.
That said, Max is correct that memory allocation for new structures is also
a cost and is something to be avoided. (Functional programming loves to
allocate memory...)
So, the basic rules of thumb are:
- If you have a big model pieces of which get rendered in various
combinations by other code, try splitting those pieces out and using the
record extension syntax to access just the fields needed while avoiding the
cost of building a separate record.
- If you only need a little bit of information from the model for a
subview, you can just extract it and call the subview function and avoid
the record syntax overhead.
- If your model is structured in a way that makes it easy to keep valid
but harder to draw, that's probably a good trade off — make impossible
states impossible and all that — but may call for using an intermediate
structure between the model and the actual view code. (See Charlie Koster's
piece on "selectors".)
- Laziness can be a big win for both render and diff times with complex
views BUT you need to be aware of how the lazy logic works and not hand it
data that isn't likely to use the same data instances from render to render.
- Laziness can be good as one approaches the leaves and the data
becomes more primitive.
- Laziness can be good near the top if there are large chunks of your
model that won't be changing from cycle to cycle.
- Laziness gets a bit tricky in between these two because it can be
useful to build intermediate structures while rendering and those break
laziness.
- Experiment with the signature to your view functions. The basic idea
of a view function is that it takes some data and returns some HTML. For
example:
- Config records can handle views that need more set up (but you will
likely want to move them out to module scope for performance if possible.
- If you have theme support in your UX, it may be useful to pass the
theme down to all view functions that care as a separate parameter.
- Sometimes it is useful to have view functions return lists of HTML
nodes rather than a single node.
Mark
On Thu, Jun 22, 2017 at 1:46 PM, Max Goldstein <[email protected]>
wrote:
> To state Mark's point clearly: if your view depends on only a small number
> of the model's fields, then you are likely to rerender the view only when
> some other fields changed, which is unnecessary.
>
> That said, you might not be at the point of needing laziness for
> performance. In particular, allocating and copying a new record has a cost
> of its own, and you'll have to measure to find if it's worth the lazy call
> to the function. Important: because of the virtual DOM, Html.lazy only
> saves you the overhead of calling the view function, both its logic and
> creating the virtual DOM. If the view function returns virtual DOM that
> matches the existing, real DOM, no DOM manipulation is performed, and
> that's the real performance win.
>
> So, it is definitely simpler and easier, and possibly no less performant,
> to pass the model directly to the view. It would be nice if we could use
> the type system to limit which fields of the model the view can see, so we
> can isolate it better for understanding and testing. Fortunately there is a
> neat trick that does just that:
>
> view : { r | foo : Int } -> Html Msg
> view {foo} = ...
>
> This function accepts any record which has a foo field of type Int. If
> your model has that field, it can be passed in, but no other fields in the
> model are available to the view function.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Elm Discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>
--
You received this message because you are subscribed to the Google Groups "Elm
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.