Skip to content

Commit a559152

Browse files
author
Taois
committed
feat: 文件头工具调优
1 parent 8c36ba5 commit a559152

File tree

2 files changed

+15
-63
lines changed

2 files changed

+15
-63
lines changed

scripts/test/test_cctv_header.js

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -105,22 +105,8 @@ async function runTest() {
105105
console.log(`平均每次读取耗时: ${avgTime.toFixed(4)} ms`);
106106
console.log('✅ 性能测试完成。');
107107

108-
// 8. 优化后的 readHeader 性能测试
109-
console.log(`\n[8/10] 优化后的 readHeader (Partial Read) 性能测试 (读取 ${iterations} 次取平均)...`);
110-
111-
const perfStartOptimized = performance.now();
112-
for(let i=0; i<iterations; i++) {
113-
await FileHeaderManager.readHeader(testFile);
114-
}
115-
const perfEndOptimized = performance.now();
116-
const totalTimeOptimized = perfEndOptimized - perfStartOptimized;
117-
const avgTimeOptimized = totalTimeOptimized / iterations;
118-
119-
console.log(`总耗时 (Optimized): ${totalTimeOptimized.toFixed(2)} ms`);
120-
console.log(`平均每次读取耗时 (Optimized): ${avgTimeOptimized.toFixed(4)} ms`);
121-
122-
const finalImprovement = ((avgTime - avgTimeOptimized) / avgTime * 100).toFixed(2);
123-
console.log(`🚀 最终性能提升: ${finalImprovement}%`);
108+
// 8. (已移除优化对比,直接全量读取更快)
109+
console.log('\n[8/10] 跳过 Partial Read 性能测试 (全量读取更快)...');
124110

125111
// 9. 写文件头性能测试
126112
console.log(`\n[9/10] 写文件头性能测试 (循环 ${iterations} 次)...`);

utils/fileHeaderManager.js

Lines changed: 13 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -136,39 +136,17 @@ class FileHeaderManager {
136136
/**
137137
* 读取文件头信息
138138
* @param {string} filePath 文件路径
139-
* @param {Object} [options] 配置选项
140-
* @param {number} [options.maxHeaderSize=8192] 最大读取字节数 (默认 8KB)
141139
* @returns {Object|null} 头信息对象
142140
*/
143-
static async readHeader(filePath, options = {}) {
144-
const { maxHeaderSize = 8192 } = options;
141+
static async readHeader(filePath) {
142+
// 对于大多数脚本文件(通常 < 1MB),直接全量读取比 open+read+close 更快
143+
const content = await fs.readFile(filePath, 'utf8');
145144
const ext = path.extname(filePath);
146145
const config = this.COMMENT_CONFIG[ext];
147146

148147
if (!config) throw new Error(`Unsupported file type: ${ext}`);
149148

150-
let content = '';
151-
let handle;
152-
153-
try {
154-
// 使用 fs.open 和 read 读取部分内容,提高性能
155-
handle = await fs.open(filePath, 'r');
156-
const buffer = Buffer.alloc(maxHeaderSize);
157-
const { bytesRead } = await handle.read(buffer, 0, maxHeaderSize, 0);
158-
content = buffer.toString('utf8', 0, bytesRead);
159-
} catch (error) {
160-
// 如果读取失败 (如文件不存在),抛出错误或返回 null
161-
if (handle) await handle.close();
162-
throw error;
163-
} finally {
164-
if (handle) await handle.close();
165-
}
166-
167149
const match = content.match(config.regex);
168-
169-
// 如果在头部没有找到匹配项,且文件可能很大,也许是注释太长被截断了?
170-
// 但目前假设 header 应该在 8KB 内。如果需要完整性,可以考虑 fallback 到读取整个文件,
171-
// 但为了性能,这里仅依赖前 8KB。
172150
if (!match) return null;
173151

174152
const headerBlock = this.findHeaderBlock(match[0], ext);
@@ -237,15 +215,18 @@ class FileHeaderManager {
237215
throw new Error(`Failed to read file: ${error.message}`);
238216
}
239217

240-
// 备份原始内容
241-
const originalContent = content;
242218
const ext = path.extname(filePath);
243219
const config = this.COMMENT_CONFIG[ext];
244220

245221
if (!config) throw new Error(`Unsupported file type: ${ext}`);
246222

247223
const headerStr = `@header(${JSON5.stringify(headerObj, null, 2)})`;
248224

225+
// 优化:先尝试只读取头部来匹配正则,避免全量匹配
226+
// 但由于 writeHeader 需要重写整个文件,全量内容是必须的
227+
// 所以这里的优化点主要在于减少不必要的全量正则匹配
228+
229+
// 使用优化后的 regex 只匹配头部注释
249230
const match = content.match(config.regex);
250231
let newContent;
251232

@@ -348,26 +329,11 @@ class FileHeaderManager {
348329
throw new Error('Generated content is empty, operation aborted');
349330
}
350331

351-
// 简单的内容完整性检查:确保新内容包含原始内容的大部分非注释代码
352-
const originalCodeLines = originalContent.split('\n').filter(line => {
353-
const trimmed = line.trim();
354-
return trimmed && !trimmed.startsWith('//') && !trimmed.startsWith('/*') &&
355-
!trimmed.startsWith('*') && !trimmed.startsWith('*/') &&
356-
!trimmed.startsWith('#') && !trimmed.startsWith('"""') && !trimmed.startsWith("'''") &&
357-
!trimmed.startsWith('<?php');
358-
});
359-
360-
const newCodeLines = newContent.split('\n').filter(line => {
361-
const trimmed = line.trim();
362-
return trimmed && !trimmed.startsWith('//') && !trimmed.startsWith('/*') &&
363-
!trimmed.startsWith('*') && !trimmed.startsWith('*/') &&
364-
!trimmed.startsWith('#') && !trimmed.startsWith('"""') && !trimmed.startsWith("'''") &&
365-
!trimmed.startsWith('<?php') && !trimmed.includes('@header(');
366-
});
367-
368-
// 如果新内容的代码行数比原始内容少了很多,可能出现了问题
369-
if (originalCodeLines.length > 5 && newCodeLines.length < originalCodeLines.length * 0.8) {
370-
throw new Error('Content integrity check failed: significant code loss detected, operation aborted');
332+
// 简单的内容完整性检查:确保新内容大小与原始内容大小差异在合理范围内
333+
// 移除复杂的行级比对以提升性能
334+
const diffRatio = Math.abs(newContent.length - content.length) / content.length;
335+
if (content.length > 100 && diffRatio > 0.5 && newContent.length < content.length) {
336+
throw new Error('Content integrity check failed: significant size reduction detected, operation aborted');
371337
}
372338

373339
// 创建备份(如果启用)

0 commit comments

Comments
 (0)