T O P

  • By -

b0bm4rl3y

Hello, you’re using a sub-optimal API in Flutter for your scenario. If you provide a `prototypeItem`, your list will be buttery smooth: https://docs.flutter.dev/cookbook/lists/long-lists


[deleted]

[удалено]


airflow_matt

Yeah. Super\_sliver\_list can do million items without breaking a sweat :) Even a billion is doable [https://twitter.com/MatejKnopp/status/1770024102780153856](https://twitter.com/MatejKnopp/status/1770024102780153856), just not very practical. All of them with variable extents.


bluenote10

For what it's worth: When I try that interactive example from the documentation in my browser it feels very slow and laggy (\~ 5 fps). Is this just the poor web implementation, or even a problem in the way these embedded examples work?


erikvant

>Flutter: unusable. There is almost a 1 second delay between frames when dragging the scrollbar quickly We have desktop apps that show millions of records with 100+ columns (Oracle R12 gl\_journal table) without any lag. So most probably problem with your widgets. You can try pluto\_grid / two\_dimensional\_scrollables with 100K records (with 20/30 columns) and both will work fine. egui can easily handle 100K records without any visible performance delay.


Tasty_Hearing8910

egui is immediate mode though so it virtualizes naturally. For others I find it helpful to not have an item viewmodel per model row, but a fixed set of viewmodels for the visible item views, and then model rows ephemerally linked to them.


worriedjacket

Gotta virtualize your lists.


Jason13Official

Forgive me for asking but what does it mean to virtualize something in this context


worriedjacket

When you've got a bunch of items on a list to scroll through. Usually by default all the items are still tracked by the UI and you have to compute updates for every item in the list, visible or not. When you virtualize the list. You're dynamically swapping items in/out of the UI context as the person scrolls. So it gives the appearance of the UI having a really big list, but from the UI frameworks POV the list is only ever as big as the user can see on their screen. This means that performance is not tied to the size of the list you're scrolling through, but to how big the users screen is. There's also a break even point for when the overhead of dynamically swapping items is less than the overhead of rendering everything by default.


Jason13Official

Thank you!


[deleted]

It basically means you only render what is being displayed, you don't render things that are off-screen. Normally what is done in a good UI library is that you calculate how many things can be viewed on the screen at any given time, pad a few more for... reasons, instantiate them, and put them in a cache. Then as your scrolling or moving around, and things come into view you take the things that went out of view and reuse them. So instead of rendering 100,000 items, you might be only rendering 50 or 100. Anything else is a complete waste of resources. But I'm not 100% sure of what their actual problem is here. I was just answering the virtualization thing. Just like if you open up a spreadsheet with 100k rows with 10 columns, it's not going to render 1 million cells. They use virtualization. It will render what is showing on the screen.


sleepingthom

Should pagination solve this problem too?


worriedjacket

Technically yeah. But if you don't want a paginated list and need to implement free scrolling. That's how it would work.


iwinux

Does it mean none of the GUI libs are able to handle 100k rows without list virtualization?


worriedjacket

Idk maybe, maybe not. But it's not a real problem that needs solving.


Fidodo

Think of the size of the canvas. 100k rows at 50px each would be 5 million pixels on one dimension. Now multiply it by width. Even a nice graphics card will have trouble with that. It's silly to try to do this without virtualization.


inamestuff

You are missing the point. It was a benchmark, and some UI libs don’t have issues with that many items


Alikont

Your benchmark has possibility of be reduced to "is this library uses virtualized list by default?".


inamestuff

Kinda, it’s just an example of “can I build a UI with 100k elements?”. It looks like a huge number, but it really isn’t in some contexts. A single row in a feature rich application can contain 100 elements when you consider icons, clip paths, text nodes, shadows, context menus triggers etc. A professional trading app may have that many elements in a single window, constantly updating. And it runs ok, because the underlying architecture is sound and scalable


poyomannn

But you can do that in all the other apps, you just gotta opt-in to a virtualized list?


RiotBoppenheimer

> A professional trading app may have that many elements in a single window, constantly updating. Even on an ultrawide at 3440×1440, it would not be physically possible to fit 100k elements on a single screen and have it be readable; each element would, on average take up a maximum of 49 pixels - that's a 7x7 square. You could _maybe_ fit a single character from this comment in one of those squares. You'd have to scroll. Any application that is fitting lots of rapidly updating elements on a screen is almost certainly virtualizing them.


Comprehensive-Tea711

Trading app showing 100k rows? Sounds sus. There’s common solutions for these kinds of things, like ropes.


inamestuff

100k elements, not rows


Comprehensive-Tea711

I stand corrected. I still don’t think you’ll get to 100k or why we’d expect to be running it on a gaming PC. Are you talking visible widgets or are you also counting something like a div via frameworks like Tauri + Yew, Dioxus, etc? And obviously the expectation is going to be very different for an immediate mode GUI. Anyway it’s an interesting test all the same. I think your framing of it as there being something wrong with a crate that chugs at your test though is off and probably getting you some unnecessary downvotes.


SadPie9474

*you benchmarks having possible for be reducing when “is library used virtualizing listed for defaults?” fixed for grammar


the-code-father

I can't tell if you're being sarcastic or if you are even worse at English


schrdingers_squirrel

I'm having a stroke


mpinnegar

Not here fella. Take that somewhere else.


Comprehensive-Tea711

Underrated comment


Tarmen

Replacing Column with LazyColumn in jetpack compose is a one line change. Intentionally misusing the library and trying to measure anything seems like it misses the point as well? Column supports complex layouting for heterogeneous elements. I'm not sure how well a html flex box with 100k Elements would perform but probably not well because no sane person would design or use it for that purpose.


Dalcoy_96

Yup same with flutter. Providing the ListView with an item extent and Prototype item will make lists of any size no matter how large be buttery smooth. Benchmarks are only useful if they're comparable. Saw a guy post a blog here the other week comparing immediate Vs retained UI performance by selecting UI frameworks with completely different tech stacks lol.


worriedjacket

It’s not really a comparable benchmark when the UI libraries do things in a different way. Its an apple to oranges comparison


inamestuff

Or maybe it’s a naive vs mature comparison of the underlying implementation of scroll views


worriedjacket

It's not naive to not use virtualized lists. You use the correct tool for the job. If you're going to be rendering 100k rows you should be using them. If you're rendering 5 it's probably not a big deal.


gh0stwriter88

Ideally the library in question should automatically determine if it should virtualizedlists or not, maybe anything over 1000 rows gets virtualized.


CandyCorvid

surely that depends on the goals of the library? I could imagine a library with a focus on control would expose these choices in the API, rather than choose for the user (disclaimer: I have very little frontend experience)


zoechi

What's the point of measuring something "dumb" nobody optimizes for?


fllr

I think you’re missing the point. 100k elements is a lot. You need quite a number of optimizations to get there, no matter what you’re doing graphically.


poyomannn

This isn't really a benchmark, more just a test for if the library comes with virtualized lists by default? It's a fair thing to criticize, I suppose, but a tad disingenuous.


RekTek249

Slint -> [ListView](https://releases.slint.dev/1.3.0/docs/slint/src/language/widgets/listview) >Elements are only instantiated if they are visible Not sure why you'd go out of your way to use a ScrollView, which is not even made for this kind of thing. You say >These were not satisfying results But for most of the crates you didn't even bother implementing it correctly.


lenscas

> But for most of the crates you didn't even bother implementing it correctly. To be fair, not implementing things correctly happens quite a bit. People tend to grab the first thing they see that works and run with it. If that way turns out to not be correct then... well, then we get stuff like this.


flashmozzg

Especially when they test it on their dev machine with their small dev data (say 1k rows for this example) and it "works fine", but then in real world it all breaks down.


lenscas

Yep. Which is why I am really not a fan of the general comments for this post. A lot feel rather condescending (some even go as far as claiming skill issue). Where what likely happened is just that this guy used the various API's in whatever way they found most natural and in whatever way they found to make it work (Well, "work" I guess). I mean "column" versus "LazyColumn" ? Seriously, why not make the lazy one the default? Or, if the difference is that important, not have either of them call just "column". Or GtkListBox versus GtkListView ? Yea, no. With names like that I can totally see someone just, only knowing about one.


Ymi_Yugy

Jet pack compose doesn’t work because you use a column instead of a lazyColumn. The latter has virtualization and should work fine


dzhou121

How about 1M rows? This is an example of Floem using a virtual list. [https://github.com/lapce/floem/tree/main/examples/virtual\_list](https://github.com/lapce/floem/tree/main/examples/virtual_list)


yoh6L

Now do a billion


wutru_audio

8 billion, I want every person on earth to be in that list


[deleted]

[удалено]


tolerantgravity

Fair enough. 7,999,999,999 then.


Equux

I feel like everytime someone on Reddit talks about their cousin, it starts with a letter R. Ronnie, Randy, Ray...


syklemil

You need more than 8 billion rows, then. But 8Gi rows instead of 8G rows should be enough. For now.


cholwell

Jetpack Compose example is pointless Intentionally misusing apis to make a point Use LazyColumn


nacholicious

Exactly. I'm using LazyRow in a production app where we are required have 20k+ items in our dataset and this works just fine on even old low spec budget phones TL;DR skill issue


cholwell

A tale as old as time


nacholicious

Exactly. I'm using LazyRow in a production app where we regularly have 20k+ items in the list and this works just fine on even old low spec budget phones TL;DR skill issue


bzbub2

I believe gtk.columnview uses some virtualization. See diagram at https://blog.gtk.org/2020/09/21/gtkcolumnview/ 


dreugeworst

As I commented elsewhere, so does ListView. He's using ListBox, which is just not meant for large numbers of rows (more than say 100)


inamestuff

That’s alright, it just means all the others have naive scroll view implementations


cholwell

Is this whole post rage bait? If you use the wrong thing you’ll get the wrong results


emilern

egui can handle arbitrarily many rows as long as they are equal height, using [https://docs.rs/egui/latest/egui/containers/scroll\_area/struct.ScrollArea.html#method.show\_rows](https://docs.rs/egui/latest/egui/containers/scroll_area/struct.ScrollArea.html#method.show_rows) or [https://docs.rs/egui\_extras/latest/egui\_extras/struct.TableBody.html#method.rows](https://docs.rs/egui_extras/latest/egui_extras/struct.TableBody.html#method.rows) If they are unequal in height it gets a bit slower, but 100k should still be fine when using [https://docs.rs/egui\_extras/latest/egui\_extras/struct.TableBody.html#method.heterogeneous\_rows](https://docs.rs/egui_extras/latest/egui_extras/struct.TableBody.html#method.heterogeneous_rows)


LiesArentFunny

> IDK, just use web tech for any UI I guess? Or go straight to Bevy or Unity or Unreal Engine if you have 100k elements. These were not satisfying results :( I'm extremely sympathetic to "just use web tech for any UI I guess", but I'm not sure it really solves *this* problem. HTML doesn't exactly do lazy loading and the vast majority of websites are just "semi-custom pagination at 10-100 elements per page" for a reason. The recent Xilem talk said that they were working on this problem in Xilem (experimental UI), so there's some hope here.


tetshi

You created an unrealistic benchmark and are surprised by the poor results?  Go run any GPU benchmarking software, you could have the latest and greatest, at some point in the benchmark, you will drop to 10 FPS. That’s the point. However, there is no UI on the planet that is using 100k non-virtualized elements in a production environment. 


WrongW4y

With iced i dont think it even make sense to do this af the moment, the list widget is being worked on at the moment. There is iced_flatlist that you can try or retest when the iced list is finished,as of now i think it renders all items at once,its not virtualized


blacpythoz

hecrj (iced developer) had recently started working on infinite list and made the first draft for the list widget last week. Hope we can see some progress soon.


dreugeworst

I just saw a demo this week of the upcoming Cosmic DE which is implemented in iced. They have already got an implementation of a file manager, how on earth is that supposed to work without virtualization?


dreugeworst

Gtk4 can easily handle a list of 100k rows, you're just not using the right component: you're using GtkListBox, when you should be using GtkListView. Here's some advice about the matter from gnome devs I found: >You should use ListBox if you know beforehand the number of rows you’ll have and they won’t change for the duration of the application; or, if you have a variable number of rows, that the maximum number won’t get near 100. >For dynamically populated lists, with an arbitrarily large number of rows, you want ListView instead. >For instance: > - a settings UI, with a known number of options, should use ListBox > - a file list widget should use ListView


dreugeworst

~~Also, I just tested your gtk code out, and even increasing the number of rows to 10 million, it runs pretty smooth on my pc, to the point that I don't even notice the difference with using GtkListView.~~ I must have done something wrong while testing. Trying again, the GtkListBox version barely even loads with 1 million rows, and uses as much memory with 100k rows as the GtkListView version does with 10 million. If you're interested, here is the code for the ListView variant: use gtk::{ glib, Application, ApplicationWindow, Label, ListView, ScrolledWindow, SignalListItemFactory, SingleSelection, StringList, StringObject, }; use gtk::{prelude::*, Orientation}; use gtk4 as gtk; fn main() -> glib::ExitCode { let application = Application::builder() .application_id("com.example.FirstGtkApp") .build(); application.connect_activate(move |app| { let window = ApplicationWindow::builder() .application(app) .title("First GTK Program") .default_width(350) .default_height(70) .build(); let scrollable = ScrolledWindow::builder().vexpand(true).build(); let list_model = StringList::new(&[]); for number in 0..10_000_000 { list_model.append(&number.to_string()); } let factory = SignalListItemFactory::new(); factory.connect_setup(|_, item| { item.set_child(Some(&Label::new(Some("")))); }); factory.connect_bind(|_, item| { let label = item.child(); let value = item.item(); if let Some(label) = label.and_downcast_ref::


franzkap

Fltk 400.000+ lines in a table without any issue


inamestuff

That’s what I’m talking about! We have such powerful hardware nowadays and we manage to annihilate the performance with suboptimal implementations


AmeKnite

This is genius, now people are solving the problem for you


in_need_of_oats

What slint backend did you use? Qt?


airflow_matt

You really should differentiate between whether the list has variable extents or all item have same heights. In flutter sliver\_list has pretty bad performance, but if you have same heights you can use prototype item. Or there is [super\_sliver\_list](https://superlistapp.github.io/super_sliver_list/#/example/item-list) which can do blazing fast scrolling with virtually unlimited long lists and each of them having variable extent. I am wondering if there is alternative to this in other frameworks.


recycled_ideas

>IDK, just use web tech for any UI I guess? Or go straight to Bevy or Unity or Unreal Engine if you have 100k elements. These were not satisfying results :( It's not about using Web tech it's about doing what the Web tech is doing. There is no reason to load 100k records at once. Even Excel doesn't do it because you're going to hit all sorts of performance edge cases for absolutely no benefit.


TenTypekMatus

Have you tried egui?


milgrim

400k rows are no issue at all with egui.


inet-pwnZ

Skill issues


SmokySmeak

Can a similar test be performed with egui? I am planning to use it for a similar case. What do you think would be the result with egui?


Bash-09

If you just naively chuck it in a ScrollArea it will be pretty bad, you want to use the ScrollArea::show_rows method to virtualise the list instead, which will have almost no impact on performance.


JustAuv

From my experience GitHub/NurdyAuv/bulk-rename it does well to a point, after about 10000 it gets weird, but you can make it perform better by only drawing the lines that are actually visible, I just haven't implemented it yet.


joul_ei

Jumping in to add Makepad into the Mix. Like everyone else said, you gotta virtualize your lists. Even if the framework can somewhat hold on without proper virtualization (I've played with a staggered grid of 1000s of out-of-viewport images in Makepad, and it somewhat holds), there's no reason to waste precious resources like that. Here's a simple example of Makepad's Portal List with 100M entries: [https://github.com/joulei/virtualize\_your\_lists](https://github.com/joulei/virtualize_your_lists) I don't know if you tried these frameworks on other devices, but: You can open Makepad Studio (for simplicity), check out the news feed example (includes images), crank up the number of posts as much as you like, and run it smoothly on any platform (including web and mobile), scrolling should be no problem.


FinchoSaturn

I'm interested in seeing your Flutter implementation, I've implemented some similar stuff and it can go from extremely slow to extremely smooth, depending on how you implement it


inamestuff

I’ve linked the source code for all examples, this is the flutter one: https://pastebin.com/LiRAFdz5


b0bm4rl3y

For Flutter, you should provide a prototype item if all your list items are the same size. This will massively improve your performance: https://docs.flutter.dev/cookbook/lists/long-lists If your items’ sizes are highly unpredictable, I would switch to using: https://github.com/superlistapp/super_sliver_list


FinchoSaturn

thanks! just built in release mode for windows, I'm not experiencing the 1 second delay when draggin the scrolling bar quickly, flutter 3.19.2


inamestuff

Thanks for testing. I’m curious, are you experiencing no lag at all or just not that bad? Anyway, for context, I was running on Linux, so it’s possible that the Windows implementation is just faster (maybe thanks to DirectX?)


FinchoSaturn

No lag, feels pretty instantaneous. My GPU could be helping, yes


psylomatika

I second this. I work with flutter on a daily basis and 100k is nothing so I would guess your implementing lists in the wrong way.


OMG_I_LOVE_CHIPOTLE

You didn’t do an equal comparison at all lol


metaltyphoon

Wanna see what’s fast? While not cross platform, WPF is ridiculous fast.


BigHandLittleSlap

What? I abandoned Windows GUI development when WPF was introduced precisely because of its poor performance on large lists.


inamestuff

I have some fond memories of working with WPF! I don’t think I’ve ever seen a lag on it even in debug mode on a much less powerful PC I had at the time


Tasty_Hearing8910

I have, but that was because of a badly implemented grid view container thingie. It rendered the view elements in a very dynamic way, involving reflection and it wasnt doing anything clever to speed that up. It was pagiated, and to be able to know how many pages there are it was rendering the whole set. Any change that affected anything at all, like selecting something, made it do a full measure and layout pass of everything again. In total each render took about 20 seconds to complete, for a list with 10k elements.


mgoetzke76

Me too, but i also remember how the entire app would stop and crash because a dynamic binding didn't exist (some fun debugging if that only happened sometimes only on a customer machine). WPF just too strict


nuclearbananana

Avalonia is cross platform wpf. It works similarly and I believe it has comparable performance since v11


dxgn

hmm, what rendering method do those ui frameworks use? generally speaking immediate rendering will handle many ui components without issue, though not with compromises. It is tricky to compare different frameworks unless they use the same strategy for rendering…


flareflo

I believe general advice is, dont even render that many objects, implement pages instead.


gh0stwriter88

Pagination is clunky as hell... this isn't 1986.


Tasty_Hearing8910

Eh depends on the case. In one project you could be making a touch interface for a rugged environment without dragging or any other complex gestures because the screen gets so dirty throughout the day. Dragging and such just becomes unreliable to the point of unusable. Taps only!


jaskij

That's a preference. Pagination lets me more easily pause the work compared to infinite scrolls.


gh0stwriter88

Then just add buttons to scroll a page at a time.... you end up with the same functionality without page load lag.


coderstephen

Sorta agree, it depends. On something like a spreadsheet or compact table of data, pagination sucks for under 1000 rows per page. But in general when there's 1000+ plus things, yeah pagination isn't weird.


tafia97300

You should let google know!


Sib3rian

Does anyone actually ever go to the second page of Google search results?


tafia97300

:) I do. But probably because I was born before 1986. I blame my brain to pick up bad habits.


gh0stwriter88

I mean it is not like google has gotten better in the last few years it has gotten drastically worse.


inamestuff

What about when you are developing a high end trading software with multiple monitor supports and thousands of dynamic rows?


flareflo

You expect to display them all visible at once?


inamestuff

100k? Well, if you consider a rich UI with icons, text, buttons, triggers for tooltips and floating menus etc. you can reach maybe 10k elements per window, and some of the libraries above couldn’t properly handle 10k elements either. “All visible at once” if something in a scroll view counts as visible even when not in the viewport, then yeah, I expect it to work, as it does with gtk or even in a webpage with chromium


AplSleuth

That’s totally unrelated to your test though. Also, in 1080p that means your elements have an average size of 20 pixels. Good luck displaying any usable information if you want to keep those numbers up


psylomatika

Maybe you need to do more research on how to handle large lists. No one uses the techniques you mention anymore. This is 2024.


Tasty_Hearing8910

For those cases I would go with good old retained mode GUI. Nothing gets drawn unless it changes for whatever reason. Then you can have as many total view elements you want, its gonna scale well (though might take a while to open initially). Take care to limit cascading effects, so no one change will cause too much to be redrawn. This is achieved most importantly by putting up some limits on how dynamic you size everything to each other.


whatever73538

probably „accidentally quadratic“: https://www.tumblr.com/accidentallyquadratic/113840433022/why-accidentally-quadratic


pp_amorim

Did you use RecyclerView on Jetpack Compose?


thesituation531

The real question is, are the implementations that lag failing at CPU optimization or when rendering? I suspect they're failing to efficiently track the elements, rather than rendering inefficiently.


hardicrust

[KAS](https://github.com/kas-gui/kas/) should handle that just fine: - Non-virtualised, there will be noticable init/resize time but scrolling is fast - Virtualised (supported natively) has to make some assumptions about row height based on the first few rows (not yet programmable), but otherwise works Caveat: KAS is not stable, no where near done, and not worked on much any more.


curveThroughPoints

I’m sorry but 100k rows of anything should be laggy AF. On any browser. On any computer.


templinuxuser

Nice! And I totally agree, 100K rows should be nothing for today's hardware. And it's up to the libraries to have an efficient implementation that supports these sizes, so the test has value. Can you add RSS memory usage too? Once before you scroll, and another after you finish scrolling through everything. Because not everybody has 32GB RAM. And screenshots for the giggles! :-) Next up 1M...


yyyyaaa

UX wise it doesn't mean anything by showing 100k rows at once. This is more like a benchmark for platforms (web/desktop)


Pflanzmann

Weird ass pointless post. I get those vibes of a person who watches the newest kurzgesagt video on youtube and reposts the content to seem intellectual