Baseline performance of rendering components is "slow"

This is a topic that might have been discussed to death, and I might think that my case is slightly different, when in fact it isn’t. If so, feel free to close this thread with an RTFM or whatever you wish.

Basically the issue I’ve run into is that it takes around 0.3-1.5 ms to render a component. In this case just a component with static HTML and no properties, attributes or actions. That might not seem much. The problematic case is iterating a large list and rendering components within that. This list might have thousands of objects, and even at 1000 it might take ~1000 ms (1 second) to render the list. I’m trying this on a macbook pro latest generation, so it’s not mobile issue or anything, using Chrome.

Check out the git repo I made to demonstrate: (Note: I tried both in development and after ember build)

Am I doing something wrong by rendering components within a list iteration? Is 0.3-1.5ms acceptable? Is this something that’s actively being worked on? Is my method for measuring wrong? What’s the general thought about this?

Glimmer 2.0, which is in active development now, will deal with initial render performance. Whereas, Glimmer 1.0 (landed in Ember 1.13) mainly delt with re-render performance, but inadvertently slowed initial render performance. Not sure when Glimmer 2.0 will land, sounds like possibly in the next couple 2.x.0 releases, so 6-12ish weeks until beta (or more).

I can’t speak to optimizations for large lists, I haven’t had to deal with that just yet, so I’ll let others speak up on that topic. My only feedback would be to specify a key in the {{each}} helper.

ember build and ember serve produce identical results. Make sure to test in production mode with ember build -prod or ember serve -prod. It should be faster, but what @Panman8201 said still holds true.

Just came across this thread again when I was seeing slow rendering times in another app. :slight_smile: Tried removing helpers, variables etc and then realised that it was just Ember being slow on initial renders for HTML elements. Glimmer 2.0 didn’t really help apparently, I wonder if these is any possible optimization possibility here? I replaced a fairly complex dynamic component with a component with 50 <div></div> in it and the rendering time was still super slow. (Took 1.5 seconds just rendering around 5000 static elements).

Are you rendering a bunch of stuff off screen? Do you have a ton of observers? Do you do any data manipulation after rendering, but before user interaction?

What ember version?

Benchmarking in browsers is quite slippery, especially given the somewhat random-feeling impact of the JIT. But for comparison, I just timed rendering of 5000 divs on a production build of 3.12 canary on desktop chrome and got 75ms. If you’re seeing numbers 20 times worse under similar conditions, something weird is going on that needs to get debugged more carefully.

If your component count (as opposed to Element count) is high, it’s also worth making sure you’re using glimmer components and not classic components. In a quick comparison, I’m measuring them as 3x to 5x faster.

  • for template-only components, make sure you have the template-only-glimmer-components optional feature turned on. This is the default for new apps, but longer-lived apps will need to enable it. The only thing this requires you to do is to explicitly add the wrapping <div> to your template-only components, whereas before that div got added magically by ember. (Not having the magic wrapping div is extremely nice by itself, even if there wasn’t a performance boost to glimmer components.)
  • for JS-backed components, you extend from @glimmer/component instead of @ember/component. The best source of documentation for this is the Octane Guides. The octane guides are still in preview but most of the features they document are already available in stable ember releases.

I also just tried this with traditional Ember components in this Ember Twiddle and it’s not quite instantaneous, but it’s also nothing like 1.5s. :thinking:

Using Ember version 3.10.

I guess the problem includes lots of components. I don’t have insanely many but a “regular” amount. I tried removing all CSS, all observers. When you say observers does that include computed properties?

I haven’t found any good documentation on how to use @glimmer/component in an existing 3.10 app. I tried simply installing npm install --save-dev @glimmer/component and converting one component, but kept getting errors. Did I miss a flag somewhere? Should it just slot in?

What I did now to be able to cut the time in half (from 1.5s to steadily 0.8 seconds) was to reduce the number of components, so I’m quite intrigued to try glimmer components to see if that can help so I don’t have to fatten up my components.

For glimmer components in ember, you need the alpha version. Checkout the octane blueprint for specifics <3

What I did now to be able to cut the time in half (from 1.5s to steadily 0.8 seconds) was to reduce the number of components,

Components rendered or components total? Were you rendering the world instead of the scene? (Rendering things outside the viewport)

I changed the “hot” component to be a Glimmer component. Average render time went from 800ms to 500ms. Which is a huge difference!

I wonder, would migrating ALL components to Glimmer components speed up everything further, or is the speed-up on a per-component basis? My thinking it’s either re-rendering the entire tree that’s slow, or just that rendering one component is slow if multiplied by many components.

I fell down the performance rabbit-hole when I was implementing drag-and-drop for these “hot” components, and moving an item in this list caused frames to take 800ms to load.

Yep! Glimmer Components are much faster. Template-only Glimmer components are faster-yet. So if you can refactor some of this so you end up with a lot of those rendered-many-times components being template-only Glimmer components, you will see substantial further increases in performance.

1 Like