Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(ivy): move attributes array into component def #32798

Closed
wants to merge 4 commits into from

Conversation

crisbeto
Copy link
Member

@crisbeto crisbeto commented Sep 21, 2019

Currently Ivy stores the element attributes into an array above the component def and passes it into the relevant instructions, however the problem is that upon minification the array will get a unique name which won't compress very well. These changes move the attributes array into the component def and pass in the index into the instructions instead.

Before:

const _c0 = ['foo', 'bar'];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', _c0);
  }
});

After:

SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', 'bar']],
  template: function() {
    element(0, 'div', 0);
  }
});

A couple of cases that this PR doesn't handle:

  • Template references are still in a separate array.
  • i18n attributes are still in a separate array.

@crisbeto crisbeto force-pushed the FW-1545/attrs-on-def branch 2 times, most recently from b419ac2 to b90be9e Compare September 21, 2019 08:38
@crisbeto crisbeto added comp: ivy action: review The PR is still awaiting reviews from at least one requested reviewer target: major This PR is targeted for the next major release labels Sep 21, 2019
@ngbot ngbot bot modified the milestone: needsTriage Sep 21, 2019
@crisbeto crisbeto marked this pull request as ready for review September 21, 2019 08:56
@crisbeto crisbeto requested review from a team as code owners September 21, 2019 08:56
@crisbeto
Copy link
Member Author

@mhevery I've reworked it based on the feedback. Can you take another look?

packages/core/src/render3/VIEW_DATA.md Outdated Show resolved Hide resolved
packages/core/test/render3/perf/setup.ts Outdated Show resolved Hide resolved
packages/core/test/render3/render_util.ts Outdated Show resolved Hide resolved
packages/core/test/render3/render_util.ts Outdated Show resolved Hide resolved
packages/core/test/render3/render_util.ts Show resolved Hide resolved
packages/core/test/render3/render_util.ts Outdated Show resolved Hide resolved
const literal = o.literalArr(constExprs);

// Try to reuse a literal that's already in the array, if possible.
for (let i = 0; i < this._constants.length; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going through the constants list every time we see an attribute seems like it might be slower. Could we re-use some of the existing constant pool logic here to de-dupe?

const lView = getLView();
const tView = lView[TVIEW];
const tViewConsts = tView.consts;
const consts = tViewConsts === null || constsIndex == null ? null : tViewConsts[constsIndex];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we checked yet if there's any perf impact of the extra read using the micro-benchmarks?

Also, wouldn't constIndex be null if tViewConsts is null? Could we remove the tViewConsts === null check?

Suggested change
const consts = tViewConsts === null || constsIndex == null ? null : tViewConsts[constsIndex];
const consts = constsIndex == null ? null : tViewConsts[constsIndex];

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't run any if the benchmarks yet. Also the constsIndex could be null if we need to skip over it to pass in the localRefs param. I suppose we can get rid of it once the local refs are in the consts array.

@kara
Copy link
Contributor

kara commented Oct 3, 2019

Compression diff

Before (left), this PR (right)

Screen Shot 2019-10-02 at 5 25 24 PM

Red squares -> yellow, showing some improvement

@petebacondarwin
Copy link
Member

Would it be possible to make consts a function that is called once before the template function is first called? This would allow us to avoid running initialization code before it is needed.

It would be particularly useful for the $localize calls. Currently $localize is being called as soon as the component is imported into the application. This makes it problematic to find a suitable moment to load translations. Currently all these I18N_... constants get initialized so early it is really hard to ensure that runtime translations are loaded early enough.

@crisbeto
Copy link
Member Author

crisbeto commented Oct 7, 2019

Makes sense to me @petebacondarwin. The question is whether we want to get these changes in and do a follow-up that turns it into a function and moves the i18n and references arrays into it.

@mhevery
Copy link
Contributor

mhevery commented Oct 7, 2019

Makes sense to me @petebacondarwin. The question is whether we want to get these changes in and do a follow-up that turns it into a function and moves the i18n and references arrays into it.

I vote to land this and follow up later.

Copy link
Contributor

@kara kara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but this is still blocked on running the microbenchmarks

Currently Ivy stores the element attributes into an array above the component def and passes it into the relevant instructions, however the problem is that upon minification the array will get a unique name which won't compress very well. These changes move the attributes array into the component def and pass in the index into the instructions instead.

Before:
```
const _c0 = ['foo', 'bar'];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', 'bar']],
  template: function() {
    element(0, 'div', 0);
  }
});
```

A couple of cases that this PR doesn't handle:
* Template references are still in a separate array.
* i18n attributes are still in a separate array.
@kara
Copy link
Contributor

kara commented Oct 8, 2019

@crisbeto Thanks for doing that! Looks like this PR gives us a slight perf edge, so we're definitely good to merge.

@alxhub
Copy link
Member

alxhub commented Oct 8, 2019

Presubmit
Ivy Presubmit

Copy link
Contributor

@mhevery mhevery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Can we do a follow up PR:

  • embedded template functions should also be moved to consts
  • Also include localization strings in the consts.
  • Change the ComponentDef.const to have a function which returns the arrays. The reason for this is that @ocombe and @petebacondarwin need a way to delay the execution of the $localize until after locale strings are loaded. By putting it into the closure this can be achieved. When TView is created and we copy the consts from ComponentDef to the TView we can execute the closure which will in turn execute the $localize and we would cache the resulting values in TView

@mhevery mhevery removed the action: review The PR is still awaiting reviews from at least one requested reviewer label Oct 9, 2019
@kara kara unassigned mhevery Oct 9, 2019
@kara kara added the action: merge The PR is ready for merge by the caretaker label Oct 9, 2019
@ngbot
Copy link

ngbot bot commented Oct 9, 2019

I see that you just added the PR action: merge label, but the following checks are still failing:
    failure status "google3" is failing
    pending 1 pending code review

If you want your PR to be merged, it has to pass all the CI checks.

If you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help.

@kara kara added the merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note label Oct 9, 2019
@kara
Copy link
Contributor

kara commented Oct 9, 2019

merge-assistance: global approval

@alxhub alxhub closed this in d5b87d3 Oct 9, 2019
crisbeto added a commit to crisbeto/angular that referenced this pull request Oct 13, 2019
Follow-up from angular#32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```
crisbeto added a commit to crisbeto/angular that referenced this pull request Oct 13, 2019
Follow-up from angular#32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```
crisbeto added a commit to crisbeto/angular that referenced this pull request Oct 13, 2019
Follow-up from angular#32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```
crisbeto added a commit to crisbeto/angular that referenced this pull request Oct 13, 2019
Follow-up from angular#32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```
crisbeto added a commit to crisbeto/angular that referenced this pull request Oct 16, 2019
Follow-up from angular#32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```
ODAVING pushed a commit to ODAVING/angular that referenced this pull request Oct 18, 2019
Currently Ivy stores the element attributes into an array above the component def and passes it into the relevant instructions, however the problem is that upon minification the array will get a unique name which won't compress very well. These changes move the attributes array into the component def and pass in the index into the instructions instead.

Before:
```
const _c0 = ['foo', 'bar'];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', 'bar']],
  template: function() {
    element(0, 'div', 0);
  }
});
```

A couple of cases that this PR doesn't handle:
* Template references are still in a separate array.
* i18n attributes are still in a separate array.

PR Close angular#32798
crisbeto added a commit to crisbeto/angular that referenced this pull request Oct 21, 2019
Follow-up from angular#32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```
crisbeto added a commit to crisbeto/angular that referenced this pull request Oct 27, 2019
Follow-up from angular#32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```
crisbeto added a commit to crisbeto/angular that referenced this pull request Oct 29, 2019
Follow-up from angular#32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```
crisbeto added a commit to crisbeto/angular that referenced this pull request Nov 1, 2019
Follow-up from angular#32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```
crisbeto added a commit to crisbeto/angular that referenced this pull request Nov 4, 2019
Follow-up from angular#32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```
atscott pushed a commit that referenced this pull request Nov 4, 2019
Follow-up from #32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```

PR Close #33129
atscott pushed a commit that referenced this pull request Nov 4, 2019
Follow-up from #32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```

PR Close #33129
mohaxspb pushed a commit to mohaxspb/angular that referenced this pull request Nov 7, 2019
Follow-up from angular#32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```

PR Close angular#33129
mohaxspb pushed a commit to mohaxspb/angular that referenced this pull request Nov 7, 2019
Follow-up from angular#32798. Moves the local references array into the component def's `consts` in order to make it compress better.

Before:
```
const _c0 = ['foo', ''];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', null, _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', '']],
  template: function() {
    element(0, 'div', null, 0);
  }
});
```

PR Close angular#33129
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Nov 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note target: major This PR is targeted for the next major release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants