Deep copy or shallow copy?

Hi,

I’m often faced with the following problem.

I have a record containing large data in a main view. Let’s say

model = {
    name = "name"
  , big_data = fooBarLarge
  , componentData = MyComponent.init   -- init a statefull component
}

I often need to pass big_data to a stateful components that need to read this data.
If this data is not available/ready at initialization, I pass it in a view like this:

let
  data = {
    big_data = model.big_data
  , other_data = "other_data"
  }
in
viewComponents data model.componentData |> Html.map MyComponentMsg

The question I have here is twofold :

  1. Is big_data, in my example, undergoes a deep copy or a shallow copy when passed to the viewComponents function?

  2. Is there a better way to share “big_data” across components (without copying it / in-memory access) ?

Thank you.

  1. big_data is not copied. The compiled code will pass it by reference. So it is not inneficient to do that.
  2. This way is fine, as it not copying.
1 Like

I agree with Sebastian on 1 - it is not copied. Just a new reference to it is created in the data record.

For 2 - There might be a better way if you want to use Html.lazy too:

viewComponents model.big_data “other_data” model.componentData

That is, don’t create the data recrod, just pass the things you need as params - since creating a new data record would automatically defeat Html.lazy. But if you are not interested in Html.lazy its all fine.

1 Like

A question about the correct usage of Html.lazy ; Suppose that the view (viewComponents) build a really simple html dom with big_data (like not iterating over all the data). Would it be efficient the use lazy in this case given that it will compute a diff on large structure every time which may be more costly than drawing/comparing the vdom ?

Html.Lazy uses JavaScript’s === operator, which compares by reference, not structure, which is fast. So it basically just asks “do these two things have the same identity” not “do these two things look the same”.

However, if you give more data than is needed to Html.Lazy, you are not getting the most out of it – that html piece will re-render even if something in big_data that isn’t used for the html piece changes.

When working with Html.Lazy I recommend:

  1. Using Debug.log inside the lazy view so you can see when it actually gets called. It’s easy to mess up so that it’s always called (because something given to Html.Lazy is considered different on every render).
  2. Measuring if adding the Html.Lazy actually resulted in quicker execution.
2 Likes

Thanks a lot for these insights !

Except of using Debug.log, what would you use/recommand to do 2 (Measuring if adding the Html.Lazy actually resulted in quicker execution.)

Chrome development tools or equivalent use the profiler to see how much CPU is needed during rendering of your application. Compare with/without Html.lazy.

1 Like

What rupert said. I’ve also done it by adding console.time('render') and console.timeEnd('render') at carefully chosen spots in the compiled JS… For example around this block:

Or this block:

2 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.