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


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mononym" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mononym/120/4124_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mononym
                    <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>Changing the messages, the <code>p</code> tags, to components gave me a definite improvement on that front. Not seeing 500ms times any more, though still getting a lot of 100ms+ layout reflows.</p>
<p>I’ve removed anything that isn’t structural from the following template, but this is what the base LiveView component looks like that takes up the whole page:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;div name="client" class="w-screen h-screen flex flex-row overflow-hidden max-h-screen" phx-window-keyup="hotkey"&gt;
  &lt;div class="w-1/5 flex flex-col"&gt;
    &lt;div class="flex flex-1 border-4"&gt;&lt;/div&gt;
    &lt;div class="flex flex-col flex-1 border-4"&gt;
      &lt;ul class="flex"&gt;
        &lt;li class="flex-1 mr-2"&gt;
          &lt;a class="text-center block border border-blue-500 rounded py-2 px-4 bg-blue-500 hover:bg-blue-700 text-white" href="#"&gt;Inventory&lt;/a&gt;
        &lt;/li&gt;
        &lt;li class="flex-1 mr-2"&gt;
          &lt;a class="text-center block border border-white rounded hover:border-gray-200 text-blue-500 hover:bg-gray-200 py-2 px-4" href="#"&gt;Skills&lt;/a&gt;
        &lt;/li&gt;
        &lt;li class="text-center flex-1"&gt;
          &lt;a class="block py-2 px-4 text-gray-400 cursor-not-allowed" href="#"&gt;Settings&lt;/a&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
      &lt;div class="flex flex-1 bg-gray-600 p-2"&gt;
        &lt;%= live_component @socket, MudWeb.Live.Component.CharacterInventory, id: :character_inventory, inventory: @client_data.inventory %&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="w-3/5 flex flex-col"&gt;
    &lt;div id="story" phx-hook="Story" class="border-4 border-r-0 min-w-full flex-1 flex flex-col overflow-y-scroll"&gt;
      &lt;div phx-update="append" class="flex flex-col flex-1 min-w-full p-2 font-extrabold font-story overflow-y-auto"&gt;
        &lt;%= for message &lt;- @messages do %&gt;
          &lt;%= live_component @socket, MudWeb.Live.Component.StoryMessage, message: message %&gt;
        &lt;% end %&gt;
      &lt;/div&gt;
      &lt;div id="scroll-to-bottom" phx-hook="ScrollToBottom" class="h-px"&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="h-8 flex flex-col"&gt;
        &lt;%= live_component @socket, MudWeb.Live.Component.CommandPrompt, input: @input %&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="w-1/5 flex flex-col"&gt;
    &lt;div class="flex flex-1 border-4"&gt;&lt;/div&gt;
    &lt;div class="flex flex-1 border-4"&gt;
      &lt;ul class="flex flex-1"&gt;
        &lt;li class="flex flex-1 mr-2"&gt;
          &lt;a class="text-center block border border-blue-500 rounded py-2 px-4 bg-blue-500 hover:bg-blue-700 text-white" href="#"&gt;Active Item&lt;/a&gt;
        &lt;/li&gt;
        &lt;li class="flex flex-1 mr-2"&gt;
          &lt;a class="text-center block border border-white rounded hover:border-gray-200 text-blue-500 hover:bg-gray-200 py-2 px-4" href="#"&gt;Nav Item&lt;/a&gt;
        &lt;/li&gt;
        &lt;li class="flex flex-1"&gt;
          &lt;a class="block text-center py-2 px-4 text-gray-400 cursor-not-allowed" href="#"&gt;Disabled Item&lt;/a&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>This is the CommandPrompt template:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;%= form_for @input, "#", [phx_submit: :submit_input, class: "flex flex-col flex-1"], fn _f -&gt; %&gt;
    &lt;%= text_input :input, :content, phx_hook: "Input", phx_blur: "stop_typing", placeholder: "Enter Commands Here...", class: "min-w-full rounded-lg resize-y min-h-full", autocomplete: "off" %&gt;
&lt;% end %&gt;
</code></pre>
<p>This is the StoryMessage:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;%= raw(@message) %&gt;
</code></pre>
<p>Is this about all I can do from a basic LiveView standpoint as far as client performance while appending to the primary message window is concerned? The delay still isn’t fantastic, but it’s at least tolerable. Would love to target sub 100ms interactions consistently though, so if I need to get fancy I will.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="179788" 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-append-and-performance-degradation-with-large-number-of-appended-elements/32376/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-179788" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="179788"
                     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="179795" data-post-id="179795">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-Phoenix-Core-Team" data-username="chrismccord" data-post="18" data-topic="32376" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/chrismccord/48/24233_2.png" class="avatar"> chrismccord:</div>
<blockquote>
<p>Components would solve your issues in this case. The issue is we have to patch the entire LiveView DOM container for any change, and for large DOM trees, this requires traversing the tree as you alluded to. If you wrap the paragraphs in a component and/or the form in a component, it will allow LiveView to patch only those areas when they change, and also skip walking those areas when the parent LiveView needs to patch a DOM a non-component node that it owns.</p>
</blockquote>
</aside>
<p>I’m interested why this way was chosen?  Drab for comparison does not traverse the DOM at all and instead only accesses an element directly by a random assigned ID (unless the user assigned it directly otherwise) then calls direct calls on it, like add an element or change text somewhere.  There’s no walking the dom or anything?  Basically it works by just seeing what changed on the assign and directly sending javascript calls to perform edits as necessary.  Drab’s EEX processor does require valid HTML code though as it does parsing so it knows the structure though so it knows how to patch the DOM directly without walking.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="179795" 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-append-and-performance-degradation-with-large-number-of-appended-elements/32376/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-179795" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="179795"
                     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="179832" data-post-id="179832">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mononym" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mononym/120/4124_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mononym
                    <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>As a followup for anyone looking about performance information, my biggest issue after changing to the live components was a continued reflow being forced on the client whenever I was appending a new message to the screen. This is 100% due to having scrolling enabled in the browser.</p>
<p>Whatever LiveView does is very quick, but having scrolling while appending to a div forces the browser to do a ton of work and this is just not something you can get around without getting a little fancy.</p>
<p>With the same number, thousands, of messages and no scrollbar I consistently get DOM updates in 50-70ms. With scrolling enabled the exact same logic takes up to 200ms due to forced reflow, which when you have multiple messages coming in quickly can really lessen the experience.</p>
<p>Since I need to be able to scroll back through the messages this does put a damper on a few things. That said, I think I’m going to see about trying to control scrolling via LiveView and hotkeys/buttons.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="179832" 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-append-and-performance-degradation-with-large-number-of-appended-elements/32376/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-179832" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="179832"
                     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="179834" data-post-id="179834">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>In such a case I’d really consider switching to client side rendering at least for that performance critical part. You could stick to liveview for pushing the data to the client (this is how phoenix_live_dashboard works) or move to a custom channel based solution. With the data being client side you can separate data management from the dom, which allows you do optimizations on the dom, where server side handling would eat up the saved performance latency by introducing additional network latency.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="179834" data-batch-url="/posts/batch_likers">
                        1
                      </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-append-and-performance-degradation-with-large-number-of-appended-elements/32376/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-179834" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="179834"
                     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="179835" data-post-id="179835">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mononym" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mononym/120/4124_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mononym
                    <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>In all honesty I could probably just handle the scrolling interaction on the client side, no reason to go back to the server since I’m going to have to write the JS hook anyway.</p>
<p>But on initial testing having a div with no scrollbar <code>overflow-y: hidden</code> and using JS to scroll up and down in the div is a very smooth and easy process that prevents huge reflows from happening whenever LiveView is appending an element.</p>
<p>So at least in my case where I have thousands of messages, I must be able to stay at the bottom of a div to see the new messages, and I have a stricter latency requirement on the front end I am going to need to override the normal way a browser handles scrolling and do something custom for my client.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="179835" 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-append-and-performance-degradation-with-large-number-of-appended-elements/32376/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-179835" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="179835"
                     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="179836" data-post-id="179836">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="mononym" data-post="26" data-topic="32376">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mononym/48/4124_2.png" class="avatar"> mononym:</div>
<blockquote>
<p><code>overflow-y: hidden</code> and using JS to scroll up and down</p>
</blockquote>
</aside>
<p>Scroll-jacking isn’t really considered best practice. The solutions I know from vuejs use a scrollable container, which has only a single child set to the correct height of all list items. But as children of that inner wrapper only the number of visible list items are rendered. This way you still get native scrolling, but far fewer dom nodes. That option only works with client side templating though.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="179836" 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-append-and-performance-degradation-with-large-number-of-appended-elements/32376/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-179836" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="179836"
                     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="179842" data-post-id="179842">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mononym" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mononym/120/4124_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mononym
                    <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">
								<blockquote>
<p>Scroll-jacking isn’t really considered best practice.</p>
</blockquote>
<p>Yeah, I know, and if it were just a normal webpage I wouldn’t consider it. Given that this is the main window of a game client, though, I think I can get away with it since it’s already going to be acting like something other than your typical webpage.</p>
<blockquote>
<p>That option only works with client side templating though.</p>
</blockquote>
<p>That is the “ideal” solution as far as the technical side of things go. And in the end if I have to make a vue component/app to inject for that one specific area of the screen I’ll do it.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="179842" data-batch-url="/posts/batch_likers">
                        1
                      </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-append-and-performance-degradation-with-large-number-of-appended-elements/32376/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-179842" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="179842"
                     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="179917" data-post-id="179917">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mononym" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mononym/120/4124_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mononym
                    <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>Apparently I don’t need to do anything fancy. Setting a max height for the div did the trick.</p>
<p>Apparently the browser (Chrome anyway) is smart enough to know how to show a scroll bar the proper size for a div with a max height and can properly ignore all of the elements that are not in view, which brings down the time it takes to append down to 50-80ms consistently which is entirely within reason for me.</p>
<p>But you toss a div at the browser that doesn’t have a max height and is going to need to scroll it chokes because it cannot, for some reason, determine that most of the elements are not visible and so it does a ton more work. TIL.</p>
<p>Once I include batching of messages from the server side this will work perfectly well for my needs.</p>
<p>Thank you everyone for helping to expand my understanding and for helping me piece together where the issue was.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="179917" data-batch-url="/posts/batch_likers">
                        6
                      </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-append-and-performance-degradation-with-large-number-of-appended-elements/32376/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-179917" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="179917"
                     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="197614" data-post-id="197614">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Even in javascript land, DOM libs move towards not walking tree for dom nodes update. Lighterhtml, Svelte, even latest Vue’s virtual dom new implementation is optimized so they do not walk tree, perform lots of referential equality check (Lazy nodes). Old VirtualDOM style is pure overhead.</p>
<p>At first .leex technique is exactly like JS’ “tagged template literal” where static and dynamic arrays joined together. But since LiveComponent was introduced, the diff-to-string process on client side gets heavier (recursively walking component ids (cids) and nested dynamic parts before hand over to Morphdom), and LiveComponents diffs tracking eat memory (unfortunately I’m lazy to benchmark 100 concurrent users on 100-cids page).</p>
<p>At this point I +1 to Drab’s <code>%{"selector" =&gt; %{innerHTML: "..."}}</code> approach. That addresses performance problem on “list/table” and “tree” -like UI update (rather than phx-update=“prepend/append”). Example widgets, “Excel” and “interactive json”. This is not only patching performance problem but also include memory usage.</p>
<p>After using liveview for months, I just realize this! Now I do exactly like Drab <code>%{"selector" =&gt; %{innerHTML: "..."}}</code> but with <code>push_event/3</code> also with <code>pushEventTo/reply</code> and friends. Though for non-complex UI, I keep the current approach since the perf is relatively good.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="197614" 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-append-and-performance-degradation-with-large-number-of-appended-elements/32376/30">Post #29</a>
	                </div>
	            </div>
              <div id="likers-container-197614" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197614"
                     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="197618" data-post-id="197618">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="50kudos" data-post="30" data-topic="32376">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/50kudos/48/4435_2.png" class="avatar"> 50kudos:</div>
<blockquote>
<p>At first .leex technique is exactly like JS’ “tagged template literal” where static and dynamic arrays joined together. But since LiveComponent was introduced, the diff-to-string process on client side gets heavier (recursively walking component ids (cids) and nested dynamic parts before hand over to Morphdom), and LiveComponents diffs tracking eat memory (unfortunately I’m lazy to benchmark 100 concurrent users on 100-cids page).</p>
</blockquote>
</aside>
<p>Would not make sense to open an issue in Github for this?</p>
<p>Or maybe notify(via forum) Chris McCord for this performance issues?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="197618" 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-append-and-performance-degradation-with-large-number-of-appended-elements/32376/31">Post #30</a>
	                </div>
	            </div>
              <div id="likers-container-197618" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197618"
                     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/32376/load_more?page=4">Load more posts (3 remaining)</a>
</div></template></turbo-stream>