kuon
Performances when using live view with large table
I am using live view to render a table:
<table>
<thead>
<tr>
<th>#</th>
<%= for c <- @columns do %>
<th>
<%= tr(c.display_name, 32) %>
</th>
<% end %>
<th></th>
</tr>
</thead>
<tbody>
<%= for {r, rnum} <- @rows_index do %>
<tr class="<%= if rnum == @selected_y do "selected" end %>">
<td><%= rnum + 1 %></td>
<%= for {val, cnum} <- r do %>
<td phx-click="select_cell"
phx-value-x="<%= cnum %>"
phx-value-y="<%= rnum %>"
class="<%= if cnum == @selected_x && rnum == @selected_y do "selected" end %>">
<%= val %></td>
<% end %>
<td></td>
</tr>
<% end %>
</tbody>
</table>
I have about 150 columns and 10 000 rows.
The problem is that when I do the select_cell call, and update selected_x and selected_y the update takes a few seconds.
Is there a way to optimize this with live view, or should I move to JS?
Trending in Questions
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
Using Phoenix.LiveView.TagEngine as an EEx.Engine is deprecated!
To compile HEEx, use Phoenix.LiveView.TagEngine.compile/2 instead.
Sta...
New
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app?
Looking for hints regarding:
Addi...
New
Hi all, I wanted to ask how the community is dealing with post-release steps.
Today we have Ecto migrations, which make sure that the db...
New
I am using Oban and occasionally, shortly after a deployment, a handful of jobs can fail because of dependency on other parts of the syst...
New
Hello,
I have an Elixir backend that implements a custom protocol over TCP. I want to load test the backend and assess the performance o...
New
Other Trending Topics
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #hex
- #performance










First 10 of 18 Posts
chrismccord
You should use temporary assigns for the rows and you can either use
phx-update="append"and append the two updated rows (the old row which is now unselected and the new selected row), or you can use a component for reach row, and do asend_updateto the old selected row, and newly selected row. Both options will send the minimal diff down and not require holding 10k rows in your server state.kuon
If I get this right, I should:
Is that the way to go?
chrismccord
You don’t need the pubsub step and instead of targeting the component, let the parent LV handle the event, then it performs the send_update to both the component children. The parent LV has the selected state, so it can use that to
send_updatethe selected component, then the handle_event params can contain the desired selected row, which you will use tosend_updatethe newly selected component. Make sense?kuon
Yes, it is working with
send_updatefrom the live view.I did create a component for each rows, but with large tables (>100 columns), even updating a single row takes a noticeable time.
Is it possible to nest components? Like having a component for the row that would just render
<tr class="...">and only handle the switch of class on the the row while using a for loop to render sub components? Would that just work?Also, I have a “tab” selector above my tables, and when I change tab, I need to re-render the whole table. Right now, live view is sending a “huge” diff with every rows when changing tabs. Is it possible to tell live view to just re-render the container and replace the whole container content in one operation?
50kudos
I have quite similar application, using
send_updatecan get hairy at some point (like jQuery approach, sometimes it needs other components updated too e.g. resetting [ui] state for the rest, and only update a component)I have a very big tree component (recursively rendered), so yes nested components is possible. However, the way out often is rethinking of state design. It’s quite tricky to get minimal diff payload for large DOM nodes.
I am moving towards more pagination, less DOM nodes is better. For the “tab”, you could possibly remodeling your assigns, moving assigns that make it marked as “changed” out, when switching tab 1 → tab 2 → tab 1 (this stays unchanged), but if you want always fresh data, I don’t think there is a way around other than reducing DOM nodes. (And I think
toStringon javascript side is not that performant .. something around Array.from that is slow)Also be aware of memory usage per process (per browser tab) too!
kuon
I tried to have a top component, like this:
This above component render a
tag with thousands of cells.Now, when I change the
@tablein the top component, instead of just having 1 single big difflike wrapper.innerHTML = "some big chunk of html"I have thousands and thousands of diffs which takes tens of seconds to be applied. (if I render the HTML normally without live view, rendering in the browser is instant)My tab selector could be regular links, but I want to keep the state between tab changes.
My use case is some sort of spreadsheet editor. I could use some JS lib, but I tested native HTML rendering, and everything is butter smooth with thousands of rows, browsers are really good at managing large pages and I thought I could leverage this with live view, but live view needs to have minimal diff.
kuon
I also tried nesting live views, but when the child live view is unmounted/remounted, there is also a huge diff which takes a very long time to be processed (much longer than just doing similar to
innerHTML = newdata).50kudos
My untested idea is that you could do something like what infinite twitter feed does, only render rows fit within screen viewport, not sure if it would be clunky or not. For example, 300 rows. The downside is native search on browser will suck.
That’s the only solution (pagination) I stick with, I gave up minimizing diff payload in other way since it’s going to have at least a bunch of one character keys (a lot of them alone without content is huge)
Or just give up view layer on server for those cells, just push_event with pure data and use whatever lib to render the cells on client.
50kudos
Also I guess your
sel: @selsit on every row (somewhere like<%= if @sel, do: "" %>), its change always mark the whole table (i.e. every row) as change and produce diff payload of every row even if@tabledata is unchanged.kuon
Well “smart partial client side rendering” is possible, but I want to avoid that because rendering the whole table works very well even with huge table.
And I don’t want to minimize diff size, what I’d like is to have a single large diff for the table when the table change, not a million small diffs for all element in the table.
As I said if I re-render the whole table, I’d like the container’s content to be swapped with the new content, in one single operation. I don’t want a million diff be applied, which is very slow.
So I am wondering if this is possible with live view.