mirror of https://github.com/vuejs/core.git
perf(server-renderer): optimize `unrollBuffer` by avoiding promises (#11340)
This commit is contained in:
parent
d76dd9c58d
commit
05779a70bd
|
@ -0,0 +1,74 @@
|
|||
import { bench, describe } from 'vitest'
|
||||
|
||||
import { type SSRBuffer, createBuffer } from '../src/render'
|
||||
import { unrollBuffer } from '../src/renderToString'
|
||||
|
||||
function createSyncBuffer(levels: number, itemsPerLevel: number): SSRBuffer {
|
||||
const buffer = createBuffer()
|
||||
|
||||
function addItems(buf: ReturnType<typeof createBuffer>, level: number) {
|
||||
for (let i = 1; i <= levels * itemsPerLevel; i++) {
|
||||
buf.push(`sync${level}.${i}`)
|
||||
}
|
||||
if (level < levels) {
|
||||
const subBuffer = createBuffer()
|
||||
addItems(subBuffer, level + 1)
|
||||
buf.push(subBuffer.getBuffer())
|
||||
}
|
||||
}
|
||||
|
||||
addItems(buffer, 1)
|
||||
return buffer.getBuffer()
|
||||
}
|
||||
|
||||
function createMixedBuffer(levels: number, itemsPerLevel: number): SSRBuffer {
|
||||
const buffer = createBuffer()
|
||||
|
||||
function addItems(buf: ReturnType<typeof createBuffer>, level: number) {
|
||||
for (let i = 1; i <= levels * itemsPerLevel; i++) {
|
||||
if (i % 3 === 0) {
|
||||
// @ts-expect-error testing...
|
||||
buf.push(Promise.resolve(`async${level}.${i}`))
|
||||
} else {
|
||||
buf.push(`sync${level}.${i}`)
|
||||
}
|
||||
}
|
||||
if (level < levels) {
|
||||
const subBuffer = createBuffer()
|
||||
addItems(subBuffer, level + 1)
|
||||
buf.push(subBuffer.getBuffer())
|
||||
}
|
||||
}
|
||||
|
||||
addItems(buffer, 1)
|
||||
return buffer.getBuffer()
|
||||
}
|
||||
|
||||
describe('unrollBuffer', () => {
|
||||
let syncBuffer = createBuffer().getBuffer()
|
||||
let mixedBuffer = createBuffer().getBuffer()
|
||||
|
||||
bench(
|
||||
'sync',
|
||||
() => {
|
||||
return unrollBuffer(syncBuffer) as any
|
||||
},
|
||||
{
|
||||
setup() {
|
||||
syncBuffer = createSyncBuffer(5, 3)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
bench(
|
||||
'mixed',
|
||||
() => {
|
||||
return unrollBuffer(mixedBuffer) as any
|
||||
},
|
||||
{
|
||||
setup() {
|
||||
mixedBuffer = createMixedBuffer(5, 3)
|
||||
},
|
||||
},
|
||||
)
|
||||
})
|
|
@ -11,26 +11,46 @@ import { type SSRBuffer, type SSRContext, renderComponentVNode } from './render'
|
|||
|
||||
const { isVNode } = ssrUtils
|
||||
|
||||
async function unrollBuffer(buffer: SSRBuffer): Promise<string> {
|
||||
if (buffer.hasAsync) {
|
||||
let ret = ''
|
||||
for (let i = 0; i < buffer.length; i++) {
|
||||
let item = buffer[i]
|
||||
if (isPromise(item)) {
|
||||
item = await item
|
||||
}
|
||||
if (isString(item)) {
|
||||
ret += item
|
||||
} else {
|
||||
ret += await unrollBuffer(item)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
} else {
|
||||
// sync buffer can be more efficiently unrolled without unnecessary await
|
||||
// ticks
|
||||
return unrollBufferSync(buffer)
|
||||
function nestedUnrollBuffer(
|
||||
buffer: SSRBuffer,
|
||||
parentRet: string,
|
||||
startIndex: number,
|
||||
): Promise<string> | string {
|
||||
if (!buffer.hasAsync) {
|
||||
return parentRet + unrollBufferSync(buffer)
|
||||
}
|
||||
|
||||
let ret = parentRet
|
||||
for (let i = startIndex; i < buffer.length; i += 1) {
|
||||
const item = buffer[i]
|
||||
if (isString(item)) {
|
||||
ret += item
|
||||
continue
|
||||
}
|
||||
|
||||
if (isPromise(item)) {
|
||||
return item.then(nestedItem => {
|
||||
buffer[i] = nestedItem
|
||||
return nestedUnrollBuffer(buffer, ret, i)
|
||||
})
|
||||
}
|
||||
|
||||
const result = nestedUnrollBuffer(item, ret, 0)
|
||||
if (isPromise(result)) {
|
||||
return result.then(nestedItem => {
|
||||
buffer[i] = nestedItem
|
||||
return nestedUnrollBuffer(buffer, '', i)
|
||||
})
|
||||
}
|
||||
|
||||
ret = result
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
export function unrollBuffer(buffer: SSRBuffer): Promise<string> | string {
|
||||
return nestedUnrollBuffer(buffer, '', 0)
|
||||
}
|
||||
|
||||
function unrollBufferSync(buffer: SSRBuffer): string {
|
||||
|
|
Loading…
Reference in New Issue