JavaScript性能优化实战(4):异步编程与主线程优化
JavaScript单线程模型与事件循环深入理解
JavaScript作为一种单线程语言,其执行模型与传统多线程编程语言有着根本性的差异。这种单线程特性既是JavaScript的局限,也是其简洁性的来源。深入理解JavaScript的单线程模型和事件循环机制,对于编写高性能的异步代码至关重要。
JavaScript单线程模型的本质
JavaScript引擎只有一个主线程,负责执行所有的JavaScript代码。这意味着在任何时刻,只有一段代码在执行,其他代码必须等待。这种设计有以下重要影响:
- 简化了编程模型:开发者无需担心线程同步、资源竞争等复杂问题
- 避免了DOM操作冲突:单线程确保了DOM操作的一致性和安全性
- 带来了性能挑战:长时间运行的任务会阻塞整个应用程序
// 阻塞式代码示例
function longRunningTask() {console.log('任务开始');// 模拟耗时计算const start = Date.now();while (Date.now() - start < 3000) {// 执行密集计算,阻塞主线程3秒}console.log('任务结束');
}console.log('调用前');
longRunningTask(); // 这里会阻塞UI和所有其他操作
console.log('调用后'); // 3秒后才会执行
上面的代码明确展示了JavaScript单线程的特性:当longRunningTask
函数执行时,整个浏览器界面都会冻结,无法响应用户交互,直到函数执行完毕。
事件循环机制详解
为了解决单线程带来的阻塞问题,JavaScript采用了事件循环(Event Loop)机制,使得异步操作成为可能。事件循环是JavaScript运行时环境(如浏览器或Node.js)提供的一种机制,用于协调各种事件、用户交互、脚本执行、UI渲染和网络请求等。
事件循环的核心组件
- 调用栈(Call Stack):追踪当前执行的函数
- 任务队列(Task Queue)/宏任务队列(Macrotask Queue):存储待执行的任务
- 微任务队列(Microtask Queue):优先级高于宏任务队列
- Web API:浏览器提供的异步API,如定时器、网络请求等
- 渲染步骤:处理页面布局、绘制等操作
事件循环的执行顺序
事件循环遵循以下基本流程:
- 从调用栈中执行当前的任务(同步代码)
- 调用栈清空后,检查微任务队列,执行所有微任务
- 执行一个宏任务(如果有)
- 再次检查微任务队列,执行所有新的微任务
- 执行页面渲染(如果需要)
- 返回步骤3,继续循环
// 事件循环顺序演示
console.log('1: 同步代码开始'); // 同步代码,立即执行setTimeout(() => {console.log('2: 宏任务'); // 宏任务,稍后执行
}, 0);Promise.resolve().then(() => {console.log('3: 微任务1'); // 微任务,在当前宏任务结束后立即执行}).then(() => {console.log('4: 微任务2'); // 链式微任务});console.log('5: 同步代码结束'); // 同步代码,立即执行// 执行顺序:
// 1: 同步代码开始
// 5: 同步代码结束
// 3: 微任务1
// 4: 微任务2
// 2: 宏任务
常见的宏任务和微任务
宏任务(Macrotasks):
setTimeout
/setInterval
回调setImmediate
(Node.js环境)- I/O操作
- UI渲染
MessageChannel
微任务(Microtasks):
- Promise回调(
.then
/.catch
/.finally
) MutationObserver
回调queueMicrotask()
process.nextTick
(Node.js环境,优先级最高的微任务)
可视化事件循环机制
以下是一个简化的事件循环图示:
+---------------------+
| 执行同步代码 |
+---------------------+|v
+---------------------+
| 检查微任务队列并执行 |
+---------------------+|v
+---------------------+
| 渲染页面(如需要) |
+---------------------+|v
+---------------------+
| 执行下一个宏任务 | <---+
+---------------------+ || |v |
+---------------------+ |
| 检查微任务队列并执行 | |
+---------------------+ || |v |
+---------------------+ |
| 渲染页面(如需要) | |
+---------------------+ || |+----------------+
事件循环对性能的影响
理解事件循环对性能优化至关重要,主要影响包括:
- 任务切片:长任务会阻塞UI渲染,导致页面卡顿
- 微任务过多:连续执行大量微任务也会阻塞渲染
- 宏任务调度:合理安排宏任务可以提高用户体验
- 渲染时机:页面渲染发生在微任务之后,宏任务之前
案例:任务阻塞与优化
问题代码:
// 处理大量数据的阻塞代码
function processData(items) {console.log('开始处理数据...');items.forEach(item => {// 假设每项处理需要1msconst start = Date.now();while (Date.now() - start < 1) {} // 阻塞// 处理数据...});console.log('数据处理完成');
}// 使用10000项数据调用
const largeDataset = Array(10000).fill().map((_, i) => ({ id: i }));
processData(largeDataset); // 将阻塞UI约10秒
优化代码:
// 非阻塞版本,使用任务分片
function processDataNonBlocking(items, chunkSize = 100) {return new Promise(resolve => {console.log('开始处理数据...');const total = items.length;let processed = 0;function processChunk() {const chunk = items.slice(processed, processed + chunkSize);// 处理当前分片chunk.forEach(item => {// 处理数据...const start = Date.now();while (Date.now() - start < 1) {} // 模拟处理});processed += chunk.length;if (processed < total) {// 安排下一个分片在下一个宏任务中处理setTimeout(processChunk, 0);} else {console.log('数据处理完成');resolve();}}// 开始处理第一个分片processChunk();});
}// 使用相同数据调用优化版本
processDataNonBlocking(largeDataset).then(() => console.log('处理完成,UI保持响应'));
这个优化示例展示了如何利用事件循环将大型任务拆分成更小的块,每个块在单独的宏任务中执行,从而避免长时间阻塞主线程。
浏览器帧渲染与事件循环的关系
浏览器通常以约60FPS(每秒60帧)的频率进行屏幕更新,这意味着每帧大约有16.7ms的时间。事件循环机制在每一帧中需要完成以下工作:
- 执行JavaScript任务
- 处理微任务
- 执行DOM布局计算
- 执行绘制操作
如果JavaScript执行时间过长,就会导致浏览器无法在16.7ms内完成一帧渲染,从而出现丢帧和UI卡顿的现象。
// 检测帧率的简单方法
let lastTime = performance.now();
let frames = 0;function checkFrameRate() {frames++;const now = performance.now();if (now - lastTime > 1000) { // 每秒计算一次const fps = Math.round(frames * 1000 / (now - lastTime));console.log(`当前帧率: ${fps} FPS`);frames = 0;lastTime = now;}requestAnimationFrame(checkFrameRate);
}requestAnimationFrame(checkFrameRate);
通过上述代码可以在控制台监测页面的实时帧率,当主线程被长任务阻塞时,帧率会明显下降。
主线程任务优先级管理
在实际应用中,不同的任务往往有不同的优先级。合理安排任务优先级可以显著提升用户体验:
- 高优先级任务:用户输入响应、动画等需要立即执行
- 中优先级任务:数据加载、视图更新等可以稍后执行
- 低优先级任务:数据分析、预加载、日志记录等可以在空闲时执行
JavaScript提供了多种API来帮助开发者根据优先级安排任务:
// 高优先级任务:微任务
queueMicrotask(() => {console.log('微任务:最高优先级');
});// 动画相关任务:下一帧执行
requestAnimationFrame(() => {console.log('动画帧任务:在下一帧渲染前执行');
});// 普通优先级任务:宏任务
setTimeout(() => {console.log('定时器任务:普通优先级');
}, 0);// 低优先级任务:空闲时执行
requestIdleCallback(() => {console.log('空闲任务:仅在浏览器空闲时执行');
}, { timeout: 2000 }); // 超时参数确保任务最终会被执行
通过这种优先级管理,可以确保重要的交互响应不会被不重要的后台任务延迟。
常见的事件循环误区
在实践中,开发者经常对事件循环存在一些误解:
-
误区:
setTimeout(fn, 0)
会立即执行回调
事实:它只是将回调放入宏任务队列,仍需等待当前同步代码和所有微任务执行完毕。 -
误区:Promise总是异步执行
事实:Promise.resolve().then(callback)
中的callback是异步的,但Promise构造函数中的执行器函数是同步执行的。 -
误区:微任务总是比宏任务先执行
事实:当前宏任务中的同步代码先执行,然后是微任务队列,最后才是下一个宏任务。 -
误区:
async
函数中的代码都是异步执行的
事实:async
函数中的代码是同步执行的,只有遇到await
才会引入异步行为。
// 同步与异步执行的复杂示例
console.log('1'); // 同步setTimeout(() => {console.log('2'); // 宏任务1Promise.resolve().then(() => {console.log('3'); // 宏任务1中的微任务});
}, 0);new Promise((resolve) => {console.log('4'); // 同步resolve();console.log('5'); // 同步
}).then(() => {console.log('6'); // 微任务1setTimeout(() => {console.log('7'); // 微任务1中安排的宏任务}, 0);
});console.log('8'); // 同步// 输出顺序: 1, 4, 5, 8, 6, 2, 3, 7
理解上述代码的执行顺序需要对事件循环机制有深入理解,这也是为什么异步编程在JavaScript中既强大又容易出错。
Node.js中的事件循环差异
Node.js的事件循环与浏览器有一些重要区别:
- 阶段性执行:Node.js事件循环分为6个阶段,每个阶段处理特定类型的回调
- process.nextTick:拥有最高优先级,在当前操作后立即执行,甚至优先于微任务
- I/O回调处理:Node.js大量处理文件系统和网络I/O的回调
- 定时器实现差异:Node.js中的定时器精度可能因事件循环其他阶段的阻塞而受影响
// Node.js事件循环特性示例
setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));
process.nextTick(() => console.log('nextTick'));
Promise.resolve().then(() => console.log('promise'));// 在Node.js中的输出顺序:
// nextTick
// promise
// timeout
// immediate
// (注意:timeout和immediate的顺序可能因情况而异)
掌握这些差异对于构建高性能的全栈JavaScript应用尤为重要。
Promise链优化与异步错误处理策略
Promise是JavaScript异步编程的基石,它提供了比回调函数更优雅的异步代码组织方式。然而,不恰当地使用Promise可能导致性能问题和难以调试的错误。本节将深入探讨Promise链的优化技巧和异步错误处理的最佳实践。
Promise的运行机制与性能特性
Promise是一个表示异步操作最终完成或失败的对象。理解Promise的内部运行机制对于优化其性能至关重要。
Promise的状态与状态转换
Promise有三种状态:
- 待定(pending):初始状态,既没有被兑现,也没有被拒绝
- 已兑现(fulfilled):操作成功完成
- 已拒绝(rejected):操作失败
状态转换的重要特性:
- 状态转换是单向的,一旦从pending转为fulfilled或rejected,状态就固定不变
- Promise对象的状态变化不可被外部干预,只能由Promise本身控制
Promise在事件循环中的执行顺序
Promise的.then()
、.catch()
和.finally()
回调被放入微任务队列,在当前宏任务执行完毕后立即执行,优先级高于下一个宏任务。
console.log('同步开始');Promise.resolve().then(() => console.log('Promise回调1')).then(() => console.log('Promise回调2'));console.log('同步结束');// 输出顺序:
// 同步开始
// 同步结束
// Promise回调1
// Promise回调2
Promise链的常见性能问题与优化
1. 过长的Promise链
过长的Promise链可能导致以下问题:
- 增加代码复杂度,难以理解和维护
- 每个
.then()
都会创建新的Promise对象,增加内存开销 - 延长错误传播路径,降低错误追踪效率
优化前:
function processData(data) {return Promise.resolve(data).then(step1).then(step2).then(step3).then(step4).then(step5).then(step6).then(step7).then(result => {console.log('处理完成:', result);return result;});
}
优化后:
// 使用async/await简化Promise链
async function processDataOptimized(data) {try {const result1 = await step1(data);const result2 = await step2(result1);const result3 = await step3(result2);const result4 = await step4(result3);const result5 = await step5(result4);const result6 = await step6(result5);const result7 = await step7(result6);console.log('处理完成:', result7);return result7;} catch (error) {console.error('处理出错:', error);throw error;}
}
这种优化提高了代码可读性,更容易理解执行流程和错误传播路径。
2. 串行执行独立任务
当多个Promise任务之间没有依赖关系时,串行执行会浪费时间。
优化前:
function fetchAllData(ids) {const results = [];// 串行执行独立的请求return ids.reduce((promise, id) => {return promise.then(() => fetchData(id)).then(data => {results.push(data);});}, Promise.resolve()).then(() => results);
}// 调用示例
fetchAllData([1, 2, 3, 4, 5]).then(allData => {console.log('所有数据:', allData);
});
优化后:
function fetchAllDataParallel(ids) {// 并行执行所有请求const promises = ids.map(id => fetchData(id));return Promise.all(promises);
}// 调用示例
fetchAllDataParallel([1, 2, 3, 4, 5]).then(allData => {console.log('所有数据:', allData);
});
这种优化可以显著减少总体执行时间,特别是对于网络请求等I/O密集型操作。
3. 不必要的Promise创建
过度创建Promise对象会增加内存使用和垃圾回收压力。
优化前:
function getData(id) {// 不必要地包装同步操作return new Promise((resolve) => {const cachedData = cache.get(id);resolve(cachedData);});
}
优化后:
function getDataOptimized(id) {const cachedData = cache.get(id);// 对于已有的数据ÿ
相关文章:
JavaScript性能优化实战(4):异步编程与主线程优化
JavaScript单线程模型与事件循环深入理解 JavaScript作为一种单线程语言,其执行模型与传统多线程编程语言有着根本性的差异。这种单线程特性既是JavaScript的局限,也是其简洁性的来源。深入理解JavaScript的单线程模型和事件循环机制,对于编写高性能的异步代码至关重要。 …...
Control Center安卓版:自定义控制中心,提升手机操作体验
在使用智能手机的过程中,许多用户希望能够更加便捷地访问常用功能和工具,提升操作效率。今天,我们要介绍的 Control Center安卓版,就是这样一款功能强大的手机控制软件。它不仅提供了简便的操作方法,还允许用户自定义操…...
Web3.0的认知补充(去中心化)
涉及开发技术: Vue Web3.js Solidity 基本认知 Web3.0含义: 新一代互联网思想:去中心化及用户为中心的互联网 数据:可读可写可授权 核心技术:区块链、NFT 应用:互联网上应用 NFT &…...
在Vue3中,如何在父组件中使用v-model与子组件进行双向绑定?
在 Vue 3 里,借助 v-model 可以轻松实现父组件与子组件的双向绑定。以下为你详细介绍实现步骤与示例代码。 实现原理 v-model 在 Vue 3 里是一种语法糖,它本质上是 :modelValue 和 update:modelValue 的组合。父组件借助 :modelValue 向子组件传递数据…...
沁恒MounRiver Studio无法printf浮点数
最近在使用沁恒MounRiver Studio进行CH32V307进行开发,但是遇到了已经成功获得浮点数,但是无法printf输出浮点数 如下图所示: 经过查找资料后,发现沁恒MounRiver Studio如果要printf输出浮点数需要打开Use float with nano print…...
初识Redis · 主从复制(下)
目录 前言: 数据同步 全量复制 部分复制 实时复制 前言: 前文我们已经介绍过了主从复制的基本概念,即分布式系统中存在多个Redis节点,一个是充当为主节点,其他的为从节点,并且从节点也是可以成为主节…...
BDO分厂开展地沟“大清肠”工作
BDO分厂装置区内的地沟主要回收生产过程中产生的污水、日常雨水,日积月累地沟内堆积了一层淤泥和杂物。厚厚的淤泥气味不仅影响员工健康,而且造成排水系统不畅通,存在安全隐患。分厂借助此次待产停车的有利时机对沉积已久的淤泥进行一次彻底“…...
程序和进程的详细对比
💡 一、程序(Program) ✅ 定义: 程序是一组指令的集合,通常是一个 可执行文件(如 .exe、.out),它是静态的、保存在磁盘上的一段代码,还没有被执行。 ✅ 特点ÿ…...
Flink介绍——实时计算核心论文之Flink论文
引入 通过前面的文章,我们梳理了大数据流计算的核心发展脉络: S4论文详解S4论文总结Storm论文详解Storm论文总结Kafka论文详解Kafka论文总结MillWheel论文详解MillWheel论文总结Dataflow论文详解Dataflow论文总结 而我们专栏的主角Flink正是站在前人的…...
【C++指南】位运算知识详解
. 💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏:《C指南》 期待您的关注 文章目录 引言一、位运算符概述1. 按位与(&)2. 按位或(|&#…...
网络开发基础(游戏)之 数据交换格式
数据交换格式是不同系统、应用程序或组件之间传输和共享数据时使用的标准化数据表示方式。在网络通信中,数据交换格式的选择直接影响系统的性能、可维护性和扩展性。以下是常用的数据交换格式的介绍和选择建议。 Protobuf (Protocol Buffers)协议缓冲区 是 Googl…...
怎么配置一个kubectl客户端访问多个k8s集群
怎么配置一个kubectl客户端访问多个k8s集群 为什么有的客户端用token也访问不了k8s集群,因为有的是把~/.kube/config文件,改为了~/.kube/.config文件,文件设置成隐藏文件了。 按照kubectl的寻找配置的逻辑,kubectl找不到要访问集群…...
【MongoDB】卸载、安装低版本
卸载 MongoDB 的步骤因操作系统而异,以下是 Windows、macOS 和 Linux 的详细卸载方法: 1. Windows 卸载 MongoDB 方法 1:通过控制面板卸载 打开控制面板 Win R → 输入 appwiz.cpl → 回车 找到 MongoDB 在程序列表里找到 MongoDB Server …...
WGAN+U-Net架构实现图像修复
简介 简介:该论文提出了一种基于Wasserstein生成对抗网络(WGAN)的图像修复方法,使用U-Net生成器,通过对抗损失与内容损失联合训练,有效解决了传统方法对破损区域形状大小受限、修复痕迹明显的问题。在CelebA和LFW数据集上的实验表明,该方法修复效果优于现有技术,尤其对…...
vscode vue文件单行注释失效解决办法
打开设置,搜索 files.associations,添加项 *.vue html 点击确定即可...
机器学习(7)——K均值聚类
文章目录 1. K均值(K-means)聚类是什么算法?2. 核心思想2. 数学目标3. 算法步骤3.1. 选择K个初始质心:3.2.迭代优化3.3. 重复步骤2和步骤3: 4. 关键参数5. 优缺点6. 改进变种7. K值选择方法8. Python示例9. 应用场景10…...
LainChain技术解析:基于RAG架构的下一代语言模型增强框架
摘要 随着大语言模型(LLM)在自然语言处理领域的突破性进展,如何突破其知识时效性限制、提升事实准确性成为关键挑战。LainChain通过整合检索增强生成(RAG)技术,构建起动态知识接入框架,为LLM提供实时外部知识支持。本文从技术原理、架构设计、应用场景三个维度,深入解…...
Java 使用 RabbitMQ 消息处理(快速上手指南)
目录 一、前言二、RabbitMQ 简介三、开发环境搭建3.1 安装 RabbitMQ在 Ubuntu 上安装在 Windows 上安装使用 Docker 安装3.2 添加 Maven 依赖四、RabbitMQ 的核心概念BrokerVirtual hostConnectionChannelExchangeQueueProducerConsumer五、RabbitMQ 基本操作5.1 发送消息(生产…...
Java 2025 技术全景与实战指南:从新特性到架构革新
作为一名Java开发者,2025年的技术浪潮将带给我们前所未有的机遇与挑战。本文将带你深入探索Java生态的最新发展,从语言特性到架构革新,助你在技术洪流中把握先机! 🌟 Java 2025 新特性全景 1. 模式匹配的全面进化 (J…...
【hadoop】HBase shell 操作
1.创建course表 hbase(main):002:0> create course,cf 2.查看HBase所有表 hbase(main):003:0> list 3.查看course表结构 hbase(main):004:0> describe course 4.向course表插入数据 hbase(main):005:0> put course,001,cf:cname,hbase hbase(main):006:0> …...
rabbitmq死信队列处理
创建私信队列并绑定 # 死信交换机配置 以直连交换机为列 my:exchangeNormalName: exchange.normal.a #正常交换机queueNormalName: queue.normal.a #正常队列exchangeDlxName: exchange.dlx.a #死信交换机queueDlxName: queue.dlx.a #死信队列…...
基于事件驱动的云原生后端架构设计:从理念到落地
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:微服务之后,事件驱动正在成为新范式 随着业务复杂度的提升,传统同步式微服务调用模式逐渐暴露出瓶颈:服务间耦合度高、并发能力有限、出错链路复杂。而在互联网业务、金融交易、物联网等场景中…...
CentOS 7 磁盘阵列搭建与管理全攻略
CentOS 7 磁盘阵列搭建与管理全攻略 在数据存储需求日益增长的今天,磁盘阵列(RAID)凭借其卓越的性能、数据安全性和可靠性,成为企业级服务器和数据中心的核心存储解决方案。CentOS 7 作为一款稳定且功能强大的 Linux 操作系统&am…...
区块链技术:深入共识算法、智能合约与DApps的架构奥秘
引言:区块链的颠覆性潜力 在数字化浪潮席卷全球的今天,区块链技术以其独特的去中心化特性、不可篡改的数据记录和透明的交易机制,正在重塑我们对信任、价值交换和组织形式的理解。从比特币的诞生到以太坊的智能合约革命,再到如今…...
深度学习物理信息神经网络PINN+大模型辅助编程
1. 物理信息神经网络(PINN)的兴起 近年来,物理信息神经网络(Physics-Informed Neural Networks, PINN)成为计算科学与人工智能交叉领域的前沿方向。传统数值方法(如有限差分法、有限单元法)在高…...
vue element使用el-table时,切换tab,table表格列项发生错位问题
展示问题 问题描述:使用el-table的fixed"right"属性后,如果切换tab时,回出现最后一列错误的问题 官网提供解决方法:doLayout 需要注意的事项:我这里是通过组件使用的table组件,涉及多层组件封装…...
(八)深入了解AVFoundation-采集:拍照功能的实现
引言 在上一篇文章中,我们初步完成了使用 AVFoundation 采集视频数据的流程,掌握了 AVCaptureSession 的搭建与视频流的预览显示。 本篇将继续深入 AVFoundation,聚焦于静态图片采集的实现。通过 AVCapturePhotoOutput,我们可以…...
C++区别于C语言的提升用法(万字总结)
1.namespace产生原因 在C语言中,变量,函数,以至于类都是大量存在的,因此会产生大量的名称存在于全局作用域中,可能产生很多冲突,至此c的祖师爷为避免命名冲突和名字的污染,造出来了关键字names…...
创新项目实训开发日志4
一、开发简介 核心工作内容:logo实现、注册实现、登录实现、上传gitee 工作时间:第十周 二、logo实现 1.设计logo 2.添加logo const logoUrl new URL(/assets/images/logo.png, import.meta.url).href <div class"aside-first">…...
ospf综合作业
需求 需求分析 区域划分: 网络划分为 area 0、area 1、area 2、area 3、area 4 多个区域。其中 area 0 作为骨干区域,其他为非骨干区域。这种划分符合 OSPF(开放式最短路径优先)协议中区域设计原则,不同区域通过 ABR…...
旋转磁体产生的场-对导航姿态的影响
pitch、yaw、roll是描述物体在空间中旋转的术语,通常用于计算机图形学或航空航天领域中。这些术语描述了物体绕不同轴旋转的方式: Pitch(俯仰):绕横轴旋转,使物体向前或向后倾斜。俯仰角度通常用来描述物体…...
Hive 数据同步到 Doris 最佳实践方案:从场景适配到性能调优全解析
在大数据领域,Hive 作为成熟的数据仓库解决方案,常用于海量数据存储与离线处理,而 Doris 凭借其强大的 OLAP 能力,在实时分析、即席查询等场景表现卓越。当企业需要将 Hive 数据仓库中的数据与 Doris 的分析能力结合时,…...
netty中的Channel与Java NIO中的Channel核心对比
Netty的Channel和Java NIO的Channel虽然都用于网络通信,但设计理念、功能扩展及适用场景存在显著差异。以下从核心特性、设计模式及性能优化等维度展开对比: 1. 抽象层次与功能范围 Java NIO Channel 基础IO模型:仅支持非阻塞IO(NIO),如SocketChannel、ServerSocketChann…...
基于whisper和ffmpeg语音转文本小程序
目录 一、环境准备 ✅ 第一步:安装并准备 Conda 环境 ✅ 第二步:创建 Whisper 专用的 Conda 虚拟环境 ✅ 第三步:安装 GPU 加速版 PyTorch(适配 RTX 4060) ✅ 第四步:安装 Whisper 和 FFMPEG 依赖 ✅…...
使用ffmpeg 将图片合成为视频,填充模糊背景,并添加两段音乐
1.输入3张图片,每张播放一次,播放两秒,视频分辨率设置为1920:1080,每张图片前0.3秒淡入,后0.3秒淡出,图片宽高比不变,用白色填充空白区域 ffmpeg -loop 1 -t 2 -i "img1.jpg" \-loop 1 -t 2 -i "img2.jpg" \-loop 1 -t 2 -i "img3.jpg" \-filte…...
Python协程详解:从基础到实战
协程是Python中实现并发编程的重要方式之一,它比线程更轻量级,能够高效处理I/O密集型任务。本文将全面介绍协程的概念、原理、实现方式以及与线程、进程的对比,包含完整的效率对比代码和详细说明,帮助Python开发者深入理解并掌握协…...
服务器部署LLaMAFactory进行LoRA微调
一、什么是LLaMAFactory LlamaFactory 是一个专为 大型语言模型(LLM)微调 设计的开源工具库,旨在简化大模型(如 LLaMA、GPT、Mistral 等)的定制化训练流程,降低技术门槛和硬件成本。以下是它的核心功能和应…...
ASP.NET MVC 入门指南
以下是一份 MVC(Model - View - Controller)培训教程,以ASP.NET MVC 为例进行讲解,适合有一定编程基础的学习者快速上手。 1. MVC 概述 1.1 什么是 MVC MVC 是一种软件设计模式,它将应用程序分为三个主要部分&#…...
mapbox高阶,高程影像、行政区边界阴影效果实现
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️line线图层样式1.4 ☘️symbol符号图层…...
如何下载适用于语音识别功能增强的Google Chrome浏览器
谷歌浏览器一直是互联网用户的首选工具之一,尤其是它强大的扩展功能,使得用户可以根据需求定制浏览器。对于需要使用语音识别功能的用户来说,谷歌浏览器提供了优秀的支持,通过简单的设置和插件,可以显著提升语音识别的…...
运维打铁:Centos 7 安装 redis_exporter 1.3.5
文章目录 一、CentOS 7 安装 redis_exporter 1.3.51. 安装2. 配置自启动,并连接 Redis,修改端口3. 配置 Prometheus 采集 redis_exporter 数据4. 配置 Grafana 查看数据5. Redis 集群配置 二、常见问题及解决办法1. 下载二进制包失败2. 解压部署时权限问…...
3台CentOS虚拟机部署 StarRocks 1 FE+ 3 BE集群
背景:公司最近业务数据量上去了,需要做一个漏斗分析功能,实时性要求较高,mysql已经已经不在适用,做了个大数据技术栈选型调研后,决定使用StarRocks StarRocks官网:StarRocks | A High-Performa…...
Oracle 11g RAC ASM磁盘组剔盘、加盘实施过程
环境:AIX6.1 Oracle RAC 11.2.0.3 前期准备: 1.查看DG磁盘组空间情况: –查看DG磁盘组空间情况: ASMCMD> lsdg State Type Rebal Sector Block AU Total_MB Free_MB Req_mir_free_MB Usable_file_MB Of…...
网站高可用架构设计基础——高可用策略和架构原则
一、正面保障与减少损失 要想让系统能够稳定可用,首先要考虑如何避免问题的发生。比如说可以通过 UPS(不间断电源)来避免服务器断电,可以通过事先增加机器来解决硬件资源不足的问题。 然后,如果问题真的发生了&#…...
从入门到精通【MySQL】视图与用户权限管理
文章目录 📕1. 视图✏️1.1 视图的基本概念✏️1.2 试图的基本操作🔖1.2.1 创建视图🔖1.2.2 使用视图🔖1.2.3 修改数据🔖1.2.4 删除视图 ✏️1.3 视图的优点 📕2. 用户与权限管理✏️2.1 用户🔖…...
使用QML Tumbler 实现时间日期选择器
目录 引言相关阅读项目结构示例实现与代码解析示例一:时间选择器(TimePicker)示例二:日期时间选择器(DateTimePicker) 主窗口整合运行效果总结下载链接 引言 在现代应用程序开发中,时间与日期选…...
[golang] 介绍 | 特点 | 应用场景
“编程不仅仅是写代码,更是一种思考方式。” 参考资料 《Unix编程环境》- Brian W. Kernighan, Rob Pike《程序设计实践》- Brian W. Kernighan, Rob PikeGo语言官方网站:https://golang.orgRob Pike的个人博客:http://herpolhode.com/rob/ …...
Python 爬虫实战 | 企名科技
文章目录 一、企名科技1、目标网站2、网站特点3、确定解密位置4、扣js代码 一、企名科技 1、目标网站 网址:https://wx.qmpsee.com/articleDetail?idfeef62bfdac45a94b9cd89aed5c235be目标数据:获取消费行业研究下面的13篇文章数据 2、网站特点 服…...
c加加学习之day06->STL标准库->day01
1.介绍:C 标准模板库(Standard Template Library,简称 STL)是一组泛型编程的模板类和函数,旨在提供常用的数据结构、算法和函数对象。STL 是 C 标准库的一部分,极大地提高了编程效率和代码的可重用性。STL …...
并发设计模式实战系列(6):读写锁
🌟 大家好,我是摘星! 🌟 今天为大家带来的是并发设计模式实战系列,第六章读写锁模式,废话不多说直接开始~ 目录 一、核心原理深度拆解 1. 读写锁三维模型 2. 关键实现原理 二、生活化类比&am…...