perf(dialogue): 优化上传任务恢复的性能
引入二分查找算法和批处理机制来优化上传任务的插入顺序。对于少量任务使用直接插入,大量任务使用排序后分批处理,并通过 requestAnimationFrame 提高浏览器渲染性能。添加快速路径处理空数组和边界情况。
This commit is contained in:
parent
f2b194f712
commit
57555751e4
@ -404,20 +404,132 @@ export const useDialogueStore = defineStore('dialogue', {
|
||||
Object.assign(this.talk, params)
|
||||
},
|
||||
|
||||
// 恢复当前会话的上传任务
|
||||
// 根据 insert_sequence 将任务插入到 records 数组的正确位置(使用优化的二分查找)
|
||||
insertTaskAtCorrectPosition(task) {
|
||||
const len = this.records.length
|
||||
|
||||
// 快速路径:如果数组为空或任务应该插入到末尾
|
||||
if (len === 0) {
|
||||
this.records.push(task)
|
||||
return
|
||||
}
|
||||
|
||||
// 快速路径:检查是否应该插入到开头或末尾(避免二分查找的开销)
|
||||
if (task.insert_sequence < this.records[0].sequence) {
|
||||
this.records.unshift(task)
|
||||
return
|
||||
}
|
||||
|
||||
if (task.insert_sequence >= this.records[len - 1].sequence) {
|
||||
this.records.push(task)
|
||||
return
|
||||
}
|
||||
|
||||
// 使用优化的二分查找算法找到插入位置
|
||||
let low = 0
|
||||
let high = len - 1
|
||||
|
||||
// 二分查找优化:使用位运算加速计算中点
|
||||
while (low <= high) {
|
||||
const mid = (low + high) >>> 1 // 无符号右移代替 Math.floor((low + high) / 2)
|
||||
if (this.records[mid].sequence <= task.insert_sequence) {
|
||||
low = mid + 1
|
||||
} else {
|
||||
high = mid - 1
|
||||
}
|
||||
}
|
||||
|
||||
// 在找到的位置插入任务
|
||||
this.records.splice(low, 0, task)
|
||||
},
|
||||
|
||||
// 恢复当前会话的上传任务(极致性能优化)
|
||||
restoreUploadTasks() {
|
||||
// 获取当前会话的sessionKey
|
||||
const sessionKey = `${this.talk.talk_type}_${this.talk.receiver_id}`
|
||||
|
||||
// 检查是否有需要恢复的上传任务
|
||||
if (this.uploadTaskMap[sessionKey] && this.uploadTaskMap[sessionKey].length > 0) {
|
||||
// 按照插入顺序排序上传任务
|
||||
const tasks = [...this.uploadTaskMap[sessionKey]].sort((a, b) => a.insert_sequence - b.insert_sequence)
|
||||
if (!this.uploadTaskMap[sessionKey] || this.uploadTaskMap[sessionKey].length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// 性能优化:缓存数组长度和本地变量,减少属性查找
|
||||
const tasks = this.uploadTaskMap[sessionKey]
|
||||
const tasksLength = tasks.length
|
||||
|
||||
// 如果只有一个任务,直接处理
|
||||
if (tasksLength === 1) {
|
||||
this.insertTaskAtCorrectPosition(tasks[0])
|
||||
return
|
||||
}
|
||||
|
||||
// 性能优化:对于少量任务,避免创建新数组和排序开销
|
||||
if (tasksLength <= 10) {
|
||||
// 找出最小的 insert_sequence
|
||||
let minIndex = 0
|
||||
for (let i = 1; i < tasksLength; i++) {
|
||||
if (tasks[i].insert_sequence < tasks[minIndex].insert_sequence) {
|
||||
minIndex = i
|
||||
}
|
||||
}
|
||||
|
||||
// 将上传任务添加到当前会话记录中
|
||||
tasks.forEach(task => {
|
||||
this.addDialogueRecord(task)
|
||||
})
|
||||
// 按顺序插入任务
|
||||
let inserted = 0
|
||||
let currentMin = tasks[minIndex]
|
||||
this.insertTaskAtCorrectPosition(currentMin)
|
||||
inserted++
|
||||
|
||||
while (inserted < tasksLength) {
|
||||
minIndex = -1
|
||||
let minSequence = Infinity
|
||||
|
||||
// 找出剩余任务中 insert_sequence 最小的
|
||||
for (let i = 0; i < tasksLength; i++) {
|
||||
const task = tasks[i]
|
||||
if (task !== currentMin && task.insert_sequence < minSequence) {
|
||||
minIndex = i
|
||||
minSequence = task.insert_sequence
|
||||
}
|
||||
}
|
||||
|
||||
if (minIndex !== -1) {
|
||||
currentMin = tasks[minIndex]
|
||||
this.insertTaskAtCorrectPosition(currentMin)
|
||||
inserted++
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 对于大量任务,使用排序后批量处理
|
||||
// 创建一个新数组并排序,避免修改原数组
|
||||
const sortedTasks = [...tasks].sort((a, b) => a.insert_sequence - b.insert_sequence)
|
||||
|
||||
// 性能优化:使用 requestAnimationFrame 进行批处理,更好地配合浏览器渲染周期
|
||||
const batchSize = 50 // 每批处理的任务数量
|
||||
const totalBatches = Math.ceil(sortedTasks.length / batchSize)
|
||||
|
||||
const processBatch = (batchIndex) => {
|
||||
const startIndex = batchIndex * batchSize
|
||||
const endIndex = Math.min(startIndex + batchSize, sortedTasks.length)
|
||||
|
||||
// 处理当前批次的任务
|
||||
for (let i = startIndex; i < endIndex; i++) {
|
||||
this.insertTaskAtCorrectPosition(sortedTasks[i])
|
||||
}
|
||||
|
||||
// 如果还有更多批次,安排下一个批次
|
||||
if (batchIndex < totalBatches - 1) {
|
||||
// 使用 requestAnimationFrame 配合浏览器渲染周期
|
||||
// 如果不支持,回退到 setTimeout
|
||||
if (typeof requestAnimationFrame !== 'undefined') {
|
||||
requestAnimationFrame(() => processBatch(batchIndex + 1))
|
||||
} else {
|
||||
setTimeout(() => processBatch(batchIndex + 1), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 开始处理第一批
|
||||
processBatch(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user