What’s a reasonable expectation of angular performance?

So my app is slow. That slow part consists of iteration over medium complex components with another bunch of nested components inside
image

Trying to render more than one of these started to add up a LOT of scripting time, up to the point where trying to render 10 of them caused 30 second freeze.

The first and biggest culprit I found was @angular/flex-layout, which, as you know, if you managed to click deep enough inside the wiki can not handle more than a hundred of grids (since I used it inside like 10 of the nested components inside it easily added up to that critical number).

But even still, with flex-layout completely gone, trying to render 100 of these can take around 12 seconds, so I thought there must be sometimes else wrong and tried to establish a baseline on a completely fresh project. That can be found here https://github.com/fxck/ngperf.

Baseline

Iterating over 200 items, printing simple text.

image

That takes around 100ms from click on the button to the content being visible.

image

Baseline for complex tests

Iterating over 200 components with mat-card and ngClass inside
image

image

That takes around 200ms from click on the button to the content being visible.

image

Test 1

Adding 20 empty divs to complex baseline

image

That takes around 250ms from click on the button to the content being visible, most of the extra time taken by rendering, which makes sense.

image

Test 2

Adding 20 divs with ngClass and ngStyle on them

image

That takes around 400ms from click on the button to the content being visible, extra time coming from scripting.. given that’s total of like 4000 new ngClasses and ngStyles, 100ms extra time spent on scripting is fair I guess
image

Test 3

Adding 20 components with a single div with ngClass and ngStyle inside them

image
image

Now this takes around 900ms from click on the button to the content being visible, 200 extra milliseconds coming rendering and another 200ms from scripting.

image

The third one confuses me the most, why would it take double the amount of time between test 2 and test 3? That makes me question everything about splitting my app into many reusable component, if there’s a huge performance hit like this.

Coming back around to my actual component (https://i.imgur.com/aoyc1er.png), it has quite a few nested components, most of them have multiple states, content projection, styles, classes, so seeing how much mess can an empty component create, how many can I possibly render at once before having to resort to infinite scroll strategies?

(both repro and my app uses v10)
image


btw this is what rendering 20 of those components looks like WITHOUT flex-layout

image

and WITH flex
image

20 seconds of scripting time difference!

Author: Fantashit

3 thoughts on “What’s a reasonable expectation of angular performance?

  1. @fxck I’m starting to look into your scenarios (for now beginning with comparing baseline with the iterating over <app-simple>) and I’m getting substantially different numbers from the ones you’ve posted. I will obviously keep digging and will share my findings here, but just to verify the obvious (I’m sorry, I know that those are basics but I’ve seen so many skewed perf measurements in the past that I prefer to verify):

    • are you running your application in the prod mode when taking measurements (ng build --prod)? The dev mode has significant overhead, so I wouldn’t expect numbers to be any good;
    • are you taking measurements in the incognito mode with all the extensions switched off? Many browser extensions can interact with the page and skew the results significantly.

    For the record I’m seeing ~50%% difference (~9ms -> ~14ms scripting time) moving from baseline -> simple on the initial render (going from an empty list to a rendered one). Off the bat I would say it is in-line with my expectations as:

    • there is 2x amount of DOM nodes (div + app-simple so we are not really comparing the same generated pages);
    • components do have cost (I will expand on it later).

    In any case – as of right now I’m seeing significant discrepancy between your and my numbers so we need to clarify this first.

  2. OK, so there are many scenarios being discussed here and many measurements so let’s start tackling them one by one. Let’s start with the baseline (200 <div> elements ) -> simple (200 <app-simple> instances).

    First of all, as indicated previously, I don’t think we compare apples to apples here as the DOM created is very different in both scenarios:

    • 200 x <div class="item">raw</div> in the baseline
    • 200 x <div class="item"><app-simple>simple</app-simple></div> – notice that we are creating 2x amount of DOM nodes here.

    Let’s put the difference aside for the second and have a look at the numbers I’m getting (scripting for first creation in the incognito mode, production build):

    • baseline: ~10ms
    • simple: ~14ms (~45%% overhead).

    See pictures below:

    Screen Shot 2020-07-23 at 14 13 58

    Screen Shot 2020-07-23 at 14 15 52

    Again, the DOM produced is not the same and the DOM nodes creation + connecting together takes time. If we change the app to generate the same amount of nodes like so:

    <app-simple class="item" *ngFor="let item of data; trackBy: trackByIndex;"></app-simple>

    the numbers get much closer:

    • baseline: ~10ms (as before)
    • simple: ~11.5ms (~18%% overhead).

    See picture below:

    Screen Shot 2020-07-23 at 14 19 09

    Obviously the numbers fluctuate a lot from one run to another (this is another story worth several blog posts) but TBH I’m surprised that we see < 20%% overhead here given all the work we need to do to instantiate a component (it is much work work than just creating an instance of a class – we are allocating internal data structures, resolve DI injection, take care of CSS encapsulation etc.).

    Components are definitively not “free” – especially in the case you are demonstrating here (where each DOM node is replaced by a component).

    I can share profile recordings with the above numbers as needed.

    For now I’m afraid that I ca’t reproduce the same numbers as reported (at least not for the case discussed in this comment). We will need to understand why we are getting different numbers and as noted before I would expect either a dev mode or browser extensions – to be investigated. @fxck could you please check the settings when capturing measurements?

    I will keep looking at the other scenarios as well but yeh, we need to gain more trust in the numbers shared initially.

Comments are closed.