<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="356419" data-post-id="356419">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Not to my exact code, but I’ll post a reproducible example.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356419" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/liveview-performance-problems-morphdom-taking-up-to-1500ms-to-patch-updates/69408/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-356419" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356419"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #21"></div>
  </section>
</div>
    <div class="postbit" id="356423" data-post-id="356423">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Just to add to the discussion: this should probably be even more obvious, but the amount of data being sent in even simple form validations for  nested forms with ~15 user-facing inputs (plus a bunch of hidden fields to implement moving and deleting items in the form) sends to the server around 10kB of data and receives around 10kB of data, which naturally scales up when you increase the number of items in the form.</p>
<p>Honestly, up until this performance problem (this is my first “big” phoenix form) I had never looked at the message size because it’s not too proeminent in the server logs and I don’t have a good intuition in converting nr of characters to kB (the logs show the received map but not the message size). I find it a little scary that I’m sending so much data upd and down for simple form validations. I think that for these amounts of data I’d have to think carefully about network bandwidth and prices… Of course, this is still all dwarfed by more data-intensive apps such as audio streaming or such, but here I am trying to get dynamic forms working and then comparing it to audio streaming (!), even if for short bursts when the user is actually editing the form.</p>
<p>Again, I don’t remember the data transfer problems being highlighted in the phoenix docs: everyone talks about how “minimal” the diffs are (and they are indeed close to minimal, no question about that), but then everyone shows examples of very small forms with minimal data transmission. So I guess that leavs less experienced users like me surprised by how much data can be transfered in more complex UI.</p>
<p>So I guess I’ve been surprised on both fronts:</p>
<ol>
<li>How slow the DOM updates can be for complex UIs</li>
<li>How much data can be transferred during form validations which I think are pretty simple. The solution, of course, would be to only validate the form on submit (the data must be sent to the server at some point), but that complicates a lot of things in the UI (designing custom events to add sub-items instead of depending one Ecto’s <code>:sort_param</code>). And isn’t the whole point of LiveView to get flashy real-time form vaidations? That’s one of the things more often shown in the demos…</li>
</ol>
<p>I think a couple of things are needed:</p>
<ol>
<li>A warning about Morphdom’s performance on “large” lists - definitely not something I’d expect on lists of &lt; 100 components (even if the components are quite complex)</li>
<li>A warning on data transfer amounts</li>
<li>Adding the amount of transferred data in the logs for the event handlers. Seeing how many kBs of data we’re sending every second (or whenever you want to validate your form) can be very illuminating</li>
</ol>
<p>I’ll post some issues to the LiveView repo to suggest these documentation and log improvements.</p>
<p>Sorry, this is turning into a rant against LiveView, but that’s not how one should interpret this thread. It’s more of a rant about the documentation not being clear about the pitfals of using LiveView for what I consider “simple” UI.</p>
<p>(I guess I won’t be using LiveView for this application)</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356423" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/liveview-performance-problems-morphdom-taking-up-to-1500ms-to-patch-updates/69408/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-356423" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356423"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #22"></div>
  </section>
</div>
    <div class="postbit" id="356425" data-post-id="356425">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="tmbb" data-post="23" data-topic="69408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<ul>
<li>A warning about Morphdom’s performance on “large” lists - definitely not something I’d expect on lists of &lt; 100 components (even if the components are quite complex)</li>
</ul>
</blockquote>
</aside>
<p>I don’t think the list size is the issue but rather its contents. DOM is a tree and you are more likely being punished by the tree than the list size. Morphdom works by comparing node by node and using IDs may help it to avoid discarding changes.</p>
<aside class="quote no-group" data-username="tmbb" data-post="23" data-topic="69408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<ul>
<li>A warning on data transfer amounts</li>
<li>Adding the amount of transferred data in the logs for the event handlers. Seeing how many kBs of data we’re sending every second (or whenever you want to validate your form) can be very illuminating</li>
</ul>
</blockquote>
</aside>
<p>Keep in mind you can track a lot of this in the Network tab already of the dev console, where you get payload sizes per WebSocket message, but it would be beneficial making this information more upfront too, so <img src="https://forum.elixirforum.com/images/emoji/apple/+1.png?v=15" title=":+1:" class="emoji" alt=":+1:" loading="lazy" width="20" height="20">.</p>
<p>Other than that, the comprehensions contents are sent as a whole if the comprehension changes, because computing the difference between two arbitrary lists can be resource expensive, so you need to resort to either LiveComponent or streams, as already explored. But these should be better documented. I will submit more docs later today.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356425" data-batch-url="/posts/batch_likers">
                        8
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/liveview-performance-problems-morphdom-taking-up-to-1500ms-to-patch-updates/69408/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-356425" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356425"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #23"></div>
  </section>
</div>
    <div class="postbit" id="356426" data-post-id="356426">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="24" data-topic="69408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>I don’t think the list size is the issue but rather its contents. DOM is a tree and you are more likely being punished by the tree than the list size.</p>
</blockquote>
</aside>
<p>Indeed, that is obvious. I should have made myself more clear:</p>
<ul>
<li><strong>In reality</strong> I’m not updating a <em>list of 100 components</em>. I’m updating a <em>deep DOM tree with 100 branches in which each branch has more many children</em></li>
<li><strong>But when planning to use LiveView for my app</strong> I was thinking “I’m just rendering a list of 100 things, how bad can it get?”. And during initial testing I was actually building the forms manually, so they never got to “production size”. Only when I decided to populate the system with synthetic data did I notice the horrible performance.</li>
</ul>
<aside class="quote group-livebook_core_team quote-modified" data-username="josevalim" data-post="24" data-topic="69408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>the comprehensions contents are sent on every update if the comprehension changes, because computing the difference between two arbitrary lists can be resource expensive</p>
</blockquote>
</aside>
<p>That I did expect, and it might turn out ok for “simple lists” of components. But then I have actually implemented components that allow you to delete (using the “checkbox disguised as button” trick) and move up and down (again, using buttons with the “checkbox disguised as button” trick) each child in a <code>has_many</code> assoc, which means 5 extra input fields per child. All these inputs are in a sense “dynamic”, and need to be sent to the server for validation and back from the server after validation. And because the lists are somewhat deeply nested (3 levels deep) and due to the way Plug encodes the parameters, each of the deep feelds consumes <em>a lot</em> of space in the message. For example (imagine the following is URL-encoded, which only increases them message size): `project[tables][0][columns][0][choices][0][name]=ChoiceName". And now imagine this repeated for 3 attributes per choice + 5 “hidden” attributes required for the sorting. This is exactly the way a form is sent to the server on HTTP requests, but that happens once in a while when the user is already primed to wait for the server “to do its stuff”.</p>
<p>In my optinion, this has very dangerous performance characteristics because it’s totally manageable for simple things but prohibetively expensive for the slightly more complex things. It’s a linear algortithm with a constant big enough that it can’t be noticed for small inputs but quickly gets very noticeable in a part of the UI the user would expect to be very fast.</p>
<p>When I have the time, I should publish a screencast (together with the code and the message sizes) as a warning about what can happen when one treates LiveView updates as “free”, like I was naïvely doing.</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="24" data-topic="69408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>Keep in mind you can track a lot of this in the Network tab already of the dev console</p>
</blockquote>
</aside>
<p>Yes, I know this and that’s how I’ve been monitoring the message sizes, but the <em>explicit</em> promise of LiveView (which I know believe to be misleading) is that you just write elixir code, forget about Javascript and the right thing will happen (those are not exact words from anywhere, but it’s the general vibe of bothn the docs and lots of talks I’ve seenH). I forgot about javascript and the browser so much that I only looked at server logs and forgot about looking at the browser completely, including the network console.</p>
<p>Again, please don’t take this as an attack on LiveView’s design decisions… I certainly wouldn’t kow how to do it better, a is obvious from my UndeadViews/Vampyre experiments from 2018. It’s instead an attack on the mismatch between the “promises” made in educational materials regarding performance and what actually happens in the real world as soon as you deviate a bit from the small tech demos in the talks.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356426" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/liveview-performance-problems-morphdom-taking-up-to-1500ms-to-patch-updates/69408/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-356426" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356426"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #24"></div>
  </section>
</div>
    <div class="postbit" id="356428" data-post-id="356428">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmjoen" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmjoen
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>We switched our block editor from Vue to LiveView some years ago and had some real pains with super large forms. These were also complex, nested forms. As a last ditch effort before going back to Vue we split out all our assocs to their own forms. So when saving the “main” form, we traverse and combine all the other forms on the page then add it to the main changeset. It was a bit of a challenge to make it all work but the speed up was enough for us to stay with LV.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356428" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/liveview-performance-problems-morphdom-taking-up-to-1500ms-to-patch-updates/69408/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-356428" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356428"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #25"></div>
  </section>
</div>
    <div class="postbit" id="356429" data-post-id="356429">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>So did you have something like this:</p>
<pre data-code-wrap="html"><code class="lang-html">&lt;form&gt;
  &lt;input ...&gt;
  &lt;input ...&gt;
&lt;/form&gt;
&lt;form id="child1"&gt;
  &lt;input ...&gt;
  &lt;input ...&gt;
&lt;/form&gt;
&lt;form id=grandchild1"&gt;
&lt;/form&gt;
&lt;form id=grandchild2"&gt;
&lt;/form&gt;
&lt;form id="child2"&gt;
  &lt;input ...&gt;
  &lt;input ...&gt;
</code></pre>
<p>It seems like a good idea, that would allow you to validade changes in one form at a time.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356429" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/liveview-performance-problems-morphdom-taking-up-to-1500ms-to-patch-updates/69408/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-356429" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356429"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #26"></div>
  </section>
</div>
    <div class="postbit" id="356430" data-post-id="356430">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Zurga" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Zurga/120/38832_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Zurga
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="tmbb" data-post="23" data-topic="69408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Honestly, up until this performance problem (this is my first “big” phoenix form) I had never looked at the message size because it’s not too proeminent in the server logs and I don’t have a good intuition in converting nr of characters to kB (the logs show the received map but not the message size). I find it a little scary that I’m sending so much data upd and down for simple form validations. I think that for these amounts of data I’d have to think carefully about network bandwidth and prices… Of course, this is still all dwarfed by more data-intensive apps such as audio streaming or such, but here I am trying to get dynamic forms working and then comparing it to audio streaming (!), even if for short bursts when the user is actually editing the form.</p>
</blockquote>
</aside>
<p>Maybe it will help only with the message size, but I wrote a <a href="https://forum.elixirforum.com/t/how-to-use-messagepack-with-liveview-instead-of-json/59038" rel="nofollow">guide</a> that explains how to switch to MessagePack encoding in the socket. I use it in production for a mobile first web app that sometimes has bad internet speed on the client side.</p>
<p>This will shave around 25% of the message size at the cost of message legibility in the developer console and a small decompression overhead.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356430" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/liveview-performance-problems-morphdom-taking-up-to-1500ms-to-patch-updates/69408/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-356430" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356430"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #27"></div>
  </section>
</div>
    <div class="postbit" id="356436" data-post-id="356436">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="tmbb" data-post="25" data-topic="69408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>I’m updating a <em>deep DOM tree with 100 branches in which each branch has more many children</em></p>
</blockquote>
</aside>
<p>And to be clear, that’s not necessarily a problem either, the tricky part is that those are dynamic branches. It seems you are updating a list with a dynamic list with a dynamic list with a dynamic list inside. This is neither common nor simple.</p>
<aside class="quote no-group" data-username="tmbb" data-post="25" data-topic="69408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>For example (imagine the following is URL-encoded, which only increases them message size): `project[tables][0][columns][0][choices][0][name]=ChoiceName"</p>
</blockquote>
</aside>
<p>This should not be a concern payload wise, enable compression on the socket and you should be good to go.</p>
<p>In any case, looking at the above, it does make me wonder indeed if three level deep association in a single form is the best design and/or UX. I assume it can get confusing for the user to manage several levels of a hierarchy at once (I think this is the first time I see that many levels in a single form!) Someone already suggested to break the forms apart but you can also do something like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">TABLE 
[ Column                  EDIT DESTROY ]
[ Column                  EDIT DESTROY ]
[ Column                  EDIT DESTROY ]
[ Column                  EDIT DESTROY ]
                                 [ NEW ]
</code></pre>
<p>Where the first level of management is not really a form but something that allows you to manage the children.</p>
<p>It also made me realize that, because you are validating the whole form and all associations at once as the user fills in, the validation on the server itself may become expensive too. It would be similar to an e-commerce platform where you have a single form for the categories, then products, then the variants, and then the images, all at once. I wouldn’t be surprised if another performance issue pops up even if the UI one is addressed.</p>
<aside class="quote no-group" data-username="tmbb" data-post="25" data-topic="69408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Yes, I know this and that’s how I’ve been monitoring the message sizes, but the <em>explicit</em> promise of LiveView (which I know believe to be misleading) is that you just write elixir code, forget about Javascript and the right thing will happen (those are not exact words from anywhere, but it’s the general vibe of bothn the docs and lots of talks I’ve seenH).</p>
</blockquote>
</aside>
<p>Anything that runs on platform XYZ will, by definition, require you to care about XYZ at some point. At some point, an Elixir dev may need to care about the Erlang VM. At some point, you may need to care about Unix if you deploy to Unix. And, if you are running in the browser, at some point you will need to care about it too.</p>
<p>Btw, after thinking about this problem a bit, I was wondering if part of the issue is because the updates are mostly the same, the diffing is expensive because Morphdom is traversing everything mostly to find out that almost nothing changed. Similar to how comparing two lists for equality will be naturally more expensive if the two lists are equal. I am speculating here though. If someone has a way to reproduce this, I will gladly take a look. I quite enjoy optimization work!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356436" data-batch-url="/posts/batch_likers">
                        12
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/liveview-performance-problems-morphdom-taking-up-to-1500ms-to-patch-updates/69408/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-356436" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356436"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #28"></div>
  </section>
</div>
    <div class="postbit" id="356445" data-post-id="356445">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tozz" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tozz
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’ve been running into similar problems, my biggest problem is that you can’t nest forms according to the spec so you’re stuck between not being able to use the nice benefits of the Ecto/Phoenix integration or building custom javascript hooks trying to merge multiple forms (and same thing on the backend side with multiple changesets).<br>
Most of my basic forms usually end up ad 20-40KiB for each validation trip, UUID’s take a lot of space, every dynamic attribute, lists etc. I’m defaulting to LiveComponents to alleviate it but even so the ID’s and dynamic nature of forms causes quite big payloads.</p>
<p>Other things that causes some headaches are that even with state on the server changesets needs to be complete, which makes partial validation and transmission very hard (or impossible).</p>
<p>Streams work ok for read-only data but any time you get into dynamic stuff it becomes quite troublesome with relying on state on the client.</p>
<p>That said it’s still a very nice way of working, but I think there are a lot of gotchas that aren’t very clear from the docs.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356445" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/liveview-performance-problems-morphdom-taking-up-to-1500ms-to-patch-updates/69408/30">Post #29</a>
	                </div>
	            </div>
              <div id="likers-container-356445" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356445"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #29"></div>
  </section>
</div>
    <div class="postbit" id="356449" data-post-id="356449">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Yeah, I’m looking at <a href="https://github.com/woutdp/live_svelte" class="inline-onebox" rel="noopener nofollow ugc">GitHub - woutdp/live_svelte: Svelte inside Phoenix LiveView with seamless end-to-end reactivity · GitHub</a> and <a href="https://github.com/Valian/live_vue" class="inline-onebox" rel="noopener nofollow ugc">GitHub - Valian/live_vue: End-to-end reactivity for Phoenix LiveView and Vue · GitHub</a> but I’m a bit afraid of the fact that to render useful content on initial page load they seem to depend on server-side rendering, which requires having a NodeJS server running in parallel with the BEAM. which I really, really don’t like. However, that is always a problem with client-side JS frameworks, whether used with LiveView or not…</p>
<p>BTW, even with a “single” list level I’m getting payloads of ~190kB with a list of 60 sub-items (~180 input widgets). And I don’t think I want to have those kinds of diffs…</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356449" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/liveview-performance-problems-morphdom-taking-up-to-1500ms-to-patch-updates/69408/31">Post #30</a>
	                </div>
	            </div>
              <div id="likers-container-356449" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356449"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #30"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/69408/load_more?page=4">Load more posts (25 remaining)</a>
</div></template></turbo-stream>