首页  >  问答  >  正文

Vue 3 提供/注入的性能如何?

<p>我从事的项目依赖于应用程序级 <code>provide</code> 进行全局状态管理。起初,<code>provide</code>d 对象很小,但它随着项目的发展而不断增长。</p> <p>在需要数据的地方注入该对象会对应用性能造成多大影响?如果没有实现像 Pinia 这样的全局状态管理工具,是否值得将我们提供的大型对象分解为单独的对象以在需要的地方提供数据“块”?</p>
P粉946336138P粉946336138419 天前525

全部回复(1)我来回复

  • P粉854119263

    P粉8541192632023-08-27 00:50:55

    我已经做了一些基本的基准测试,想知道是否应该提供/注入经常使用的变量,或者是否应该从大量组件中的 Pinia 商店访问它们。

    结果表明,没有显着的性能差异。

    我的第一个测试用例非常基本: 提供/注入单个 bool 与从组件中的 Pinia 存储获取它并多次渲染组件不同。 50k 组件渲染花费的时间在 20-24 秒之间,使用提供/注入和使用 Pinia 时也是如此。没有一致的差异可以说两者中的任何一个更快/更慢。

    在第二个测试中,我使用了一个更大的对象,一个大约 1MiB 数据的数组(以无空格 JSON 打印测量)。差异同样不显着。我已经渲染了 50k 组件,并且使用注入和存储访问都花费了大约相同的时间,在 19-26 秒之间。

    每种情况下的组件都会渲染主题变量的布尔值,因此它们的渲染时间不会因大数据与小布尔值而增加。

    毕竟,我得出的结论是,provide/inject 与 Pinia 商店之间确实没有任何有意义的区别。唯一明显的区别是,数据较大时,性能不太稳定,数据较小时,性能更可预测。无论我对布尔值重复测试多少次,时间总是在 20-24 秒之间,随着数据的增加,我得到了一些异常值,例如 19 秒或 26 秒。再次没有一致的情况,这可能只是我实际 CPU 使用率的波动,与 Provide/inject 与 Pinia store 的使用情况无关。

    我使用 vue@3.2.47 和 pinia@2.0.32 在 macOS 上的 Chrome v110 (x86_64) 上进行了测试。

    我使用的测试代码:

    <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>
    

    回复
    0
  • 取消回复