工程化与框架系列(22)--前端性能优化(中)

news2025/3/11 3:23:02

前端性能优化(运行) 🏃

引言

运行时性能直接影响用户交互体验和应用流畅度。本文将深入探讨前端运行时性能优化的各种策略和技术,包括渲染优化、内存管理、计算优化等关键主题,帮助开发者构建高性能的Web应用。

运行时性能概述

运行时性能优化主要关注以下方面:

  • 渲染性能:减少重排重绘,优化动画效果
  • 内存管理:防止内存泄漏,优化内存使用
  • 计算优化:提升JavaScript执行效率
  • 事件处理:优化事件监听和响应
  • 异步操作:合理使用异步编程

渲染性能优化

DOM操作优化

// DOM操作优化工具
class DOMOptimizer {
    private static documentFragment: DocumentFragment;
    
    // 批量DOM更新
    static batchUpdate(elements: HTMLElement[]): void {
        this.documentFragment = document.createDocumentFragment();
        
        elements.forEach(element => {
            this.documentFragment.appendChild(element);
        });
        
        document.body.appendChild(this.documentFragment);
    }
    
    // 虚拟滚动实现
    static createVirtualScroller(
        container: HTMLElement,
        items: any[],
        itemHeight: number,
        renderItem: (item: any) => HTMLElement
    ): void {
        const totalHeight = items.length * itemHeight;
        const visibleItems = Math.ceil(container.clientHeight / itemHeight);
        
        container.style.height = `${totalHeight}px`;
        
        let startIndex = 0;
        let endIndex = visibleItems;
        
        const render = () => {
            container.innerHTML = '';
            const fragment = document.createDocumentFragment();
            
            for (let i = startIndex; i < endIndex; i++) {
                if (items[i]) {
                    const element = renderItem(items[i]);
                    element.style.position = 'absolute';
                    element.style.top = `${i * itemHeight}px`;
                    fragment.appendChild(element);
                }
            }
            
            container.appendChild(fragment);
        };
        
        container.addEventListener('scroll', () => {
            const scrollTop = container.scrollTop;
            startIndex = Math.floor(scrollTop / itemHeight);
            endIndex = startIndex + visibleItems;
            
            requestAnimationFrame(render);
        });
        
        render();
    }
    
    // 防止布局抖动
    static preventLayoutThrashing(callback: () => void): void {
        requestAnimationFrame(() => {
            const measurements = [];
            
            // 读取阶段
            measurements.push(document.body.scrollHeight);
            measurements.push(document.body.offsetHeight);
            
            // 写入阶段
            callback();
        });
    }
}

// 使用示例
const elements = Array.from({ length: 1000 }, (_, i) => {
    const div = document.createElement('div');
    div.textContent = `Item ${i}`;
    return div;
});

DOMOptimizer.batchUpdate(elements);

// 虚拟滚动示例
const container = document.getElementById('scroll-container')!;
const items = Array.from({ length: 10000 }, (_, i) => ({ id: i, text: `Item ${i}` }));

DOMOptimizer.createVirtualScroller(
    container,
    items,
    50,
    item => {
        const div = document.createElement('div');
        div.textContent = item.text;
        return div;
    }
);

动画性能优化

// 动画优化工具
class AnimationOptimizer {
    // 使用requestAnimationFrame实现动画
    static animate(
        element: HTMLElement,
        properties: { [key: string]: number },
        duration: number,
        easing: (t: number) => number = t => t
    ): Promise<void> {
        return new Promise(resolve => {
            const startValues: { [key: string]: number } = {};
            const startTime = performance.now();
            
            // 记录初始值
            for (const prop in properties) {
                startValues[prop] = parseFloat(getComputedStyle(element)[prop]) || 0;
            }
            
            const tick = (currentTime: number) => {
                const elapsed = currentTime - startTime;
                const progress = Math.min(elapsed / duration, 1);
                const easedProgress = easing(progress);
                
                // 更新属性值
                for (const prop in properties) {
                    const start = startValues[prop];
                    const end = properties[prop];
                    const current = start + (end - start) * easedProgress;
                    element.style[prop as any] = `${current}px`;
                }
                
                if (progress < 1) {
                    requestAnimationFrame(tick);
                } else {
                    resolve();
                }
            };
            
            requestAnimationFrame(tick);
        });
    }
    
    // GPU加速
    static enableGPUAcceleration(element: HTMLElement): void {
        element.style.transform = 'translateZ(0)';
        element.style.willChange = 'transform';
    }
    
    // 优化动画帧率
    static optimizeFrameRate(
        callback: () => void,
        targetFPS: number = 60
    ): () => void {
        let lastTime = 0;
        const interval = 1000 / targetFPS;
        
        const animate = (currentTime: number) => {
            if (currentTime - lastTime >= interval) {
                callback();
                lastTime = currentTime;
            }
            
            return requestAnimationFrame(animate);
        };
        
        const animationId = requestAnimationFrame(animate);
        
        return () => cancelAnimationFrame(animationId);
    }
}

// 使用示例
const element = document.getElementById('animated-element')!;

// 启用GPU加速
AnimationOptimizer.enableGPUAcceleration(element);

// 执行平滑动画
AnimationOptimizer.animate(
    element,
    { left: 500, top: 300 },
    1000,
    t => t * t // 二次缓动
);

// 优化动画帧率
const stopAnimation = AnimationOptimizer.optimizeFrameRate(() => {
    // 动画逻辑
    element.style.transform = `rotate(${Date.now() / 1000 * 360}deg)`;
}, 30); // 30FPS

内存管理优化

内存泄漏防护

// 内存管理工具
class MemoryManager {
    private static eventListeners: Map<HTMLElement, Set<Function>> = new Map();
    
    // 安全地添加事件监听器
    static addEventListenerSafely(
        element: HTMLElement,
        eventType: string,
        handler: Function
    ): void {
        if (!this.eventListeners.has(element)) {
            this.eventListeners.set(element, new Set());
        }
        
        this.eventListeners.get(element)!.add(handler);
        element.addEventListener(eventType, handler as EventListener);
    }
    
    // 清理事件监听器
    static removeEventListeners(element: HTMLElement): void {
        const listeners = this.eventListeners.get(element);
        
        if (listeners) {
            listeners.forEach(handler => {
                element.removeEventListener('click', handler as EventListener);
            });
            
            this.eventListeners.delete(element);
        }
    }
    
    // 清理DOM引用
    static cleanupDOMReferences(root: HTMLElement): void {
        const elements = root.getElementsByTagName('*');
        
        for (const element of elements) {
            // 清理事件监听器
            this.removeEventListeners(element as HTMLElement);
            
            // 清理数据
            delete (element as any).dataset;
            
            // 清理自定义属性
            for (const prop in element) {
                if ((element as any)[prop]?.remove) {
                    (element as any)[prop].remove();
                }
            }
        }
    }
    
    // 监控内存使用
    static monitorMemoryUsage(threshold: number = 100): void {
        if ('memory' in performance) {
            setInterval(() => {
                const usage = (performance as any).memory.usedJSHeapSize / 1024 / 1024;
                
                if (usage > threshold) {
                    console.warn(`内存使用超过阈值: ${usage.toFixed(2)}MB`);
                    // 触发垃圾回收
                    this.forceGarbageCollection();
                }
            }, 5000);
        }
    }
    
    // 强制垃圾回收(仅供开发环境使用)
    private static forceGarbageCollection(): void {
        if ('gc' in window) {
            (window as any).gc();
        }
    }
}

// 使用示例
const container = document.getElementById('container')!;

// 安全地添加事件监听器
MemoryManager.addEventListenerSafely(
    container,
    'click',
    () => console.log('Clicked')
);

// 组件卸载时清理
function unmountComponent(root: HTMLElement): void {
    MemoryManager.cleanupDOMReferences(root);
    root.remove();
}

// 监控内存使用
MemoryManager.monitorMemoryUsage(150); // 150MB阈值

对象池优化

// 对象池实现
class ObjectPool<T> {
    private pool: T[] = [];
    private createFn: () => T;
    private resetFn: (obj: T) => void;
    
    constructor(
        createFn: () => T,
        resetFn: (obj: T) => void,
        initialSize: number = 0
    ) {
        this.createFn = createFn;
        this.resetFn = resetFn;
        
        // 初始化对象池
        for (let i = 0; i < initialSize; i++) {
            this.pool.push(this.createFn());
        }
    }
    
    // 获取对象
    acquire(): T {
        return this.pool.pop() || this.createFn();
    }
    
    // 释放对象
    release(obj: T): void {
        this.resetFn(obj);
        this.pool.push(obj);
    }
    
    // 清空对象池
    clear(): void {
        this.pool = [];
    }
}

// 使用示例
interface Particle {
    x: number;
    y: number;
    velocity: { x: number; y: number };
    active: boolean;
}

const particlePool = new ObjectPool<Particle>(
    // 创建函数
    () => ({
        x: 0,
        y: 0,
        velocity: { x: 0, y: 0 },
        active: false
    }),
    // 重置函数
    particle => {
        particle.x = 0;
        particle.y = 0;
        particle.velocity.x = 0;
        particle.velocity.y = 0;
        particle.active = false;
    },
    1000 // 初始大小
);

// 使用对象池创建粒子系统
class ParticleSystem {
    private particles: Particle[] = [];
    
    createParticle(x: number, y: number): void {
        const particle = particlePool.acquire();
        particle.x = x;
        particle.y = y;
        particle.velocity.x = Math.random() * 2 - 1;
        particle.velocity.y = Math.random() * 2 - 1;
        particle.active = true;
        
        this.particles.push(particle);
    }
    
    update(): void {
        for (let i = this.particles.length - 1; i >= 0; i--) {
            const particle = this.particles[i];
            
            particle.x += particle.velocity.x;
            particle.y += particle.velocity.y;
            
            if (particle.x < 0 || particle.x > window.innerWidth ||
                particle.y < 0 || particle.y > window.innerHeight) {
                // 回收粒子
                particlePool.release(particle);
                this.particles.splice(i, 1);
            }
        }
    }
}

计算性能优化

高性能计算

// 计算优化工具
class ComputeOptimizer {
    // Web Worker管理
    private static workers: Map<string, Worker> = new Map();
    
    // 创建计算Worker
    static createComputeWorker(
        taskName: string,
        workerScript: string
    ): Worker {
        const worker = new Worker(workerScript);
        this.workers.set(taskName, worker);
        return worker;
    }
    
    // 执行密集计算
    static async computeIntensive(
        taskName: string,
        data: any
    ): Promise<any> {
        const worker = this.workers.get(taskName);
        
        if (!worker) {
            throw new Error(`Worker not found for task: ${taskName}`);
        }
        
        return new Promise((resolve, reject) => {
            worker.onmessage = (e) => resolve(e.data);
            worker.onerror = (e) => reject(e);
            worker.postMessage(data);
        });
    }
    
    // 终止计算
    static terminateCompute(taskName: string): void {
        const worker = this.workers.get(taskName);
        if (worker) {
            worker.terminate();
            this.workers.delete(taskName);
        }
    }
    
    // 批量数据处理
    static processBatch<T, R>(
        items: T[],
        processor: (item: T) => R,
        batchSize: number = 1000
    ): Promise<R[]> {
        return new Promise(resolve => {
            const results: R[] = [];
            let index = 0;
            
            const processNextBatch = () => {
                const end = Math.min(index + batchSize, items.length);
                
                while (index < end) {
                    results.push(processor(items[index]));
                    index++;
                }
                
                if (index < items.length) {
                    setTimeout(processNextBatch, 0);
                } else {
                    resolve(results);
                }
            };
            
            processNextBatch();
        });
    }
}

// 使用示例
// 创建计算Worker
const computeWorker = ComputeOptimizer.createComputeWorker(
    'matrix-multiply',
    '/workers/matrix-worker.js'
);

// 执行密集计算
async function multiplyLargeMatrices(matrix1: number[][], matrix2: number[][]) {
    try {
        const result = await ComputeOptimizer.computeIntensive(
            'matrix-multiply',
            { matrix1, matrix2 }
        );
        return result;
    } catch (error) {
        console.error('计算失败:', error);
        throw error;
    }
}

// 批量处理数据
const items = Array.from({ length: 10000 }, (_, i) => i);
const results = await ComputeOptimizer.processBatch(
    items,
    item => item * item,
    1000
);

防抖与节流

// 性能优化装饰器
class PerformanceDecorators {
    // 防抖装饰器
    static debounce(delay: number = 300): MethodDecorator {
        return function (
            target: any,
            propertyKey: string | symbol,
            descriptor: PropertyDescriptor
        ) {
            const original = descriptor.value;
            let timeoutId: NodeJS.Timeout;
            
            descriptor.value = function (...args: any[]) {
                clearTimeout(timeoutId);
                timeoutId = setTimeout(() => {
                    original.apply(this, args);
                }, delay);
            };
            
            return descriptor;
        };
    }
    
    // 节流装饰器
    static throttle(limit: number = 300): MethodDecorator {
        return function (
            target: any,
            propertyKey: string | symbol,
            descriptor: PropertyDescriptor
        ) {
            const original = descriptor.value;
            let lastRun: number = 0;
            
            descriptor.value = function (...args: any[]) {
                const now = Date.now();
                
                if (now - lastRun >= limit) {
                    lastRun = now;
                    original.apply(this, args);
                }
            };
            
            return descriptor;
        };
    }
    
    // 性能监控装饰器
    static measurePerformance(): MethodDecorator {
        return function (
            target: any,
            propertyKey: string | symbol,
            descriptor: PropertyDescriptor
        ) {
            const original = descriptor.value;
            
            descriptor.value = function (...args: any[]) {
                const start = performance.now();
                const result = original.apply(this, args);
                const end = performance.now();
                
                console.log(`${String(propertyKey)} 执行时间: ${end - start}ms`);
                
                return result;
            };
            
            return descriptor;
        };
    }
}

// 使用示例
class SearchComponent {
    @PerformanceDecorators.debounce(300)
    async search(query: string): Promise<void> {
        // 搜索逻辑
        const results = await fetch(`/api/search?q=${query}`);
        // 处理结果
    }
    
    @PerformanceDecorators.throttle(1000)
    handleScroll(): void {
        // 滚动处理逻辑
    }
    
    @PerformanceDecorators.measurePerformance()
    computeExpensiveOperation(): void {
        // 复杂计算逻辑
    }
}

事件处理优化

事件委托

// 事件优化工具
class EventOptimizer {
    // 事件委托
    static delegate(
        element: HTMLElement,
        eventType: string,
        selector: string,
        handler: (e: Event, target: HTMLElement) => void
    ): void {
        element.addEventListener(eventType, (event) => {
            const target = event.target as HTMLElement;
            const delegateTarget = target.closest(selector);
            
            if (delegateTarget && element.contains(delegateTarget)) {
                handler(event, delegateTarget as HTMLElement);
            }
        });
    }
    
    // 批量事件处理
    static batchEventProcessing<T>(
        handler: (items: T[]) => void,
        delay: number = 100
    ): (item: T) => void {
        const batch: T[] = [];
        let timeoutId: NodeJS.Timeout;
        
        return (item: T) => {
            batch.push(item);
            
            clearTimeout(timeoutId);
            timeoutId = setTimeout(() => {
                handler(batch.splice(0));
            }, delay);
        };
    }
    
    // 事件优化装饰器
    static optimizeEventHandler(): MethodDecorator {
        return function (
            target: any,
            propertyKey: string | symbol,
            descriptor: PropertyDescriptor
        ) {
            const original = descriptor.value;
            
            descriptor.value = function (...args: any[]) {
                requestAnimationFrame(() => {
                    original.apply(this, args);
                });
            };
            
            return descriptor;
        };
    }
}

// 使用示例
const list = document.getElementById('list')!;

// 使用事件委托处理列表点击
EventOptimizer.delegate(
    list,
    'click',
    '.item',
    (event, target) => {
        console.log('Clicked item:', target.textContent);
    }
);

// 批量处理事件
const batchProcessor = EventOptimizer.batchEventProcessing<string>(
    items => {
        console.log('Processing batch:', items);
    }
);

// 优化的事件处理器
class UIHandler {
    @EventOptimizer.optimizeEventHandler()
    handleResize(): void {
        // 处理调整大小的逻辑
    }
}

异步操作优化

Promise优化

// 异步操作优化工具
class AsyncOptimizer {
    // Promise并发控制
    static async concurrent<T>(
        tasks: (() => Promise<T>)[],
        concurrency: number = 3
    ): Promise<T[]> {
        const results: T[] = [];
        const executing: Promise<void>[] = [];
        
        for (const task of tasks) {
            const p = Promise.resolve().then(() => task());
            results.push(p);
            
            if (concurrency <= tasks.length) {
                const e: Promise<void> = p.then(() => {
                    executing.splice(executing.indexOf(e), 1);
                });
                executing.push(e);
                if (executing.length >= concurrency) {
                    await Promise.race(executing);
                }
            }
        }
        
        return Promise.all(results);
    }
    
    // 异步重试机制
    static async retry<T>(
        fn: () => Promise<T>,
        retries: number = 3,
        delay: number = 1000
    ): Promise<T> {
        try {
            return await fn();
        } catch (error) {
            if (retries === 0) throw error;
            
            await new Promise(resolve => setTimeout(resolve, delay));
            
            return this.retry(fn, retries - 1, delay * 2);
        }
    }
    
    // 异步缓存
    static memoizeAsync<T>(
        fn: (...args: any[]) => Promise<T>,
        ttl: number = 60000
    ): (...args: any[]) => Promise<T> {
        const cache = new Map<string, { value: T; timestamp: number }>();
        
        return async (...args: any[]): Promise<T> => {
            const key = JSON.stringify(args);
            const cached = cache.get(key);
            
            if (cached && Date.now() - cached.timestamp < ttl) {
                return cached.value;
            }
            
            const result = await fn(...args);
            cache.set(key, { value: result, timestamp: Date.now() });
            
            return result;
        };
    }
}

// 使用示例
// 并发控制
const tasks = Array.from({ length: 10 }, (_, i) => async () => {
    await new Promise(resolve => setTimeout(resolve, Math.random() * 1000));
    return i;
});

const results = await AsyncOptimizer.concurrent(tasks, 3);

// 异步重试
const fetchWithRetry = async () => {
    return await AsyncOptimizer.retry(
        async () => {
            const response = await fetch('/api/data');
            if (!response.ok) throw new Error('Request failed');
            return response.json();
        },
        3,
        1000
    );
};

// 异步缓存
const memoizedFetch = AsyncOptimizer.memoizeAsync(
    async (url: string) => {
        const response = await fetch(url);
        return response.json();
    },
    60000 // 1分钟缓存
);

最佳实践与建议

  1. 渲染优化

    • 避免频繁的DOM操作
    • 使用DocumentFragment进行批量更新
    • 实现虚拟滚动
    • 优化动画性能
  2. 内存管理

    • 及时清理事件监听器
    • 使用对象池复用对象
    • 避免闭包导致的内存泄漏
    • 定期监控内存使用
  3. 计算优化

    • 使用Web Worker处理密集计算
    • 实现数据的批量处理
    • 合理使用防抖和节流
    • 优化循环和递归
  4. 事件处理

    • 使用事件委托
    • 批量处理事件
    • 优化事件监听器
    • 使用requestAnimationFrame

总结

前端运行时性能优化是一个系统工程,需要从多个维度进行优化:

  1. 优化渲染性能
  2. 合理管理内存
  3. 提升计算效率
  4. 优化事件处理
  5. 改进异步操作

通过合理运用这些优化策略,可以显著提升Web应用的运行时性能,为用户提供流畅的交互体验。

学习资源

  1. 浏览器渲染原理
  2. JavaScript性能优化指南
  3. Web Worker使用指南
  4. 内存管理最佳实践
  5. 异步编程进阶

如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2313012.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

API调试工具的无解困境:白名单、动态IP与平台设计问题

引言 你是否曾经在开发中遇到过这样的尴尬情形&#xff1a;你打开了平台的API调试工具&#xff0c;准备一番操作&#xff0c;结果却发现根本无法连接到平台&#xff1f;别急&#xff0c;问题出在调试工具本身。今天我们要吐槽的就是那些神奇的开放平台API调试工具&#xff0c;…

php虚拟站点提示No input file specified时的问题及权限处理方法

访问站点&#xff0c;提示如下 No input file specified. 可能是文件权限有问题&#xff0c;也可能是“.user.ini”文件路径没有配置对&#xff0c;最简单的办法就是直接将它删除掉&#xff0c;还有就是将它设置正确 #配置成自己服务器上正确的路径 open_basedir/mnt/qiy/te…

RISC-V汇编学习(三)—— RV指令集

有了前两节对于RISC-V汇编、寄存器、汇编语法等的认识&#xff0c;本节开始介绍RISC-V指令集和伪指令。 前面说了RISC-V的模块化特点&#xff0c;是以RV32I为作为ISA的核心模块&#xff0c;其他都是要基于此为基础&#xff0c;可以这样认为&#xff1a;RISC-V ISA 基本整数指…

java 重点知识 — JVM存储模块与类加载器

1 jvm主要模块 方法区 存储了由类加载器从.class文件中解析的类的元数据&#xff08;类型信息、域信息、方法信息&#xff09;及运行时常量池&#xff08;引用符号及字面量&#xff09;。 所有线程共享&#xff1b;内存不要求连续&#xff0c;可扩展&#xff0c;可能发生垃圾回…

idea中使用DeepSeek让编程更加便捷

IDEA中使用DeepSeek让编程更加便捷 对于开发者来说&#xff0c;IDEA&#xff08;IntelliJ IDEA&#xff09;是一款强大的开发工具。但你是否知道&#xff0c;通过安装DeepSeek这款插件&#xff0c;可以让你的编程体验更上一层楼&#xff1f;今天&#xff0c;我们就来聊聊如何在…

elasticsearch是哪家的

Elasticsearch&#xff1a;数据搜索与分析的领航者 在当今这个信息爆炸的时代&#xff0c;快速且准确地处理海量数据成为了众多企业和组织追求的目标。而Elasticsearch正是在这个背景下脱颖而出的一款强大的开源搜索引擎。它是由位于美国加利福尼亚州的Elastic公司所开发和维护…

5. MySQL 存储引擎(详解说明)

5. MySQL 存储引擎(详解说明) 文章目录 5. MySQL 存储引擎(详解说明)1. 查看存储引擎2. 设置系统默认的存储引擎3. 设置表的存储引擎3.1 创建表时指定存储引擎3.2 修改表的存储引擎 4. 引擎介绍4.1 InnoDB 引擎&#xff1a;具备外键支持功能的事务存储引擎4.2 MyISAM 引擎&…

基于LabVIEW的伺服阀高频振动测试闭环控制系统

为实现伺服阀在设定位置上下快速移动&#xff08;1kHz控制频率&#xff09;的振动测试目标&#xff0c;需构建基于LabVIEW的闭环控制系统。系统需满足高速数据采集、实时控制算法&#xff08;如PID或自适应控制&#xff09;、高精度电流驱动及传感器反馈处理等需求。结合用户提…

97.在 Vue 3 中使用 OpenLayers 根据两行根数 (TLE) 计算并显示卫星轨迹(EPSG:3857)

前言 在许多卫星应用场景中&#xff0c;我们需要 基于 TLE&#xff08;Two-Line Element Set, 两行根数&#xff09;计算卫星轨迹&#xff0c;并在地图上进行可视化。本文将使用 Vue 3 OpenLayers satellite.js&#xff0c;实现 实时计算卫星轨迹&#xff0c;并在地图上动态更…

fastjson漏洞#不出网#原理#流量特征

原理 本质是java的反序列化漏洞&#xff0c;由于引进了自动检测类型的&#xff08;autotype&#xff09;功能&#xff0c;fastjson在对json字符串反序列化的时候&#xff0c;会读取type内容&#xff0c;会试图将json内容反序列化成这个对象&#xff0c;并调用这个类的setter方…

Linux系统基于ARM平台的LVGL移植

软硬件介绍&#xff1a;Ubuntu 20.04 ARM 和&#xff08;Cortex-A53架构&#xff09;开发板 基本原理 LVGL图形库是支持使用Linux系统的Framebuffer帧缓冲设备实现的&#xff0c;如果想要实现在ARM开发板上运行LVGL图形库&#xff0c;那么就需要把LVGL图形库提供的关于帧缓冲设…

电力场景绝缘子缺陷分割数据集labelme格式1585张4类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;1585 标注数量(json文件个数)&#xff1a;1585 标注类别数&#xff1a;4 标注类别名称:["broken part","broken insulat…

【计算机网络】深入解析 HTTP 协议的概念、工作原理和通过 Fiddler 抓包查看 HTTP 请求/响应的协议格式

网络原理— HTTP 1. 什么是HTTP? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议&#xff1a; HTTP 往往是基于传输层的 TCP 协议实现的 (HTTP1.0,HTTP1.1,HTTP2.0 均为TCP,HTTP3基于UDP实现) 我们平时打开一个网站&#xff0c;就是通过HTTP协议来…

SpringBoot优雅关机,监听关机事件,docker配置

Spring Boot 提供了多种方法来实现优雅停机&#xff08;Graceful Shutdown&#xff09;&#xff0c;这意味着在关闭应用程序之前&#xff0c;它会等待当前正在处理的请求完成&#xff0c;并且不再接受新的请求。 一、优雅停机的基本概念 优雅停机的主要步骤如下&#xff1a; …

在【k8s】中部署Jenkins的实践指南

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Kubernetes航线图&#xff1a;从船长到K8s掌舵者》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Jenkins简介 2、k8s简介 3、什么在…

Unity DOTS从入门到精通之 C# Job System

文章目录 前言安装 DOTS 包C# 任务系统Mono 环境DOTS 环境运行作业NativeContainer 前言 作为 DOTS 教程&#xff0c;我们将创建一个旋转立方体的简单程序&#xff0c;并将传统的 Unity 设计转换为 DOTS 设计。 Unity 2022.3.52f1Entities 1.3.10 安装 DOTS 包 要安装 DOTS…

【Godot4.4】浅尝Godot中的MVC

概述 基于一个Unity的视频。学习了一下基本的MVC概念&#xff0c;并尝试在Godot中实现了一下。 原始的MVC&#xff1a; Godot中的MVC&#xff1a; Model、View和Controller各自应该实现的功能如下&#xff1a; Model: 属性(数据字段)数据存取方法数据更新信号 View: 控…

Elasticsearch为索引设置自动时间戳,ES自动时间戳

文章目录 0、思路1、配置 ingest pipeline2、在索引映射中启用_source字段的时间戳3、使用 index template 全局设置时间戳4、写入测试数据5、验证结果6、总结 在使用 Elasticsearch 进行数据存储和检索时&#xff0c;时间戳字段是一个非常重要的组成部分。它可以帮助我们追踪数…

计算机网络:计算机网络的组成和功能

计算机网络的组成&#xff1a; 计算机网络的工作方式&#xff1a; 计算机网络的逻辑功能; 总结&#xff1a; 计算机网络的功能&#xff1a; 1.数据通信 2.资源共享 3.分布式处理:计算机网络的分布式处理是指将计算任务分散到网络中的多个节点&#xff08;计算机或设备&…

FPGA设计时序约束用法大全保姆级说明

目录 一、序言 二、时序约束概览 2.1 约束五大类 2.2 约束功能简述 2.3 跨时钟域约束 三、时序约束规范 3.1 时序约束顺序 3.2 约束的优先级 四、约束示例 4.1 设计代码 4.2 时序结果 4.2.1 create_clock 4.2.2 create_generated_clock 4.2.3 Rename_Auto-Derive…