From 57555751e49c59e62504235c355285838811d2ee Mon Sep 17 00:00:00 2001 From: Phoenix <64720302+Concur-max@users.noreply.github.com> Date: Tue, 1 Jul 2025 11:42:54 +0800 Subject: [PATCH] =?UTF-8?q?perf(dialogue):=20=E4=BC=98=E5=8C=96=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E4=BB=BB=E5=8A=A1=E6=81=A2=E5=A4=8D=E7=9A=84=E6=80=A7?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 引入二分查找算法和批处理机制来优化上传任务的插入顺序。对于少量任务使用直接插入,大量任务使用排序后分批处理,并通过 requestAnimationFrame 提高浏览器渲染性能。添加快速路径处理空数组和边界情况。 --- src/store/modules/dialogue.js | 128 +++++++++++++++++++++++++++++++--- 1 file changed, 120 insertions(+), 8 deletions(-) diff --git a/src/store/modules/dialogue.js b/src/store/modules/dialogue.js index 9f2daab..6a5ab14 100644 --- a/src/store/modules/dialogue.js +++ b/src/store/modules/dialogue.js @@ -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) } } }