P粉8541192632023-08-27 00:50:55
I've done some basic benchmarking and was wondering if frequently used variables should be provided/injected, or if they should be accessed from the Pinia store in a large number of components.
The results show that there is no significant performance difference.
My first test case is very basic:
Providing/injecting a single bool
is not the same as getting it from the Pinia storage in the component and rendering the component multiple times.
50k components took between 20-24 seconds to render, also using provide/inject and using Pinia. There's no consistent difference to say either one is faster/slower.
In the second test, I used a larger object, an array of about 1MiB of data (measured in a JSON print without spaces). The difference is also not significant. I've rendered 50k components and both using injection and storage access took about the same amount of time, between 19-26 seconds.
The components in each case render the boolean value of the theme variable, so their rendering time does not increase with large data vs. small boolean values.
After all, I've come to the conclusion that there really isn't any meaningful difference between provide/inject and the Pinia store. The only obvious difference is that performance is less stable with larger data and more predictable with smaller data. No matter how many times I repeat the test on the boolean values, the time is always between 20-24 seconds and as the data increases I get some outliers like 19 seconds or 26 seconds. Again nothing consistent, this could just be a fluctuation in my actual CPU usage and nothing to do with Provide/inject vs. Pinia store usage.
I tested on Chrome v110 (x86_64) on macOS using vue@3.2.47 and pinia@2.0.32.
Test code I used:
<template> <div>Inject {{ number }}: {{ injected ? 'yes' : 'no' }}</div> </template> <script setup lang="ts"> export interface Props { number?: number, } const props = withDefaults( defineProps<Props>(), { number: 0, }) import { inject } from 'vue' const injected = inject('inject-test') </script>
<template> <div>Store get {{ number }}: {{ testStore.test ? 'yes' : 'no' }}</div> </template> <script setup lang="ts"> export interface Props { number?: number, } const props = withDefaults( defineProps<Props>(), { number: 0, }) import { useTestStore } from 'stores/test' const testStore = useTestStore() </script>
<template> <div v-if="testStore"> <h1>Store get</h1> <pre>Start: {{ start() }}</pre> <div class="test"> <StoreGet v-for="n in 50000" :key="n" :number="n" /> </div> <pre>End: {{ end() }}</pre> <pre>Duration: {{ endTime - startTime }} seconds</pre> </div> <div v-else> <h1>Inject</h1> <pre>Start: {{ start() }}</pre> <div class="test"> <Inject v-for="n in 50000" :key="n" :number="n" /> </div> <pre>End: {{ end() }}</pre> <pre>Duration: {{ endTime - startTime }} seconds</pre> </div> </template> <script setup lang="ts"> import { provide } from 'vue' import Inject from './test/Inject.vue' import StoreGet from './test/StoreGet.vue' // Roughly 1M of json data import { large } from '@sbnc/datasets/largeTest' // Comment one or the other: const testData = true //const testData = large // Choose which one to test: const testStore = true // set false to test inject provide( 'inject-test', testData) import { useTestStore } from 'stores/test' const testStore = useTestStore() testStore.test = testData let startTime let endTime function start() { startTime = performance.now() return startTime } function end() { endTime = performance.now() return endTime } </script>