现代Web存储技术(六):企业级性能优化与监控体系

举报
Yeats_Liao 发表于 2025/11/14 08:55:06 2025/11/14
【摘要】 深入探讨Web存储的性能优化技巧,提供实用的最佳实践和常见问题解决方案,帮助开发者构建高性能的Web应用。用户在地铁里刷新闻,每次加载都要等3秒;在线文档编辑器,每次保存都卡顿1秒;音乐播放器切换歌曲时出现明显延迟;游戏存档读取时间过长,影响游戏体验。这些问题的根源往往在于存储性能。一个高性能的存储系统不仅能提升用户体验,还能减少服务器压力,降低运营成本。 1. 性能基准测试与监控 1.1 ...

深入探讨Web存储的性能优化技巧,提供实用的最佳实践和常见问题解决方案,帮助开发者构建高性能的Web应用。

用户在地铁里刷新闻,每次加载都要等3秒;在线文档编辑器,每次保存都卡顿1秒;音乐播放器切换歌曲时出现明显延迟;游戏存档读取时间过长,影响游戏体验。

这些问题的根源往往在于存储性能。一个高性能的存储系统不仅能提升用户体验,还能减少服务器压力,降低运营成本。

1. 性能基准测试与监控

1.1 建立性能基准

在优化之前,我们需要知道当前的性能水平:

class StoragePerformanceBenchmark {
  constructor() {
    this.results = {};
    this.testData = this.generateTestData();
  }
  
  // 生成测试数据
  generateTestData() {
    const sizes = {
      small: this.createTestObject(1024), // 1KB
      medium: this.createTestObject(100 * 1024), // 100KB
      large: this.createTestObject(1024 * 1024), // 1MB
      huge: this.createTestObject(10 * 1024 * 1024) // 10MB
    };
    
    return sizes;
  }
  
  createTestObject(targetSize) {
    const baseObj = {
      id: Math.random().toString(36),
      timestamp: Date.now(),
      type: 'test-data'
    };
    
    // 填充到目标大小
    const currentSize = JSON.stringify(baseObj).length;
    const remainingSize = targetSize - currentSize;
    
    if (remainingSize > 0) {
      baseObj.padding = 'x'.repeat(remainingSize);
    }
    
    return baseObj;
  }
  
  // 运行完整基准测试
  async runFullBenchmark() {
    console.log('开始存储性能基准测试...');
    
    // 测试各种存储方案
    await this.benchmarkLocalStorage();
    await this.benchmarkSessionStorage();
    await this.benchmarkIndexedDB();
    await this.benchmarkCacheAPI();
    await this.benchmarkOPFS();
    
    // 生成报告
    this.generateReport();
    
    return this.results;
  }
  
  // LocalStorage基准测试
  async benchmarkLocalStorage() {
    console.log('测试LocalStorage性能...');
    
    const results = {
      write: {},
      read: {},
      errors: []
    };
    
    for (const [size, data] of Object.entries(this.testData)) {
      try {
        // 写入测试
        const writeStart = performance.now();
        localStorage.setItem(`test-${size}`, JSON.stringify(data));
        const writeEnd = performance.now();
        results.write[size] = writeEnd - writeStart;
        
        // 读取测试
        const readStart = performance.now();
        const retrieved = JSON.parse(localStorage.getItem(`test-${size}`));
        const readEnd = performance.now();
        results.read[size] = readEnd - readStart;
        
        // 清理
        localStorage.removeItem(`test-${size}`);
        
      } catch (error) {
        results.errors.push({ size, error: error.message });
      }
    }
    
    this.results.localStorage = results;
  }
  
  // IndexedDB基准测试
  async benchmarkIndexedDB() {
    console.log('测试IndexedDB性能...');
    
    const results = {
      write: {},
      read: {},
      batchWrite: {},
      query: {},
      errors: []
    };
    
    try {
      const db = await this.openTestDB();
      
      for (const [size, data] of Object.entries(this.testData)) {
        try {
          // 单条写入测试
          const writeStart = performance.now();
          await this.writeToIndexedDB(db, `test-${size}`, data);
          const writeEnd = performance.now();
          results.write[size] = writeEnd - writeStart;
          
          // 读取测试
          const readStart = performance.now();
          const retrieved = await this.readFromIndexedDB(db, `test-${size}`);
          const readEnd = performance.now();
          results.read[size] = readEnd - readStart;
          
          // 批量写入测试(100条记录)
          const batchData = Array(100).fill(data).map((item, index) => ({
            ...item,
            id: `batch-${size}-${index}`
          }));
          
          const batchStart = performance.now();
          await this.batchWriteToIndexedDB(db, batchData);
          const batchEnd = performance.now();
          results.batchWrite[size] = batchEnd - batchStart;
          
          // 查询测试
          const queryStart = performance.now();
          const queryResults = await this.queryIndexedDB(db, 'type', 'test-data');
          const queryEnd = performance.now();
          results.query[size] = queryEnd - queryStart;
          
        } catch (error) {
          results.errors.push({ size, error: error.message });
        }
      }
      
      db.close();
    } catch (error) {
      results.errors.push({ operation: 'db-open', error: error.message });
    }
    
    this.results.indexedDB = results;
  }
  
  // Cache API基准测试
  async benchmarkCacheAPI() {
    console.log('测试Cache API性能...');
    
    const results = {
      write: {},
      read: {},
      errors: []
    };
    
    try {
      const cache = await caches.open('performance-test');
      
      for (const [size, data] of Object.entries(this.testData)) {
        try {
          const url = `/test-${size}`;
          const response = new Response(JSON.stringify(data));
          
          // 写入测试
          const writeStart = performance.now();
          await cache.put(url, response.clone());
          const writeEnd = performance.now();
          results.write[size] = writeEnd - writeStart;
          
          // 读取测试
          const readStart = performance.now();
          const cachedResponse = await cache.match(url);
          const retrieved = await cachedResponse.json();
          const readEnd = performance.now();
          results.read[size] = readEnd - readStart;
          
        } catch (error) {
          results.errors.push({ size, error: error.message });
        }
      }
      
      // 清理
      await caches.delete('performance-test');
      
    } catch (error) {
      results.errors.push({ operation: 'cache-open', error: error.message });
    }
    
    this.results.cacheAPI = results;
  }
  
  // OPFS基准测试
  async benchmarkOPFS() {
    console.log('测试OPFS性能...');
    
    const results = {
      write: {},
      read: {},
      stream: {},
      errors: []
    };
    
    if (!('storage' in navigator) || !('getDirectory' in navigator.storage)) {
      results.errors.push({ error: 'OPFS not supported' });
      this.results.opfs = results;
      return;
    }
    
    try {
      const opfsRoot = await navigator.storage.getDirectory();
      
      for (const [size, data] of Object.entries(this.testData)) {
        try {
          const filename = `test-${size}.json`;
          const jsonData = JSON.stringify(data);
          
          // 写入测试
          const writeStart = performance.now();
          const fileHandle = await opfsRoot.getFileHandle(filename, { create: true });
          const writable = await fileHandle.createWritable();
          await writable.write(jsonData);
          await writable.close();
          const writeEnd = performance.now();
          results.write[size] = writeEnd - writeStart;
          
          // 读取测试
          const readStart = performance.now();
          const file = await fileHandle.getFile();
          const content = await file.text();
          const retrieved = JSON.parse(content);
          const readEnd = performance.now();
          results.read[size] = readEnd - readStart;
          
          // 流式写入测试(大文件)
          if (size === 'huge') {
            const streamStart = performance.now();
            const streamWritable = await fileHandle.createWritable();
            
            // 分块写入
            const chunkSize = 64 * 1024; // 64KB chunks
            for (let i = 0; i < jsonData.length; i += chunkSize) {
              const chunk = jsonData.slice(i, i + chunkSize);
              await streamWritable.write(chunk);
            }
            
            await streamWritable.close();
            const streamEnd = performance.now();
            results.stream[size] = streamEnd - streamStart;
          }
          
          // 清理
          await opfsRoot.removeEntry(filename);
          
        } catch (error) {
          results.errors.push({ size, error: error.message });
        }
      }
      
    } catch (error) {
      results.errors.push({ operation: 'opfs-init', error: error.message });
    }
    
    this.results.opfs = results;
  }
  
  // 生成性能报告
  generateReport() {
    console.log('\n存储性能基准测试报告');
    console.log('=' .repeat(50));
    
    const storageTypes = Object.keys(this.results);
    const dataSizes = ['small', 'medium', 'large', 'huge'];
    
    // 写入性能对比
    console.log('\n写入性能 (毫秒)');
    console.log('-'.repeat(30));
    
    const writeTable = {};
    storageTypes.forEach(type => {
      writeTable[type] = {};
      dataSizes.forEach(size => {
        const result = this.results[type];
        if (result && result.write && result.write[size] !== undefined) {
          writeTable[type][size] = result.write[size].toFixed(2);
        } else {
          writeTable[type][size] = 'N/A';
        }
      });
    });
    
    console.table(writeTable);
    
    // 读取性能对比
    console.log('\n读取性能 (毫秒)');
    console.log('-'.repeat(30));
    
    const readTable = {};
    storageTypes.forEach(type => {
      readTable[type] = {};
      dataSizes.forEach(size => {
        const result = this.results[type];
        if (result && result.read && result.read[size] !== undefined) {
          readTable[type][size] = result.read[size].toFixed(2);
        } else {
          readTable[type][size] = 'N/A';
        }
      });
    });
    
    console.table(readTable);
    
    // 性能建议
    this.generateRecommendations();
  }
  
  // 生成性能建议
  generateRecommendations() {
    console.log('\n性能优化建议');
    console.log('-'.repeat(30));
    
    const recommendations = [];
    
    // 分析写入性能
    const writePerf = this.analyzeWritePerformance();
    if (writePerf.slowest) {
      recommendations.push(`${writePerf.slowest} 写入性能较慢,考虑使用批量操作`);
    }
    
    // 分析读取性能
    const readPerf = this.analyzeReadPerformance();
    if (readPerf.fastest) {
      recommendations.push(`${readPerf.fastest} 读取性能最佳,适合频繁访问的数据`);
    }
    
    // 分析大文件处理
    const largeFilePerf = this.analyzeLargeFilePerformance();
    if (largeFilePerf.recommendation) {
      recommendations.push(largeFilePerf.recommendation);
    }
    
    recommendations.forEach(rec => console.log(rec));
  }
  
  // 分析写入性能
  analyzeWritePerformance() {
    const writePerfs = {};
    
    Object.keys(this.results).forEach(type => {
      const result = this.results[type];
      if (result.write && result.write.medium) {
        writePerfs[type] = result.write.medium;
      }
    });
    
    const slowest = Object.keys(writePerfs).reduce((a, b) => 
      writePerfs[a] > writePerfs[b] ? a : b
    );
    
    return { slowest, perfs: writePerfs };
  }
  
  // 分析读取性能
  analyzeReadPerformance() {
    const readPerfs = {};
    
    Object.keys(this.results).forEach(type => {
      const result = this.results[type];
      if (result.read && result.read.medium) {
        readPerfs[type] = result.read.medium;
      }
    });
    
    const fastest = Object.keys(readPerfs).reduce((a, b) => 
      readPerfs[a] < readPerfs[b] ? a : b
    );
    
    return { fastest, perfs: readPerfs };
  }
  
  // 分析大文件性能
  analyzeLargeFilePerformance() {
    const opfsResult = this.results.opfs;
    
    if (opfsResult && opfsResult.write && opfsResult.write.huge > 1000) {
      return {
        recommendation: '大文件建议使用OPFS流式写入,可以提升性能'
      };
    }
    
    return {};
  }
  
  // 辅助方法
  async openTestDB() {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open('performance-test', 1);
      
      request.onerror = () => reject(request.error);
      request.onsuccess = () => resolve(request.result);
      
      request.onupgradeneeded = (event) => {
        const db = event.target.result;
        
        if (!db.objectStoreNames.contains('test')) {
          const store = db.createObjectStore('test', { keyPath: 'id' });
          store.createIndex('type', 'type', { unique: false });
        }
      };
    });
  }
  
  async writeToIndexedDB(db, key, data) {
    const transaction = db.transaction(['test'], 'readwrite');
    const store = transaction.objectStore('test');
    
    return new Promise((resolve, reject) => {
      const request = store.put({ id: key, ...data });
      request.onsuccess = () => resolve();
      request.onerror = () => reject(request.error);
    });
  }
  
  async readFromIndexedDB(db, key) {
    const transaction = db.transaction(['test'], 'readonly');
    const store = transaction.objectStore('test');
    
    return new Promise((resolve, reject) => {
      const request = store.get(key);
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }
  
  async batchWriteToIndexedDB(db, dataArray) {
    const transaction = db.transaction(['test'], 'readwrite');
    const store = transaction.objectStore('test');
    
    const promises = dataArray.map(data => {
      return new Promise((resolve, reject) => {
        const request = store.put(data);
        request.onsuccess = () => resolve();
        request.onerror = () => reject(request.error);
      });
    });
    
    return Promise.all(promises);
  }
  
  async queryIndexedDB(db, indexName, value) {
    const transaction = db.transaction(['test'], 'readonly');
    const store = transaction.objectStore('test');
    const index = store.index(indexName);
    
    return new Promise((resolve, reject) => {
      const request = index.getAll(value);
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }
}

// 使用示例
const benchmark = new StoragePerformanceBenchmark();

// 运行基准测试
benchmark.runFullBenchmark().then(results => {
  console.log('基准测试完成,结果已保存');
  
  // 可以将结果保存到本地
  localStorage.setItem('storage-benchmark', JSON.stringify(results));
});

1.2 实时性能监控

class StoragePerformanceMonitor {
  constructor() {
    this.metrics = {
      operations: [],
      errors: [],
      slowQueries: []
    };
    
    this.thresholds = {
      slowOperation: 100, // 100ms
      errorRate: 0.05, // 5%
      memoryUsage: 0.8 // 80%
    };
    
    this.init();
  }
  
  init() {
    // 监控存储操作
    this.wrapStorageAPIs();
    
    // 定期生成报告
    setInterval(() => {
      this.generatePerformanceReport();
    }, 60000); // 每分钟
    
    // 监控内存使用
    this.monitorMemoryUsage();
  }
  
  // 包装存储API以监控性能
  wrapStorageAPIs() {
    // 包装IndexedDB
    this.wrapIndexedDB();
    
    // 包装Cache API
    this.wrapCacheAPI();
    
    // 包装LocalStorage
    this.wrapLocalStorage();
  }
  
  // 包装IndexedDB操作
  wrapIndexedDB() {
    const originalOpen = indexedDB.open;
    const monitor = this;
    
    indexedDB.open = function(...args) {
      const startTime = performance.now();
      const request = originalOpen.apply(this, args);
      
      request.onsuccess = function(event) {
        const endTime = performance.now();
        monitor.recordOperation('indexeddb', 'open', endTime - startTime, true);
        
        // 包装数据库操作
        const db = event.target.result;
        monitor.wrapDatabaseOperations(db);
      };
      
      request.onerror = function(event) {
        const endTime = performance.now();
        monitor.recordOperation('indexeddb', 'open', endTime - startTime, false, event.target.error);
      };
      
      return request;
    };
  }
  
  // 包装数据库操作
  wrapDatabaseOperations(db) {
    const monitor = this;
    const originalTransaction = db.transaction;
    
    db.transaction = function(...args) {
      const transaction = originalTransaction.apply(this, args);
      const startTime = performance.now();
      
      transaction.oncomplete = function() {
        const endTime = performance.now();
        monitor.recordOperation('indexeddb', 'transaction', endTime - startTime, true);
      };
      
      transaction.onerror = function(event) {
        const endTime = performance.now();
        monitor.recordOperation('indexeddb', 'transaction', endTime - startTime, false, event.target.error);
      };
      
      return transaction;
    };
  }
  
  // 记录操作指标
  recordOperation(storageType, operation, duration, success, error = null) {
    const record = {
      timestamp: Date.now(),
      storageType,
      operation,
      duration,
      success,
      error: error ? error.message : null
    };
    
    this.metrics.operations.push(record);
    
    // 检查是否为慢操作
    if (duration > this.thresholds.slowOperation) {
      this.metrics.slowQueries.push(record);
      console.warn(`慢操作检测: ${storageType}.${operation} 耗时 ${duration.toFixed(2)}ms`);
    }
    
    // 记录错误
    if (!success) {
      this.metrics.errors.push(record);
      console.error(`存储操作失败: ${storageType}.${operation}`, error);
    }
    
    // 限制记录数量
    this.limitMetricsSize();
  }
  
  // 限制指标记录数量
  limitMetricsSize() {
    const maxRecords = 1000;
    
    if (this.metrics.operations.length > maxRecords) {
      this.metrics.operations = this.metrics.operations.slice(-maxRecords);
    }
    
    if (this.metrics.slowQueries.length > 100) {
      this.metrics.slowQueries = this.metrics.slowQueries.slice(-100);
    }
    
    if (this.metrics.errors.length > 100) {
      this.metrics.errors = this.metrics.errors.slice(-100);
    }
  }
  
  // 生成性能报告
  generatePerformanceReport() {
    const now = Date.now();
    const oneMinuteAgo = now - 60000;
    
    // 过滤最近一分钟的数据
    const recentOps = this.metrics.operations.filter(op => op.timestamp > oneMinuteAgo);
    const recentErrors = this.metrics.errors.filter(err => err.timestamp > oneMinuteAgo);
    const recentSlowOps = this.metrics.slowQueries.filter(op => op.timestamp > oneMinuteAgo);
    
    if (recentOps.length === 0) return;
    
    // 计算统计数据
    const stats = this.calculateStats(recentOps);
    const errorRate = recentErrors.length / recentOps.length;
    
    console.log('\n存储性能报告 (最近1分钟)');
    console.log('-'.repeat(40));
    console.log(`总操作数: ${recentOps.length}`);
    console.log(`平均响应时间: ${stats.avgDuration.toFixed(2)}ms`);
    console.log(`最大响应时间: ${stats.maxDuration.toFixed(2)}ms`);
    console.log(`错误率: ${(errorRate * 100).toFixed(2)}%`);
    console.log(`慢操作数: ${recentSlowOps.length}`);
    
    // 按存储类型分组统计
    const byType = this.groupByStorageType(recentOps);
    console.log('\n按存储类型统计:');
    Object.keys(byType).forEach(type => {
      const typeStats = this.calculateStats(byType[type]);
      console.log(`  ${type}: ${byType[type].length}次操作, 平均${typeStats.avgDuration.toFixed(2)}ms`);
    });
    
    // 性能警告
    this.checkPerformanceAlerts(stats, errorRate, recentSlowOps.length);
  }
  
  // 计算统计数据
  calculateStats(operations) {
    if (operations.length === 0) {
      return { avgDuration: 0, maxDuration: 0, minDuration: 0 };
    }
    
    const durations = operations.map(op => op.duration);
    
    return {
      avgDuration: durations.reduce((sum, d) => sum + d, 0) / durations.length,
      maxDuration: Math.max(...durations),
      minDuration: Math.min(...durations)
    };
  }
  
  // 按存储类型分组
  groupByStorageType(operations) {
    return operations.reduce((groups, op) => {
      if (!groups[op.storageType]) {
        groups[op.storageType] = [];
      }
      groups[op.storageType].push(op);
      return groups;
    }, {});
  }
  
  // 检查性能警告
  checkPerformanceAlerts(stats, errorRate, slowOpCount) {
    if (stats.avgDuration > this.thresholds.slowOperation) {
      console.warn('警告: 平均响应时间过高');
    }
    
    if (errorRate > this.thresholds.errorRate) {
      console.warn('警告: 错误率过高');
    }
    
    if (slowOpCount > 10) {
      console.warn('警告: 慢操作过多');
    }
  }
  
  // 监控内存使用
  async monitorMemoryUsage() {
    if ('memory' in performance) {
      setInterval(() => {
        const memInfo = performance.memory;
        const usageRatio = memInfo.usedJSHeapSize / memInfo.jsHeapSizeLimit;
        
        if (usageRatio > this.thresholds.memoryUsage) {
          console.warn(`内存使用率过高: ${(usageRatio * 100).toFixed(2)}%`);
        }
      }, 30000); // 每30秒检查一次
    }
  }
}

// 使用示例
const monitor = new StoragePerformanceMonitor();

// 监听性能警告
window.addEventListener('storage-performance-warning', (event) => {
  console.warn('存储性能警告:', event.detail);
});

2. 批量操作优化

2.1 IndexedDB批量操作

单条操作vs批量操作的性能差异巨大:

class BatchOperationManager {
  constructor() {
    this.batchSize = 100;
    this.pendingOperations = [];
    this.batchTimer = null;
    this.batchDelay = 50; // 50ms延迟批处理
  }
  
  // 批量写入优化
  async batchWrite(storeName, dataArray, options = {}) {
    const { 
      batchSize = this.batchSize,
      onProgress = null,
      onError = null 
    } = options;
    
    const db = await this.openDB();
    const results = [];
    const errors = [];
    
    // 分批处理
    for (let i = 0; i < dataArray.length; i += batchSize) {
      const batch = dataArray.slice(i, i + batchSize);
      
      try {
        const batchResult = await this.processBatch(db, storeName, batch);
        results.push(...batchResult);
        
        // 进度回调
        if (onProgress) {
          onProgress({
            processed: Math.min(i + batchSize, dataArray.length),
            total: dataArray.length,
            percentage: Math.min((i + batchSize) / dataArray.length * 100, 100)
          });
        }
        
      } catch (error) {
        errors.push({ batch: i / batchSize, error });
        if (onError) {
          onError(error, batch);
        }
      }
    }
    
    db.close();
    
    return {
      success: results.length,
      errors: errors.length,
      results,
      errorDetails: errors
    };
  }
  
  // 处理单个批次
  async processBatch(db, storeName, batch) {
    return new Promise((resolve, reject) => {
      const transaction = db.transaction([storeName], 'readwrite');
      const store = transaction.objectStore('test');
      const results = [];
      
      transaction.oncomplete = () => resolve(results);
      transaction.onerror = () => reject(transaction.error);
      
      // 批量添加数据
      batch.forEach((item, index) => {
        const request = store.put(item);
        
        request.onsuccess = () => {
          results.push({ index, success: true, key: request.result });
        };
        
        request.onerror = () => {
          results.push({ index, success: false, error: request.error });
        };
      });
    });
  }
  
  // 智能批处理队列
  queueOperation(operation) {
    this.pendingOperations.push(operation);
    
    // 清除之前的定时器
    if (this.batchTimer) {
      clearTimeout(this.batchTimer);
    }
    
    // 设置新的批处理定时器
    this.batchTimer = setTimeout(() => {
      this.processPendingOperations();
    }, this.batchDelay);
    
    // 如果队列满了,立即处理
    if (this.pendingOperations.length >= this.batchSize) {
      clearTimeout(this.batchTimer);
      this.processPendingOperations();
    }
  }
  
  // 处理待处理操作
  async processPendingOperations() {
    if (this.pendingOperations.length === 0) return;
    
    const operations = [...this.pendingOperations];
    this.pendingOperations = [];
    
    // 按操作类型分组
    const groupedOps = this.groupOperationsByType(operations);
    
    // 并行处理不同类型的操作
    const promises = Object.keys(groupedOps).map(type => {
      return this.processOperationGroup(type, groupedOps[type]);
    });
    
    try {
      await Promise.all(promises);
      console.log(`批处理完成: ${operations.length} 个操作`);
    } catch (error) {
      console.error('批处理失败:', error);
    }
  }
  
  // 按操作类型分组
  groupOperationsByType(operations) {
    return operations.reduce((groups, op) => {
      const key = `${op.storeName}-${op.type}`;
      if (!groups[key]) {
        groups[key] = [];
      }
      groups[key].push(op);
      return groups;
    }, {});
  }
  
  // 处理操作组
  async processOperationGroup(groupKey, operations) {
    const [storeName, operationType] = groupKey.split('-');
    
    switch (operationType) {
      case 'write':
        return this.batchWrite(storeName, operations.map(op => op.data));
      case 'delete':
        return this.batchDelete(storeName, operations.map(op => op.key));
      case 'update':
        return this.batchUpdate(storeName, operations);
      default:
        console.warn(`未知操作类型: ${operationType}`);
    }
  }
  
  // 批量删除
  async batchDelete(storeName, keys) {
    const db = await this.openDB();
    
    return new Promise((resolve, reject) => {
      const transaction = db.transaction([storeName], 'readwrite');
      const store = transaction.objectStore('test');
      const results = [];
      
      transaction.oncomplete = () => {
        db.close();
        resolve(results);
      };
      
      transaction.onerror = () => {
        db.close();
        reject(transaction.error);
      };
      
      keys.forEach((key, index) => {
        const request = store.delete(key);
        
        request.onsuccess = () => {
          results.push({ index, key, success: true });
        };
        
        request.onerror = () => {
          results.push({ index, key, success: false, error: request.error });
        };
      });
    });
  }
  
  // 批量更新
  async batchUpdate(storeName, operations) {
    const db = await this.openDB();
    
    return new Promise((resolve, reject) => {
      const transaction = db.transaction([storeName], 'readwrite');
      const store = transaction.objectStore('test');
      const results = [];
      
      transaction.oncomplete = () => {
        db.close();
        resolve(results);
      };
      
      transaction.onerror = () => {
        db.close();
        reject(transaction.error);
      };
      
      operations.forEach((op, index) => {
        // 先读取现有数据
        const getRequest = store.get(op.key);
        
        getRequest.onsuccess = () => {
          const existingData = getRequest.result;
          if (existingData) {
            // 合并数据
            const updatedData = { ...existingData, ...op.updates };
            
            // 写回数据库
            const putRequest = store.put(updatedData);
            
            putRequest.onsuccess = () => {
              results.push({ index, key: op.key, success: true });
            };
            
            putRequest.onerror = () => {
              results.push({ index, key: op.key, success: false, error: putRequest.error });
            };
          } else {
            results.push({ index, key: op.key, success: false, error: 'Record not found' });
          }
        };
        
        getRequest.onerror = () => {
          results.push({ index, key: op.key, success: false, error: getRequest.error });
        };
      });
    });
  }
  
  // 打开数据库
  async openDB() {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open('batch-operations', 1);
      
      request.onerror = () => reject(request.error);
      request.onsuccess = () => resolve(request.result);
      
      request.onupgradeneeded = (event) => {
        const db = event.target.result;
        
        if (!db.objectStoreNames.contains('test')) {
          const store = db.createObjectStore('test', { keyPath: 'id' });
          store.createIndex('category', 'category', { unique: false });
          store.createIndex('timestamp', 'timestamp', { unique: false });
        }
      };
    });
  }
}

// 使用示例
const batchManager = new BatchOperationManager();

// 批量写入大量数据
const largeDataset = Array(10000).fill(null).map((_, index) => ({
  id: `item-${index}`,
  name: `Item ${index}`,
  category: `category-${index % 10}`,
  timestamp: Date.now() + index,
  data: `Some data for item ${index}`
}));

// 带进度回调的批量写入
batchManager.batchWrite('test', largeDataset, {
  batchSize: 200,
  onProgress: (progress) => {
    console.log(`进度: ${progress.percentage.toFixed(2)}% (${progress.processed}/${progress.total})`);
  },
  onError: (error, batch) => {
    console.error('批次处理失败:', error);
  }
}).then(result => {
  console.log('批量写入完成:', result);
});

// 使用智能队列
for (let i = 0; i < 1000; i++) {
  batchManager.queueOperation({
    type: 'write',
    storeName: 'test',
    data: {
      id: `queued-${i}`,
      value: Math.random()
    }
  });
}

2.2 Cache API批量操作

class CacheBatchManager {
  constructor() {
    this.batchSize = 50;
    this.concurrentLimit = 5;
  }
  
  // 批量缓存资源
  async batchCacheResources(cacheName, resources, options = {}) {
    const { 
      batchSize = this.batchSize,
      concurrentLimit = this.concurrentLimit,
      onProgress = null 
    } = options;
    
    const cache = await caches.open(cacheName);
    const results = [];
    const errors = [];
    
    // 分批处理
    for (let i = 0; i < resources.length; i += batchSize) {
      const batch = resources.slice(i, i + batchSize);
      
      try {
        // 限制并发数
        const chunks = this.chunkArray(batch, concurrentLimit);
        
        for (const chunk of chunks) {
          const chunkPromises = chunk.map(resource => 
            this.cacheResource(cache, resource)
          );
          
          const chunkResults = await Promise.allSettled(chunkPromises);
          
          chunkResults.forEach((result, index) => {
            if (result.status === 'fulfilled') {
              results.push(result.value);
            } else {
              errors.push({
                resource: chunk[index],
                error: result.reason
              });
            }
          });
        }
        
        // 进度回调
        if (onProgress) {
          onProgress({
            processed: Math.min(i + batchSize, resources.length),
            total: resources.length,
            percentage: Math.min((i + batchSize) / resources.length * 100, 100)
          });
        }
        
      } catch (error) {
        console.error('批次缓存失败:', error);
      }
    }
    
    return {
      success: results.length,
      errors: errors.length,
      results,
      errorDetails: errors
    };
  }
  
  // 缓存单个资源
  async cacheResource(cache, resource) {
    const { url, options = {} } = resource;
    
    try {
      // 检查是否已缓存
      const existing = await cache.match(url);
      if (existing && !options.force) {
        return { url, status: 'already-cached' };
      }
      
      // 获取资源
      const response = await fetch(url, options.fetchOptions);
      
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }
      
      // 缓存资源
      await cache.put(url, response.clone());
      
      return { 
        url, 
        status: 'cached',
        size: response.headers.get('content-length') || 'unknown'
      };
      
    } catch (error) {
      throw new Error(`缓存失败 ${url}: ${error.message}`);
    }
  }
  
  // 预加载关键资源
  async preloadCriticalResources(resources) {
    console.log('开始预加载关键资源...');
    
    const criticalCache = await caches.open('critical-resources');
    const results = [];
    
    // 并行预加载
    const promises = resources.map(async (resource) => {
      try {
        const startTime = performance.now();
        
        // 使用高优先级获取
        const response = await fetch(resource.url, {
          priority: 'high',
          ...resource.options
        });
        
        if (response.ok) {
          await criticalCache.put(resource.url, response.clone());
          
          const endTime = performance.now();
          results.push({
            url: resource.url,
            success: true,
            loadTime: endTime - startTime,
            size: response.headers.get('content-length')
          });
        }
        
      } catch (error) {
        results.push({
          url: resource.url,
          success: false,
          error: error.message
        });
      }
    });
    
    await Promise.all(promises);
    
    console.log('关键资源预加载完成:', results);
    return results;
  }
  
  // 智能缓存更新
  async smartCacheUpdate(cacheName, resources) {
    const cache = await caches.open(cacheName);
    const updates = [];
    
    // 检查哪些资源需要更新
    for (const resource of resources) {
      const cached = await cache.match(resource.url);
      
      if (!cached) {
        updates.push({ ...resource, action: 'add' });
        continue;
      }
      
      // 检查是否需要更新
      const needsUpdate = await this.checkIfNeedsUpdate(cached, resource);
      if (needsUpdate) {
        updates.push({ ...resource, action: 'update' });
      }
    }
    
    if (updates.length === 0) {
      console.log('所有资源都是最新的');
      return { updated: 0, added: 0 };
    }
    
    // 批量更新
    const result = await this.batchCacheResources(cacheName, updates);
    
    const added = updates.filter(u => u.action === 'add').length;
    const updated = updates.filter(u => u.action === 'update').length;
    
    console.log(`缓存更新完成: 新增 ${added}, 更新 ${updated}`);
    
    return { updated, added, errors: result.errors };
  }
  
  // 检查资源是否需要更新
  async checkIfNeedsUpdate(cachedResponse, resource) {
    // 检查ETag
    if (resource.etag) {
      const cachedETag = cachedResponse.headers.get('etag');
      return cachedETag !== resource.etag;
    }
    
    // 检查Last-Modified
    if (resource.lastModified) {
      const cachedLastModified = cachedResponse.headers.get('last-modified');
      return new Date(cachedLastModified) < new Date(resource.lastModified);
    }
    
    // 检查缓存时间
    if (resource.maxAge) {
      const cacheDate = cachedResponse.headers.get('date');
      const age = Date.now() - new Date(cacheDate).getTime();
      return age > resource.maxAge * 1000;
    }
    
    return false;
  }
  
  // 数组分块
  chunkArray(array, chunkSize) {
    const chunks = [];
    for (let i = 0; i < array.length; i += chunkSize) {
      chunks.push(array.slice(i, i + chunkSize));
    }
    return chunks;
  }
}

// 使用示例
const cacheManager = new CacheBatchManager();

// 批量缓存静态资源
const staticResources = [
  { url: '/css/main.css' },
  { url: '/js/app.js' },
  { url: '/js/vendor.js' },
  { url: '/images/logo.png' },
  { url: '/images/hero.jpg' },
  // ... 更多资源
];

cacheManager.batchCacheResources('static-v1', staticResources, {
  batchSize: 10,
  onProgress: (progress) => {
    console.log(`缓存进度: ${progress.percentage.toFixed(1)}%`);
  }
}).then(result => {
  console.log('静态资源缓存完成:', result);
});

// 预加载关键资源
const criticalResources = [
  { url: '/api/user/profile', options: { credentials: 'include' } },
  { url: '/css/critical.css' },
  { url: '/js/critical.js' }
];

cacheManager.preloadCriticalResources(criticalResources);

3. 数据压缩与序列化优化

3.1 数据压缩策略

class DataCompressionManager {
  constructor() {
    this.compressionMethods = {
      gzip: this.gzipCompress.bind(this),
      lz4: this.lz4Compress.bind(this),
      json: this.jsonOptimize.bind(this),
      binary: this.binarySerialize.bind(this)
    };
  }
  
  // 智能压缩选择
  async smartCompress(data, options = {}) {
    const { 
      method = 'auto',
      threshold = 1024, // 1KB以上才压缩
      target = 'storage' // storage | network
    } = options;
    
    const originalSize = this.getDataSize(data);
    
    // 小数据不压缩
    if (originalSize < threshold) {
      return {
        data,
        compressed: false,
        originalSize,
        compressedSize: originalSize,
        method: 'none'
      };
    }
    
    let bestResult = null;
    let bestRatio = 0;
    
    // 自动选择最佳压缩方法
    if (method === 'auto') {
      const methods = target === 'network' 
        ? ['gzip', 'json'] 
        : ['gzip', 'lz4', 'json', 'binary'];
      
      for (const methodName of methods) {
        try {
          const result = await this.compressWithMethod(data, methodName);
          const ratio = (originalSize - result.compressedSize) / originalSize;
          
          if (ratio > bestRatio) {
            bestRatio = ratio;
            bestResult = result;
          }
        } catch (error) {
          console.warn(`压缩方法 ${methodName} 失败:`, error);
        }
      }
    } else {
      bestResult = await this.compressWithMethod(data, method);
    }
    
    // 如果压缩效果不好,返回原始数据
    if (!bestResult || bestResult.compressedSize >= originalSize * 0.9) {
      return {
        data,
        compressed: false,
        originalSize,
        compressedSize: originalSize,
        method: 'none'
      };
    }
    
    return bestResult;
  }
  
  // 使用指定方法压缩
  async compressWithMethod(data, method) {
    const originalSize = this.getDataSize(data);
    const startTime = performance.now();
    
    const compressedData = await this.compressionMethods[method](data);
    const compressedSize = this.getDataSize(compressedData);
    const compressionTime = performance.now() - startTime;
    
    return {
      data: compressedData,
      compressed: true,
      originalSize,
      compressedSize,
      method,
      compressionTime,
      ratio: (originalSize - compressedSize) / originalSize
    };
  }
  
  // GZIP压缩
  async gzipCompress(data) {
    const stream = new CompressionStream('gzip');
    const writer = stream.writable.getWriter();
    const reader = stream.readable.getReader();
    
    const chunks = [];
    
    // 写入数据
    const encoder = new TextEncoder();
    const inputData = typeof data === 'string' ? data : JSON.stringify(data);
    writer.write(encoder.encode(inputData));
    writer.close();
    
    // 读取压缩结果
    let result;
    while (!(result = await reader.read()).done) {
      chunks.push(result.value);
    }
    
    // 合并chunks
    const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
    const compressed = new Uint8Array(totalLength);
    let offset = 0;
    
    for (const chunk of chunks) {
      compressed.set(chunk, offset);
      offset += chunk.length;
    }
    
    return {
      type: 'gzip',
      data: compressed,
      metadata: {
        originalType: typeof data,
        timestamp: Date.now()
      }
    };
  }
  
  // GZIP解压
  async gzipDecompress(compressedData) {
    const stream = new DecompressionStream('gzip');
    const writer = stream.writable.getWriter();
    const reader = stream.readable.getReader();
    
    const chunks = [];
    
    // 写入压缩数据
    writer.write(compressedData.data);
    writer.close();
    
    // 读取解压结果
    let result;
    while (!(result = await reader.read()).done) {
      chunks.push(result.value);
    }
    
    // 合并并解码
    const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
    const decompressed = new Uint8Array(totalLength);
    let offset = 0;
    
    for (const chunk of chunks) {
      decompressed.set(chunk, offset);
      offset += chunk.length;
    }
    
    const decoder = new TextDecoder();
    const text = decoder.decode(decompressed);
    
    // 根据原始类型返回数据
    return compressedData.metadata.originalType === 'string' 
      ? text 
      : JSON.parse(text);
  }
  
  // JSON优化压缩
  async jsonOptimize(data) {
    if (typeof data !== 'object') {
      return data;
    }
    
    // 移除空值和undefined
    const cleaned = this.removeEmptyValues(data);
    
    // 压缩键名
    const { compressed, keyMap } = this.compressKeys(cleaned);
    
    // 使用紧凑JSON格式
    const jsonString = JSON.stringify(compressed);
    
    return {
      type: 'json-optimized',
      data: jsonString,
      keyMap,
      metadata: {
        originalKeys: Object.keys(data).length,
        compressedKeys: Object.keys(keyMap).length
      }
    };
  }
  
  // 移除空值
  removeEmptyValues(obj) {
    if (Array.isArray(obj)) {
      return obj.map(item => this.removeEmptyValues(item))
                .filter(item => item !== null && item !== undefined);
    }
    
    if (typeof obj === 'object' && obj !== null) {
      const cleaned = {};
      
      for (const [key, value] of Object.entries(obj)) {
        if (value !== null && value !== undefined && value !== '') {
          const cleanedValue = this.removeEmptyValues(value);
          if (cleanedValue !== null && cleanedValue !== undefined) {
            cleaned[key] = cleanedValue;
          }
        }
      }
      
      return cleaned;
    }
    
    return obj;
  }
  
  // 压缩对象键名
  compressKeys(obj) {
    const keyMap = {};
    let keyCounter = 0;
    
    const compress = (item) => {
      if (Array.isArray(item)) {
        return item.map(compress);
      }
      
      if (typeof item === 'object' && item !== null) {
        const compressed = {};
        
        for (const [key, value] of Object.entries(item)) {
          // 为长键名创建短别名
          let compressedKey = key;
          if (key.length > 3) {
            if (!keyMap[key]) {
              keyMap[key] = `k${keyCounter++}`;
            }
            compressedKey = keyMap[key];
          }
          
          compressed[compressedKey] = compress(value);
        }
        
        return compressed;
      }
      
      return item;
    };
    
    return {
      compressed: compress(obj),
      keyMap
    };
  }
  
  // 二进制序列化
  async binarySerialize(data) {
    // 简化的二进制序列化实现
    const buffer = new ArrayBuffer(1024 * 1024); // 1MB buffer
    const view = new DataView(buffer);
    let offset = 0;
    
    const serialize = (value) => {
      if (typeof value === 'number') {
        view.setUint8(offset++, 1); // type: number
        view.setFloat64(offset, value);
        offset += 8;
      } else if (typeof value === 'string') {
        view.setUint8(offset++, 2); // type: string
        const encoder = new TextEncoder();
        const encoded = encoder.encode(value);
        view.setUint32(offset, encoded.length);
        offset += 4;
        
        for (let i = 0; i < encoded.length; i++) {
          view.setUint8(offset++, encoded[i]);
        }
      } else if (typeof value === 'boolean') {
        view.setUint8(offset++, 3); // type: boolean
        view.setUint8(offset++, value ? 1 : 0);
      } else if (Array.isArray(value)) {
        view.setUint8(offset++, 4); // type: array
        view.setUint32(offset, value.length);
        offset += 4;
        
        value.forEach(serialize);
      } else if (typeof value === 'object' && value !== null) {
        view.setUint8(offset++, 5); // type: object
        const keys = Object.keys(value);
        view.setUint32(offset, keys.length);
        offset += 4;
        
        keys.forEach(key => {
          serialize(key);
          serialize(value[key]);
        });
      }
    };
    
    serialize(data);
    
    return {
      type: 'binary',
      data: buffer.slice(0, offset),
      size: offset
    };
  }
  
  // 获取数据大小
  getDataSize(data) {
    if (data instanceof ArrayBuffer) {
      return data.byteLength;
    }
    
    if (data instanceof Uint8Array) {
      return data.length;
    }
    
    if (typeof data === 'string') {
      return new TextEncoder().encode(data).length;
    }
    
    return new TextEncoder().encode(JSON.stringify(data)).length;
  }
  
  // 解压数据
  async decompress(compressedData) {
    switch (compressedData.type) {
      case 'gzip':
        return this.gzipDecompress(compressedData);
      
      case 'json-optimized':
        return this.jsonDecompress(compressedData);
      
      case 'binary':
        return this.binaryDeserialize(compressedData);
      
      default:
        return compressedData.data;
    }
  }
  
  // JSON解压
  jsonDecompress(compressedData) {
    const parsed = JSON.parse(compressedData.data);
    
    // 恢复键名
    const decompress = (item) => {
      if (Array.isArray(item)) {
        return item.map(decompress);
      }
      
      if (typeof item === 'object' && item !== null) {
        const decompressed = {};
        
        for (const [key, value] of Object.entries(item)) {
          // 查找原始键名
          const originalKey = Object.keys(compressedData.keyMap)
            .find(k => compressedData.keyMap[k] === key) || key;
          
          decompressed[originalKey] = decompress(value);
        }
        
        return decompressed;
      }
      
      return item;
    };
    
    return decompress(parsed);
  }
}

// 使用示例
const compressionManager = new DataCompressionManager();

// 压缩大型数据对象
const largeData = {
  users: Array(1000).fill(null).map((_, i) => ({
    id: i,
    name: `User ${i}`,
    email: `user${i}@example.com`,
    profile: {
      age: 20 + (i % 50),
      city: `City ${i % 10}`,
      preferences: {
        theme: i % 2 ? 'dark' : 'light',
        language: i % 3 ? 'en' : 'zh',
        notifications: true
      }
    }
  })),
  metadata: {
    version: '1.0',
    timestamp: Date.now(),
    source: 'user-management-system'
  }
};

// 智能压缩
compressionManager.smartCompress(largeData, {
  method: 'auto',
  target: 'storage'
}).then(result => {
  console.log('压缩结果:', {
    method: result.method,
    originalSize: `${(result.originalSize / 1024).toFixed(2)} KB`,
    compressedSize: `${(result.compressedSize / 1024).toFixed(2)} KB`,
    ratio: `${(result.ratio * 100).toFixed(2)}%`,
    compressionTime: `${result.compressionTime.toFixed(2)} ms`
  });
  
  // 保存压缩数据
  localStorage.setItem('compressed-data', JSON.stringify(result));
});

3.2 序列化优化

class SerializationOptimizer {
  constructor() {
    this.serializers = {
      json: this.jsonSerializer.bind(this),
      msgpack: this.msgpackSerializer.bind(this),
      protobuf: this.protobufSerializer.bind(this),
      custom: this.customSerializer.bind(this)
    };
  }
  
  // 智能序列化选择
  async optimizeSerialize(data, options = {}) {
    const { 
      format = 'auto',
      includeMetadata = true,
      validateData = true 
    } = options;
    
    if (validateData) {
      this.validateData(data);
    }
    
    const results = [];
    
    if (format === 'auto') {
      // 测试所有序列化方法
      for (const [name, serializer] of Object.entries(this.serializers)) {
        try {
          const startTime = performance.now();
          const serialized = await serializer(data);
          const endTime = performance.now();
          
          results.push({
            format: name,
            data: serialized,
            size: this.getSerializedSize(serialized),
            time: endTime - startTime
          });
        } catch (error) {
          console.warn(`序列化方法 ${name} 失败:`, error);
        }
      }
      
      // 选择最优方法(综合考虑大小和速度)
      const best = results.reduce((best, current) => {
        const bestScore = best.size * 0.7 + best.time * 0.3;
        const currentScore = current.size * 0.7 + current.time * 0.3;
        return currentScore < bestScore ? current : best;
      });
      
      return {
        ...best,
        metadata: includeMetadata ? {
          originalSize: this.getDataSize(data),
          allResults: results,
          selectedReason: 'auto-optimization'
        } : undefined
      };
    } else {
      const serializer = this.serializers[format];
      if (!serializer) {
        throw new Error(`不支持的序列化格式: ${format}`);
      }
      
      const startTime = performance.now();
      const serialized = await serializer(data);
      const endTime = performance.now();
      
      return {
        format,
        data: serialized,
        size: this.getSerializedSize(serialized),
        time: endTime - startTime,
        metadata: includeMetadata ? {
          originalSize: this.getDataSize(data)
        } : undefined
      };
    }
  }
  
  // JSON序列化优化
  jsonSerializer(data) {
    // 自定义JSON序列化,处理特殊类型
    const replacer = (key, value) => {
      // 处理Date对象
      if (value instanceof Date) {
        return { __type: 'Date', value: value.toISOString() };
      }
      
      // 处理RegExp对象
       if (value instanceof RegExp) {
         return { __type: 'RegExp', source: value.source, flags: value.flags };
       }
       
       // 处理Map对象
       if (value instanceof Map) {
         return { __type: 'Map', entries: Array.from(value.entries()) };
       }
       
       // 处理Set对象
       if (value instanceof Set) {
         return { __type: 'Set', values: Array.from(value.values()) };
       }
       
       // 处理BigInt
       if (typeof value === 'bigint') {
         return { __type: 'BigInt', value: value.toString() };
       }
       
       return value;
     };
     
     return JSON.stringify(data, replacer);
   }
   
   // MessagePack序列化(简化实现)
   msgpackSerializer(data) {
     // 这里应该使用真正的MessagePack库
     // 为了演示,使用简化的二进制格式
     const buffer = new ArrayBuffer(1024 * 1024);
     const view = new DataView(buffer);
     let offset = 0;
     
     const encode = (value) => {
       if (value === null) {
         view.setUint8(offset++, 0xc0); // nil
       } else if (typeof value === 'boolean') {
         view.setUint8(offset++, value ? 0xc3 : 0xc2); // true/false
       } else if (typeof value === 'number') {
         if (Number.isInteger(value) && value >= 0 && value < 128) {
           view.setUint8(offset++, value); // positive fixint
         } else {
           view.setUint8(offset++, 0xcb); // float64
           view.setFloat64(offset, value);
           offset += 8;
         }
       } else if (typeof value === 'string') {
         const encoder = new TextEncoder();
         const encoded = encoder.encode(value);
         
         if (encoded.length < 32) {
           view.setUint8(offset++, 0xa0 | encoded.length); // fixstr
         } else {
           view.setUint8(offset++, 0xda); // str16
           view.setUint16(offset, encoded.length);
           offset += 2;
         }
         
         for (let i = 0; i < encoded.length; i++) {
           view.setUint8(offset++, encoded[i]);
         }
       } else if (Array.isArray(value)) {
         if (value.length < 16) {
           view.setUint8(offset++, 0x90 | value.length); // fixarray
         } else {
           view.setUint8(offset++, 0xdc); // array16
           view.setUint16(offset, value.length);
           offset += 2;
         }
         
         value.forEach(encode);
       } else if (typeof value === 'object') {
         const keys = Object.keys(value);
         
         if (keys.length < 16) {
           view.setUint8(offset++, 0x80 | keys.length); // fixmap
         } else {
           view.setUint8(offset++, 0xde); // map16
           view.setUint16(offset, keys.length);
           offset += 2;
         }
         
         keys.forEach(key => {
           encode(key);
           encode(value[key]);
         });
       }
     };
     
     encode(data);
     
     return {
       type: 'msgpack',
       data: buffer.slice(0, offset),
       size: offset
     };
   }
   
   // Protocol Buffers序列化(简化实现)
   protobufSerializer(data) {
     // 这里应该使用真正的protobuf库
     // 为了演示,使用简化的格式
     const fields = this.analyzeDataStructure(data);
     const schema = this.generateProtobufSchema(fields);
     
     return {
       type: 'protobuf',
       schema,
       data: this.encodeWithSchema(data, schema),
       metadata: {
         fieldCount: fields.length,
         schemaSize: JSON.stringify(schema).length
       }
     };
   }
   
   // 自定义序列化
   customSerializer(data) {
     // 针对特定数据结构的优化序列化
     if (this.isUserProfileData(data)) {
       return this.serializeUserProfile(data);
     }
     
     if (this.isTimeSeriesData(data)) {
       return this.serializeTimeSeries(data);
     }
     
     if (this.isImageMetadata(data)) {
       return this.serializeImageMetadata(data);
     }
     
     // 默认使用JSON
     return this.jsonSerializer(data);
   }
   
   // 分析数据结构
   analyzeDataStructure(data, path = '') {
     const fields = [];
     
     const analyze = (obj, currentPath) => {
       if (typeof obj === 'object' && obj !== null && !Array.isArray(obj)) {
         Object.keys(obj).forEach(key => {
           const value = obj[key];
           const fieldPath = currentPath ? `${currentPath}.${key}` : key;
           
           fields.push({
             path: fieldPath,
             type: this.getFieldType(value),
             required: value !== null && value !== undefined,
             repeated: Array.isArray(value)
           });
           
           if (typeof value === 'object' && value !== null) {
             analyze(value, fieldPath);
           }
         });
       }
     };
     
     analyze(data, path);
     return fields;
   }
   
   // 获取字段类型
   getFieldType(value) {
     if (value === null || value === undefined) return 'optional';
     if (typeof value === 'boolean') return 'bool';
     if (typeof value === 'number') {
       return Number.isInteger(value) ? 'int32' : 'double';
     }
     if (typeof value === 'string') return 'string';
     if (Array.isArray(value)) return 'repeated';
     if (typeof value === 'object') return 'message';
     return 'bytes';
   }
   
   // 用户配置文件序列化
   serializeUserProfile(data) {
     const buffer = new ArrayBuffer(1024);
     const view = new DataView(buffer);
     let offset = 0;
     
     // 用户ID(4字节)
     view.setUint32(offset, data.id || 0);
     offset += 4;
     
     // 用户名长度和内容
     const nameBytes = new TextEncoder().encode(data.name || '');
     view.setUint8(offset++, nameBytes.length);
     for (let i = 0; i < nameBytes.length; i++) {
       view.setUint8(offset++, nameBytes[i]);
     }
     
     // 邮箱长度和内容
     const emailBytes = new TextEncoder().encode(data.email || '');
     view.setUint8(offset++, emailBytes.length);
     for (let i = 0; i < emailBytes.length; i++) {
       view.setUint8(offset++, emailBytes[i]);
     }
     
     // 年龄(1字节)
     view.setUint8(offset++, data.age || 0);
     
     // 偏好设置(位标志)
     let preferences = 0;
     if (data.preferences) {
       if (data.preferences.theme === 'dark') preferences |= 1;
       if (data.preferences.notifications) preferences |= 2;
       if (data.preferences.language === 'zh') preferences |= 4;
     }
     view.setUint8(offset++, preferences);
     
     return {
       type: 'user-profile',
       data: buffer.slice(0, offset),
       size: offset
     };
   }
   
   // 时间序列数据序列化
   serializeTimeSeries(data) {
     const buffer = new ArrayBuffer(data.points.length * 12 + 16);
     const view = new DataView(buffer);
     let offset = 0;
     
     // 头部信息
     view.setUint32(offset, data.points.length); // 点数量
     offset += 4;
     view.setFloat64(offset, data.startTime || 0); // 开始时间
     offset += 8;
     view.setUint32(offset, data.interval || 1000); // 时间间隔
     offset += 4;
     
     // 数据点(时间戳 + 值)
     data.points.forEach(point => {
       view.setFloat64(offset, point.timestamp);
       offset += 8;
       view.setFloat32(offset, point.value);
       offset += 4;
     });
     
     return {
       type: 'time-series',
       data: buffer.slice(0, offset),
       size: offset,
       metadata: {
         pointCount: data.points.length,
         compression: 'delta-encoding'
       }
     };
   }
   
   // 图片元数据序列化
   serializeImageMetadata(data) {
     const metadata = {
       width: data.width || 0,
       height: data.height || 0,
       format: data.format || 'unknown',
       size: data.size || 0,
       created: data.created || Date.now(),
       tags: data.tags || []
     };
     
     // 使用紧凑的二进制格式
     const buffer = new ArrayBuffer(256);
     const view = new DataView(buffer);
     let offset = 0;
     
     // 尺寸信息
     view.setUint16(offset, metadata.width);
     offset += 2;
     view.setUint16(offset, metadata.height);
     offset += 2;
     
     // 文件大小
     view.setUint32(offset, metadata.size);
     offset += 4;
     
     // 创建时间
     view.setFloat64(offset, metadata.created);
     offset += 8;
     
     // 格式(枚举)
     const formatMap = { 'jpeg': 1, 'png': 2, 'webp': 3, 'gif': 4 };
     view.setUint8(offset++, formatMap[metadata.format] || 0);
     
     // 标签
     view.setUint8(offset++, metadata.tags.length);
     metadata.tags.forEach(tag => {
       const tagBytes = new TextEncoder().encode(tag);
       view.setUint8(offset++, tagBytes.length);
       for (let i = 0; i < tagBytes.length; i++) {
         view.setUint8(offset++, tagBytes[i]);
       }
     });
     
     return {
       type: 'image-metadata',
       data: buffer.slice(0, offset),
       size: offset
     };
   }
   
   // 数据类型检测
   isUserProfileData(data) {
     return data && typeof data === 'object' && 
            'id' in data && 'name' in data && 'email' in data;
   }
   
   isTimeSeriesData(data) {
     return data && typeof data === 'object' && 
            Array.isArray(data.points) && 
            data.points.every(p => 'timestamp' in p && 'value' in p);
   }
   
   isImageMetadata(data) {
     return data && typeof data === 'object' && 
            'width' in data && 'height' in data && 'format' in data;
   }
   
   // 数据验证
   validateData(data) {
     if (data === null || data === undefined) {
       throw new Error('数据不能为空');
     }
     
     // 检查循环引用
     try {
       JSON.stringify(data);
     } catch (error) {
       if (error.message.includes('circular')) {
         throw new Error('数据包含循环引用');
       }
       throw error;
     }
     
     // 检查数据大小
     const size = this.getDataSize(data);
     if (size > 100 * 1024 * 1024) { // 100MB
       console.warn('数据过大,可能影响序列化性能');
     }
   }
   
   // 获取数据大小
   getDataSize(data) {
     if (typeof data === 'string') {
       return new TextEncoder().encode(data).length;
     }
     
     if (data instanceof ArrayBuffer) {
       return data.byteLength;
     }
     
     if (data && typeof data === 'object') {
       return new TextEncoder().encode(JSON.stringify(data)).length;
     }
     
     return 0;
   }
   
   // 获取序列化后大小
   getSerializedSize(serialized) {
     if (typeof serialized === 'string') {
       return new TextEncoder().encode(serialized).length;
     }
     
     if (serialized instanceof ArrayBuffer) {
       return serialized.byteLength;
     }
     
     if (serialized && typeof serialized === 'object' && serialized.data) {
       return this.getSerializedSize(serialized.data);
     }
     
     return 0;
   }
}

// 使用示例
const serializationOptimizer = new SerializationOptimizer();

// 测试不同类型的数据
const testData = {
  userProfile: {
    id: 12345,
    name: 'John Doe',
    email: 'john@example.com',
    age: 30,
    preferences: {
      theme: 'dark',
      notifications: true,
      language: 'zh'
    }
  },
  timeSeries: {
    startTime: Date.now(),
    interval: 1000,
    points: Array(100).fill(null).map((_, i) => ({
      timestamp: Date.now() + i * 1000,
      value: Math.sin(i * 0.1) * 100
    }))
  },
  imageMetadata: {
    width: 1920,
    height: 1080,
    format: 'jpeg',
    size: 2048576,
    created: Date.now(),
    tags: ['landscape', 'nature', 'sunset']
  }
};

// 自动选择最优序列化方法
Object.keys(testData).forEach(async (key) => {
  const data = testData[key];
  
  const result = await serializationOptimizer.optimizeSerialize(data, {
    format: 'auto',
    includeMetadata: true
  });
  
  console.log(`${key} 序列化结果:`, {
    format: result.format,
    originalSize: `${(result.metadata.originalSize / 1024).toFixed(2)} KB`,
    serializedSize: `${(result.size / 1024).toFixed(2)} KB`,
    compressionRatio: `${((1 - result.size / result.metadata.originalSize) * 100).toFixed(2)}%`,
    serializationTime: `${result.time.toFixed(2)} ms`
  });
});

通过这些优化技术,我们可以根据不同的数据特点选择最适合的存储和序列化方案,从而获得最佳的性能表现。

记住,性能优化是一个持续的过程。在实际应用中,需要:

  1. 建立基准测试:了解当前性能水平
  2. 监控关键指标:跟踪存储操作的性能变化
  3. 逐步优化:一次优化一个方面,测量效果
  4. 根据数据调整:基于实际使用情况持续改进

这样才能构建出真正高性能的Web存储解决方案,为用户提供流畅的体验。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。