vue icon indicating copy to clipboard operation
vue copied to clipboard

perf(core): getType uses a cache for well known types.

Open Glandos opened this issue 2 years ago • 11 comments

What kind of change does this PR introduce? (check at least one)

  • [ ] Bugfix
  • [ ] Feature
  • [ ] Code style update
  • [ ] Refactor
  • [ ] Build-related changes
  • [X] Other, please describe: Performance

Does this PR introduce a breaking change? (check one)

  • [ ] Yes
  • [X] No

If yes, please describe the impact and migration path for existing applications:

The PR fulfills these requirements:

  • [X] It's submitted to the dev branch for v2.x (or to a previous version branch), not the master branch
  • [X] When resolving a specific issue, it's referenced in the PR's title (e.g. fix #xxx[,#xxx], where "xxx" is the issue number)
  • [X] All tests are passing: https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#development-setup
  • [ ] New/updated tests are included

If adding a new feature, the PR's description includes:

  • [ ] A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)

Other information:

getType is called a lot, and it just run the same regexp over and over on the same base types. A cache increase its own efficiency by more than 80% for basic types. On a real world application with a lot of components, getType was profiled for 8% of call duration before this patch, and about 0.5% after. The impact is more limited for smaller applications.

Light application

Before: Profile light without cache After: Profile light with cache

Heavy application

Before: Profile heavy without cache After: Profile heavy with cache

Test was done on a laptop with Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz, Chromium Version 90.0.4430.212

Glandos avatar Jun 08 '21 14:06 Glandos

Thank you. Do you have a runnable sample in a single index.html file to check the perf gain?

posva avatar Jun 08 '21 14:06 posva

No :( I performed the test on my company's application that I'm currently developing. If I don't have the time to build one myself, the result were done when there is a lot of reactivity in a lot of component instances.

Glandos avatar Jun 08 '21 14:06 Glandos

Quick sample here: image image

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue 2 demo for https://github.com/vuejs/vue/pull/12123</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<button id="mount" type="button">click to mount</button>
<div id="app"></div>
<script>
    var exampleLength = 50000;
    var app = new Vue(({
        render(h) {
            var children = []
            for (let i = 0, len = this.arr.length; i < len; i++) {
                children.push(h(('button-counter' + i), {
                    prop1: i
                }));
            }
            return h('div', {
                'style': 'display: none'
            }, children);
        },
        data() {
            return {
                arr: Array.from({length: exampleLength}, (_, i) => i)
            }
        }
    }));
    {
        for (let i = 0; i < exampleLength; i++) {
            Vue.component('button-counter' + i, {
                props: {
                    prop1: [Boolean, String, Object, Number],

                    // Basic type check (`null` and `undefined` values will pass any type validation)
                    propA: Number,
                    // Multiple possible types
                    propB: [String, Number],
                    // string
                    propC: {
                        type: String,
                        // required: true
                    },
                    // Number with a default value
                    propD: {
                        type: Number,
                        default: 100
                    },
                    // Object with a default value
                    propE: {
                        type: Object,
                        // Object or array defaults must be returned from
                        // a factory function
                        default() {
                            return { message: 'hello' }
                        }
                    },
                    // Custom validator function
                    propF: {
                        validator(value) {
                            // The value must match one of these strings
                            return ['success', 'warning', 'danger'].includes(value)
                        }
                    },
                    // Function with a default value
                    propG: {
                        type: Function,
                        // Unlike object or array default, this is not a factory function - this is a function to serve as a default value
                        default() {
                            return 'Default function'
                        }
                    }
                },
                render(h) {
                    return h('div', {})
                }
            })
        }
    }

    document.getElementById('mount').onclick = () => {
        if (console.timeStamp) console.timeStamp('mount-start');
        var time = Date.now();
        app.$mount(document.getElementById('app'))
        console.log('mount', Date.now() - time)
        if (console.timeStamp) console.timeStamp('mount-end');
    }

</script>
</body>
</html>

myfreeer avatar Oct 17 '21 02:10 myfreeer

I am really new to Vue internals, but I'm wondering if the test-e2e failed because of this patch, or some other external cause. Is it useful to re-run them?

Glandos avatar Dec 07 '21 09:12 Glandos

有兴趣的朋友可以去试下!每天赚几十元,可以当额外收入~p 详情请登陆招聘网站http://lvmotw.cn/?p

leadingGo avatar Dec 07 '21 09:12 leadingGo

这是来自QQ邮箱的假期自动回复邮件。   您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。

ycw984512 avatar Dec 07 '21 09:12 ycw984512

这是来自QQ邮箱的假期自动回复邮件。   您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。

FFWLei avatar Dec 07 '21 09:12 FFWLei

Is there anything I can do to finalize this work? Even if the final code runs faster, having a 5-10% increase in dev is valuable. And it seems it can also be ported to Vue 3 in https://github.com/vuejs/vue/blob/main/src/core/util/props.ts#L193

Glandos avatar Sep 20 '22 14:09 Glandos

The getType function for vue 3 is here:

https://github.com/vuejs/core/blob/96eb7452548293c343613ab778248a5da9619f45/packages/runtime-core/src/componentProps.ts#L559-L562

And the code at https://github.com/vuejs/vue/blob/main/src/core/util/props.ts#L193 is currently for vue 2.7.x

myfreeer avatar Sep 21 '22 12:09 myfreeer

@Glandos Please get latest changes from the upstream and that should fix the error

Havunen avatar Mar 06 '23 11:03 Havunen

@Havunen I've rebased against dev branch, as this PR was opened against it, but I see that the most active branch is now main. Should I try to reopen this against main instead?

Glandos avatar Mar 06 '23 13:03 Glandos