Stencil: Large memory overhead for component instances

Created on 2 Feb 2018  路  3Comments  路  Source: ionic-team/stencil

Stencil version:

 @stencil/[email protected]

Current behavior:
If you are rendering a large number of components then the number of @Prop() properties impacts the memory requirements and rendering performance.

Here is an example where each component instance adds 6k to the heap:

// my-component.tsx
import { Component, Prop } from '@stencil/core';
@Component({
    tag: 'my-component'
})
export class MyComponent {
    @Prop() property1;
    @Prop() property2;
    @Prop() property3;
    @Prop() property4;
    @Prop() property5;
    @Prop() property6;
    @Prop() property7;
    @Prop() property8;
    @Prop() property9;
    @Prop() property10;
    @Prop() property11;
    @Prop() property12;
    @Prop() property13;
    @Prop() property14;
    @Prop() property15;
    @Prop() property16;
    @Prop() property17;
    @Prop() property18;
    @Prop() property19;
    @Prop() property20;
}

// my-page.tsx
import { Component, Prop } from '@stencil/core';
@Component({
    tag: 'my-page'
})
export class MyPage {
     render() {
        const list = [];
        for (let i=0 ; i < 1000; i++) {
            list.push(<m2-component />);
        }
        return list;
     }
}

When the page is rendered it creates 1000 instances of the component. Note: in this case there is no JSX content rendering that occurs so it is the minimal implementation of a component.

Refreshing the page is somewhat slow even though there is no content.

  • Roughly 1500ms to refresh
  • Console shows warnings such as: [Violation] 'requestAnimationFrame' handler took 97ms during rendering

It also looks like there are significant memory requirements for the components.

  • Heap increases by over 6mb compared to the same component without properties (6k per instance). This overhead is even if none of the properties are used.
  • Memory increases roughly linearly with the number of @Prop() properties that are defined.
  • Some of this memory may be associated with the instance getters and setters (vs. prototype members) used by Stencil. This results in many dynamic function definitions and closures.

I know you guys are working hard on performance but I thought I would mention these items before Stencil gets too locked down since they seem like they could be significant with real apps. Ionic core has many components with lots of optional properties so it would likely impact Ionic memory requirements.

performance

Most helpful comment

Stencil One features a new runtime that is way more V8 friendly, we are adding few bytes on top of the overhead of customElements itself, in addition, we started using Constructable Stylesheets, which reduces the memory usage caused by stylesheets drastically!

Stencil 1.0 will hit beta in the upcoming weeks!

All 3 comments

After reading this, I really wonder whether it makes sense to wrap certain functionality in simple components instead of just using functions?

I was thinking of making something like this time-ago-web-component for my app, which just has a date prop, but then might be used many times on a single page (e. g. last activity of chats in a chats list).

Has there been any more investigation/improvements on this front?

I use a combination of stencil web components and purely functional components. Functional components can still be used in JSX just like stencil components.

Some of the benefits of functional components include:

  • Fastest rendering due to very simple function call.
  • No additional memory overhead per instance.
  • Synchronous rendering

Some of the limitations of functional components include:

  • Unable to have state and change rendering over time. They simply render based on input properties.
  • Unable to have tightly coupled css. Global styles and class names can be used but it starts getting coupled to the app.
  • Some async loading differences.

It is hard to know all of the tradeoffs until Stencil is complete. In general I use functions for simple stateless rendering - especially if there are likely to be large numbers of instances of a component.

Stencil One features a new runtime that is way more V8 friendly, we are adding few bytes on top of the overhead of customElements itself, in addition, we started using Constructable Stylesheets, which reduces the memory usage caused by stylesheets drastically!

Stencil 1.0 will hit beta in the upcoming weeks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mitchellsimoens picture mitchellsimoens  路  3Comments

romulocintra picture romulocintra  路  3Comments

lcswillems picture lcswillems  路  3Comments

ryanmunger picture ryanmunger  路  3Comments

karsvaniersel picture karsvaniersel  路  3Comments