深入剖析JavaScript内存泄漏:识别、定位与实战解决
在JavaScript的世界里,开发者通常不必像使用C++那样手动管理内存的分配和释放,这得益于JavaScript引擎内置的垃圾回收(Garbage Collection, GC)机制。然而,这并不意味着我们可以完全忽视内存管理。“自动"不等于"万无一失”,内存泄漏仍然是JavaScript应用中一个常见且棘手的问题,它会悄无声息地蚕食系统资源,导致应用性能下降、响应迟缓,甚至最终崩溃。
本文将带你深入理解JavaScript内存泄漏的本质,探讨常见的泄漏场景,并提供一套系统的识别、定位和解决内存泄漏问题的实战方法。
一、什么是JavaScript内存泄漏?
简单来说,内存泄漏指的是程序中不再需要使用的内存,由于某种原因未能被垃圾回收器正确识别并释放,从而长期驻留在内存中,导致可用内存逐渐减少的现象。
想象一下你的房间:垃圾回收器就像一个清洁工,会定期清理掉你明确丢弃(不再引用)的垃圾。但如果有些东西你已经不用了,却忘记扔掉,或者不小心把它藏在了一个你以为空了、但实际还连着其他东西的盒子里(间接引用),清洁工就不会把它清理掉,久而久之,房间就会被这些“遗忘的垃圾”堆满。在JavaScript中,这些“遗忘的垃圾”就是无法被回收的内存对象。
二、JavaScript内存管理与垃圾回收(GC)基础
要理解泄漏,得先明白内存是如何被管理的。JavaScript引擎(如V8)管理内存主要涉及:
- 分配内存: 当你创建变量、对象、函数等时,引擎会分配内存来存储它们。
- 使用内存: 在代码中读取、写入变量和对象属性。
- 释放内存: 这就是垃圾回收器的工作。GC的核心任务是找出那些“不再可达”(unreachable)的对象,并释放它们占用的内存。
可达性(Reachability) 是关键概念。GC从一组已知的“根”(Roots)对象(如全局对象、当前函数调用栈中的变量等)开始,沿着引用链遍历所有可以访问到的对象。所有可达的对象都被认为是“活”的,不可达的对象则被认为是“死”的,可以被回收。
最常见的GC算法是标记-清除(Mark-and-Sweep):
- 标记阶段: 从根对象出发,递归地访问所有可达对象,并给它们打上标记。
- 清除阶段: 遍历整个内存堆,清除所有未被标记的对象,回收它们占用的空间。
内存泄漏的根本原因,往往是开发者无意中维持了对不再需要的对象的引用,使得GC误以为这些对象仍然“可达”,从而无法回收它们。
三、常见的JavaScript内存泄漏场景及剖析
以下是一些在实际开发中非常容易踩坑的内存泄漏场景:
1. 意外的全局变量
问题描述: 在JavaScript中,如果在非严格模式下('use strict'
)忘记声明变量(未使用var
, let
, const
),该变量会被隐式地创建为全局对象的属性(在浏览器中是window
对象)。全局变量通常在页面关闭前不会被回收。
function createData() {// 忘记使用 let/const/varleakyData = new Array(1000000).join('*'); // leakyData 成为 window.leakyData
}// 调用后,即使 createData 函数执行完毕,leakyData 依然存在于全局作用域
createData();
// window.leakyData 仍然持有对大字符串的引用
为何泄漏: leakyData
成为全局变量,被根对象window
引用,因此GC认为它是可达的,即使我们后续不再需要它。
解决方案:
- 始终使用
'use strict';
模式,它会在试图创建隐式全局变量时抛出错误。 - 确保所有变量都使用
let
,const
, 或var
(函数作用域内) 正确声明。
2. 被遗忘的定时器与回调
问题描述: setInterval
和 setTimeout
创建的定时器,如果其回调函数引用了外部作用域的变量(形成了闭包),并且这个定时器没有被清除(clearInterval
/ clearTimeout
),那么即使你认为相关的对象或DOM元素已经不再需要,定时器回调函数及其闭包所引用的内存也无法被回收。
function setupTimer() {let data = { counter: 0, largeObject: new Array(100000).fill('data') };setInterval(() => {// 这个回调函数隐式地持有了对 data 对象的引用console.log(data.counter++);// 假设在某个时刻,我们不再需要这个定时器和 data 了,// 但忘记清除定时器...}, 1000);// 忘记调用 clearInterval(timerId);
}setupTimer();
为何泄漏: 只要 setInterval
还在运行,它的回调函数就一直存活。回调函数通过闭包引用了 data
对象,导致 data
对象及其包含的 largeObject
永远无法被GC回收,即使调用 setupTimer
的上下文已经销毁。
解决方案:
- 在不再需要定时器时,务必使用
clearInterval
或clearTimeout
清除它们。 - 在组件卸载或页面离开等生命周期钩子中清理定时器是常见的实践(例如在React的
useEffect
的清理函数中,或Vue的beforeDestroy
/unmounted
钩子中)。
function setupTimer() {let data = { counter: 0, largeObject: new Array(100000).fill('data') };const timerId = setInterval(() => {console.log(data.counter++);}, 1000);// 返回一个清理函数,或在适当的时候调用return function cleanup() {clearInterval(timerId);data = null; // 可选,帮助更快释放,但主要靠clearInterval};
}const cleanupTimer = setupTimer();
// ... 在未来某个时刻 ...
cleanupTimer(); // 清除定时器,释放闭包引用的内存
3. 闭包引起的内存泄漏
问题描述: 闭包是JavaScript的强大特性,但也容易成为内存泄漏的温床。当一个内部函数引用了其外部函数的变量,并且这个内部函数被传递到外部作用域并长期存活时,外部函数的整个活动对象(包含所有局部变量)可能都无法被回收,即使只有部分变量被内部函数实际使用。
function createClosure() {const largeData = new Array(1000000).join('x'); // 一个大对象const unusedData = new Array(500000).join('y'); // 未被内部函数使用return function innerFunction() {// innerFunction 只用到了 largeData 的长度,但闭包会保持对整个外部作用域的引用console.log(largeData.length);};
}// globalClosure 持有了 innerFunction 的引用
// innerFunction 通过闭包持有了 createClosure 的作用域
let globalClosure = createClosure();// 即使我们只关心 largeData.length,unusedData 也因为闭包的存在而无法被回收
// 只有当 globalClosure 不再被引用时 (e.g., globalClosure = null),闭包作用域才可能被回收
为何泄漏: innerFunction
形成了闭包,保持了对 createClosure
函数作用域的引用。虽然 innerFunction
只直接使用了 largeData
,但引擎通常会保持整个作用域链(或至少是优化后的部分),导致 unusedData
这样的大对象也无法释放。
解决方案:
- 谨慎设计闭包: 只让闭包引用确实需要的变量。如果可能,在不再需要时解除对闭包的引用(例如,将
globalClosure
设为null
)。 - 避免在闭包中持有不必要的大对象引用: 如果只需要对象的某个属性,考虑在创建闭包时只传入该属性值,而不是整个对象。
4. 未移除的DOM事件监听器
问题描述: 当你给一个DOM元素添加了事件监听器,这个监听器函数通常会隐式或显式地引用该DOM元素或其他变量。如果你之后通过JavaScript移除了这个DOM元素(例如,element.remove()
或通过innerHTML替换),但没有移除附加在其上的事件监听器,那么监听器函数及其可能通过闭包引用的任何对象(包括那个已被移除的DOM元素本身!)都无法被回收。
function attachListener() {const button = document.getElementById('myButton');const largeData = new Array(100000).fill('event data');function handleClick() {console.log('Button clicked!', largeData.length);// handleClick 通过闭包引用了 largeData}button.addEventListener('click', handleClick);// ... 稍后 ...// 假设我们通过JS移除了按钮,但忘记移除监听器button.parentNode.removeChild(button);// 或者 button = null; (这只断开了变量button对元素的引用,没移除监听器)// 此时,虽然按钮不在DOM树中,但浏览器内部可能仍然保持着对按钮元素// 的引用,因为 handleClick 监听器还附加在上面,而 handleClick 又被// (浏览器的事件分发机制)间接引用。同时,handleClick 还引用了 largeData。
}// 如果 attachListener 被反复调用,且每次都不清理监听器,泄漏会累积
为何泄漏: 事件监听器机制需要保持对回调函数 (handleClick
) 和目标元素 (button
) 的引用。即使 button
从DOM树中移除,只要监听器未被 removeEventListener
移除,这条引用链就存在,阻止了 button
元素和 handleClick
函数(及其闭包环境,包括 largeData
)被GC回收。
解决方案:
- 始终在元素被销毁或不再需要监听时,使用
removeEventListener
移除监听器。 确保传入removeEventListener
的参数(事件类型、回调函数引用、捕获/冒泡选项)与addEventListener
时完全一致。 - 使用
WeakMap
或框架提供的机制管理监听器: 对于需要动态添加/移除大量元素的场景,可以考虑使用WeakMap
来存储与元素关联的数据或回调,当元素被GC回收时,WeakMap
中的对应条目会自动消失。现代前端框架通常有自己的生命周期管理,会自动处理组件销毁时的监听器移除。
5. DOM引用泄漏(Detached DOM)
问题描述: 与事件监听器类似,如果在JavaScript代码中持有对DOM元素的引用,即使该元素已经从DOM树中移除,只要这个JS引用还存在,该DOM元素及其子元素就无法被回收。
let detachedTree; // 全局变量或某个长期存活的对象属性function createDetachedTree() {const ul = document.createElement('ul');for (let i = 0; i < 1000; i++) {const li = document.createElement('li');li.textContent = `Item ${i}`;ul.appendChild(li);}// 将这个 ul 存储在一个变量中detachedTree = ul;// 这个 ul 从未被添加到主 DOM 树,或者被添加后又被移除了// document.body.appendChild(ul);// ... later ...// document.body.removeChild(ul); // 从 DOM 移除// 只要 detachedTree 这个变量还在,并且可达,// 整个 ul 元素及其所有子 li 元素都无法被回收。
}createDetachedTree();
// 假设 detachedTree 一直存在,这1001个DOM节点就泄漏了
为何泄漏: detachedTree
变量直接引用了 ul
元素。即使 ul
不在可视的DOM树中,只要这个JavaScript引用存在,GC就认为它是可达的。
解决方案:
- 在不再需要DOM元素引用时,手动将其设为
null
。detachedTree = null;
- 利用
WeakMap
: 如果你需要将某些数据与DOM元素关联,但又不希望这种关联阻止DOM元素被回收,可以使用WeakMap
,将DOM元素作为键。当DOM元素被回收后,WeakMap
中的条目会自动移除。
四、识别与定位内存泄漏:Chrome DevTools实战
发现内存泄漏的存在通常源于观察到应用性能随时间推移而下降,或者内存占用持续增长。Chrome DevTools是诊断内存问题的强大武器。
1. 使用 Performance Monitor 实时监控
- 打开DevTools (
F12
或Ctrl+Shift+I
/Cmd+Option+I
)。 - 按
Esc
打开下方的抽屉(Console Drawer),点击三个点选择Performance monitor
。 - 勾选
JS heap size
。 - 操作你的应用,执行那些你怀疑可能导致泄漏的操作(例如,反复打开/关闭某个组件、加载大量数据)。
- 观察
JS heap size
图表。如果内存持续增长且从不回落到稳定水平,即使手动触发GC(在Memory
面板点击垃圾桶图标)后也是如此,那么很可能存在内存泄漏。
2. 使用 Memory 面板 - Heap Snapshot 对比
这是定位内存泄漏最核心的方法。
- 操作流程:
- 打开DevTools ->
Memory
面板。 - 拍下基线快照: 加载页面,达到一个稳定状态后,点击
Take snapshot
按钮,生成快照1(Snapshot 1)。 - 执行疑似泄漏的操作: 在应用中执行你怀疑导致内存泄漏的操作序列,可以重复几次以放大效果。
- 拍下对比快照: 操作完成后,再次点击
Take snapshot
,生成快照2(Snapshot 2)。 - 对比快照:
- 在快照列表中选中 Snapshot 2。
- 在下方的下拉菜单中,选择
Comparison
(对比)。 - 在其旁边的下拉菜单中,选择
Snapshot 1
作为对比基准。
- 分析对比结果:
- 排序: 按
#Delta
(增量)或Size Delta
(大小增量)降序排序。这会显示两次快照之间新增了哪些对象,或者哪些类型的对象数量显著增加。 - 关注点:
(Detached DOM tree)
/Detached HTMLDivElement
等: 红色高亮显示的通常是脱离DOM树但未被回收的元素,这是典型的DOM泄漏。点击展开,查看其Retainers
(持有者)面板。- 自定义对象/闭包: 寻找你自己代码中定义的构造函数或对象,如果它们的数量或大小异常增长,重点排查。
- 数组/字符串: 大量的数组或长字符串增长也值得关注。
- 分析
Retainers
(持有者)链: 选中一个可疑的对象,下方的Retainers
面板会显示一个引用链,告诉你是什么东西阻止了这个对象被回收。从你的代码根源(例如window
或某个全局变量、事件监听器、闭包)一直追溯到这个泄漏的对象。这通常能直接定位到泄漏源头。
- 排序: 按
- 打开DevTools ->
3. 使用 Memory 面板 - Allocation Instrumentation on Timeline / Allocation Sampling
- Allocation Instrumentation on Timeline (旧版,更详细但开销大): 记录一段时间内所有的内存分配。可以按时间线查看内存增长情况,并关联到具体的函数调用。适合精确定位短期内大量分配内存的代码。
- Allocation Sampling (新版,开销小,基于采样): 记录内存分配的来源函数。运行一段时间后停止记录,可以得到一个按函数分配内存多少排序的列表。适合查找持续分配内存且可能导致泄漏的函数。
使用这些工具可以帮助你找到哪些代码路径正在创建大量对象,结合 Heap Snapshot 可以确认这些对象是否最终被回收。
五、解决与预防:最佳实践
- 编码习惯:
- 始终使用
'use strict';
。 - 用
let
和const
代替var
,并确保变量在使用前已声明。 - 注意闭包范围,避免无意中捕获不需要的大对象。
- 始终使用
- 资源清理:
- 定时器:
setInterval
/setTimeout
返回的ID要保存好,在不再需要时调用clearInterval
/clearTimeout
。 - 事件监听器: 使用
addEventListener
后,务必在适当时候(元素移除、组件卸载)使用removeEventListener
清理。注意参数需完全匹配。考虑使用AbortController
/signal
来批量取消事件监听。 - DOM引用: 当不再需要对DOM元素的JS引用时,将其赋值为
null
。 - Web Workers / Observers 等: 任何需要手动
terminate()
或disconnect()
的API,都要确保在生命周期结束时调用清理方法。
- 定时器:
- 善用现代特性:
WeakMap
/WeakSet
: 用于将数据与对象关联,而不会阻止对象被GC回收。非常适合缓存、存储与DOM节点相关的信息等场景。WeakRef
/FinalizationRegistry
(ES2021+): 提供更底层的弱引用和对象被回收时的回调通知能力,适用于更复杂的内存管理场景,但使用时需谨慎。
- 框架生命周期: 熟悉你所使用的前端框架(React, Vue, Angular等)提供的生命周期钩子函数,在组件卸载或销毁时执行必要的清理操作。框架通常会帮助处理很多底层的DOM和事件监听器管理。
- 代码审查: 将内存管理和资源清理作为代码审查的一部分。
- 持续监控: 对于大型或长期运行的应用,考虑集成性能监控工具(RUM - Real User Monitoring),持续观察线上应用的内存使用情况。
六、结语
JavaScript内存泄漏是一个潜藏的性能杀手。虽然现代JS引擎的GC已经非常智能,但不良的编码习惯和对资源生命周期管理的疏忽仍会导致内存无法释放。理解GC的基本原理,熟悉常见的泄漏模式,并掌握使用DevTools等工具进行诊断的方法,是每个专业JavaScript开发者必备的技能。
记住,内存优化不是一蹴而就的事情,它需要持续的关注和实践。养成良好的编码习惯,时刻谨记资源的申请与释放,才能构建出健壮、高效的JavaScript应用。
相关文章:
深入剖析JavaScript内存泄漏:识别、定位与实战解决
在JavaScript的世界里,开发者通常不必像使用C那样手动管理内存的分配和释放,这得益于JavaScript引擎内置的垃圾回收(Garbage Collection, GC)机制。然而,这并不意味着我们可以完全忽视内存管理。“自动"不等于&qu…...
JVM原理与实战
一、Java虚拟机概述 java程序通过虚拟机实现了java代码的跨平台。 二、java虚拟机运行过程: 类编译器编译java代码为class文件, 类加载器将class文件加载到jvm, 程序计数器控制程序的执行, 虚拟机栈存放局部变量,方法名…...
MCP协议用到的Node.js 和 npm npx
一、Node.js 与 npm、npx 的介绍 Node.js:是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,使您能够在服务器端运行 JavaScript 代码。它广泛用于构建服务器端应用程序和工具。 npm(Node Package Manager):是 Nod…...
如何写 commit message?
前言 每次写 commit message 时,都会纠结用什么动词,格式应该什么样,所以决定总结一下。 查了一下,还是挺复杂的。因为只面向我个人日常使用,所以只进行一些简单的、适合我的总结。 正文 message 分为两部分&#…...
【厦门大学】DeepSeek大模型赋能高校教学和科研
DeepSeek赋能高校教学和科研 引言人工智能发展简史:从图灵测试到大模型时代大模型核心技术解析:构筑智能金字塔DeepSeek赋能高校:打造智能校园生态本地部署方案:安全、高效与定制化兼得教学革新:重塑知识传授与学习体验…...
【专刷】滑动窗口(一)
📝前言说明: 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录,按专题划分每题主要记录:(1)本人解法 本人屎山代码;(2)优质解法 优质代码;ÿ…...
cJSON_Print 和 cJSON_PrintUnformatted的区别
cJSON_Print 和 cJSON_PrintUnformatted 是 cJSON 库中用于将 cJSON 对象转换为 JSON 字符串的两个函数,它们的区别主要在于输出的格式: 1. cJSON_Print 功能:将 cJSON 对象转换为格式化的 JSON 字符串。 特点: 输出的 JSON 字符…...
C 语 言 --- 指 针 4(习 题)
C 语 言 --- 指 针 4(习 题) sizeofstrlen整 型 数 组 - - - int a[ ]字 符 数 组 - - - char arr[ ]字 符 数 组 - - - char arr1[ ]字 符 串 常 量 指 针 - - - char arr[ ]二 维 数 组 - - - char arr[3][4]总结 💻作 者 简 介:…...
可发1区的超级创新思路(python 、MATLAB实现):基于区域注意力双通道MABMA的时间序列预测模型
首先声明,该模型为原创!原创!原创!且该思路还未有成果发表,感兴趣的小伙伴可以借鉴! 应用领域:功率预测、故障诊断、流量预测等领域! 目录 首先声明,该模型为原创!原创!原创!且该思路还未有成果发表,感兴趣的小伙伴可以借鉴! 应用领域:功率预测、故障诊断、流…...
可发1区的超级创新思路(python 、MATLAB实现):基于多尺度注意力TCN-KAN与小波变换的时间序列预测模型
一、数学模型与原理 1.1 小波变换多尺度分解 输入功率序列 x(t) 经小波变换分解为近似系数 Aj 与细节系数 Dj: 1.2 多尺度TCN特征提取 对每个尺度子序列 {A3,D3,D2,D1} 采用独立TCN: 式中 ∗d 为扩张率 d=2l 的扩张卷积,Wd 为可学习参数。 1.3 多尺度注…...
PyTorch `flatten()` 和 `squeeze()` 区别
PyTorch flatten() 和 squeeze() 区别 在 PyTorch 里,flatten() 和 squeeze(0) 是两个不同的张量操作, 1. flatten() 方法 flatten() 方法用于把一个多维张量展开成一维张量。它会将张量里的所有元素按顺序排列成一个一维序列。 语法 torch.flatten(input, start_dim=...
使用Java基于Geotools的SLD文件编程式创建与磁盘生成实战
前言 在地理信息系统(GIS)领域,地图的可视化呈现至关重要,而样式定义语言(SLD)文件为地图元素的样式配置提供了强大的支持。SLD 能够精确地定义地图图层中各类要素(如点、线、面、文本等&#x…...
opencv练习
1.创建一个 PyQt 应用程序,该应用程序能够: (1)使用 OpenCV 加载一张图像。 (2)在 PyQt 的窗口中显示这张图像。 (3)提供四个按钮(QPushButton)࿱…...
opencv--基础
opencv OpenCV是一个实现数字图像处理和计算机视觉通用算法的开源跨平台库。 链接 opencv中的cv是什么意思 在OpenCV中,"cv" 是 "Computer Vision"(计算机视觉) 的缩写。 opencv的实现语言 opencv的底层实现代码是使…...
基于模板匹配的信用卡号码识别系统
本项目实现了一个基于模板匹配的信用卡号码识别系统。 1. 导入库和设置参数 # -*- coding: utf-8 -*- # 导入工具包 from imutils import contours import numpy as np import argparse import cv2 import myutils import os# 设置参数 ap argparse.ArgumentParser() # 替换…...
Spring Boot中Excel处理完全指南
文章目录 1. Excel处理基础知识1.1 为什么需要在应用中处理Excel文件?1.2 Java中的Excel处理库介绍1.2.1 Apache POI1.2.2 EasyExcel1.2.3 JExcel1.2.4 Apache POI SXSSF1.3 Spring Boot中集成Excel处理2. 在Spring Boot中集成Excel处理库2.1 集成Apache POI2.1.1 添加依赖2.1…...
洛谷P1312 [NOIP 2011 提高组] Mayan 游戏
题目 #算法/进阶搜索 思路: 根据题意,我们可以知道,这题只能枚举,剪枝,因此,我们考虑如何枚举,剪枝. 首先,我们要定义下降函数down(),使得小木块右移时,能够下降到最低处,其次,我们还需要写出判断函数,判断矩阵内是否有小木块没被消除.另外,我们还需要消除函数,将矩阵内三个相连…...
c++ (异常)
1.异常的概念及使用 1.1异常的概念 异常处理机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并做出相应的处理, 异常使得我们能够将问题的检测与解决问题的过程分开,程序的一部分负责检测问题的出现,然后 解决问题的任务传…...
MySQL如何实现行行比较
概述 在MySQL中实现行行比较通常涉及比较同一表或不同表中不同行的数据。以下是几种常见的方法及示例: 1. 自连接(Self-Join) 通过将表与自身连接,比较不同行的数据。 场景示例:比较同一用户相邻订单的金额差异。 …...
springboot2.X创建maven多模块工程
因为需要,所以付出。 好长时间没有搭建新的框架了,最近在搭建微服务的多模块maven工程,现在就将创建的过程记录下来,方便自学的小伙伴找寻资料,少走弯路。好了下面直接开干。 开发工具 :idea 、springboo…...
八股文---Redis(1)
目录 1.Redis-使用场景 1.我看你做的项目中,都用到了redis,你在最近的项目中哪些场景使用了redis呢? 2.缓存三兄弟可以我看我另一个文章(穿透,雪崩,击穿) 3.redis做为缓存,mysql…...
QT聊天项目DAY06
1.从git上同步项目 编译测试,编译通过 Post请求测试 测试成功 2. email is 打印有问题,检查 解析结果是存储在jsonResult中的,修改 3. 客户端实现Post验证码请求 3.1 同步Qt客户端项目 检查QT版本,由于我在公司用的还是QT5.12.9…...
python(八)-数据类型转换
#数据类型转换 #转换为整型int #字符串str--》整数int #纯数字的字符串可以转换,否则会报错 s 2025 n int(s) print(type(s),type(n)) print(n)#浮点数float--》整数int s1 2.23 print(int(s1))#bool-->整数int s2,s3 True,False print(int(s2),int(s3))#转…...
JavaScript 变量命名规范
在编写JavaScript代码时,遵循良好的变量命名规范对于提高代码的可读性、可维护性和协作效率至关重要。一个清晰且一致的命名习惯不仅有助于开发者自己理解代码,也能让其他团队成员更容易上手和维护项目。本文将详细介绍JavaScript中常见的变量命名规则和…...
2025年渗透测试面试题总结-拷打题库05(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 2025年渗透测试面试题总结-拷打题库05 1. 病毒和蠕虫的区别 2. DNS欺骗(DNS Spoofing&…...
【排队论】Probabilistic Forecasts of Bike-Sharing Systems for Journey Planning
Probabilistic Forecasts of Bike-Sharing Systems forJourney Planning abstract 我们研究了对共享单车系统(BSS)车站未来自行车可用性进行预测的问题。这是相关的,以便提出建议,保证用户能够进行旅行的概率足够高。为此&#x…...
Redis 的持久化机制(RDB, AOF)对微服务的数据一致性和恢复性有何影响?如何选择?
Redis 的持久化机制(RDB 和 AOF)对于保证 Redis 服务重启或崩溃后数据的恢复至关重要,这直接影响到依赖 Redis 的微服务的数据一致性和恢复能力。 1. RDB (Redis Database Backup) 机制: 在指定的时间间隔内,将 Redis 在内存中的…...
手撕LLM(四):从源码出发,探索大模型的预训练(pretrain)过程
前面我们基于Minimind项目介绍了大模型的推理、LoRa加载、Moe结构, 大家对大模型的整体结构应该有一个比较清晰的认识;从该篇博客开始,我们通过代码剖析大模型的训练过程,今天的主题是大模型的预训练。 那大模型的预训练是一个什么…...
Linux系统:进程终止的概念与相关接口函数(_exit,exit,atexit)
本节目标 理解进程终止的概念理解退出状态码的概念以及使用方法掌握_exit与exit函数的用法以及区别atexit函数注册终止时执行的函数相关宏 一、进程终止 进程终止(Process Termination)是指操作系统结束一个进程的执行,回收其占用的资源&a…...
keil5 µVision 升级为V5.40.0.0:增加了对STM32CubeMX作为全局生成器的支持,主要有哪些好处?
在Keil5 μVision V5.40.0.0版本中,增加了对STM32CubeMX作为全局生成器的支持,这一更新主要带来了以下三方面的提升: 开发流程整合STM32CubeMX原本就支持生成Keil项目代码,但新版本将这一集成升级为“全局生成器”级别,意味着STM32CubeMX生成的代码能直接成为Keil项目的核…...
C 语言联合与枚举:自定义类型的核心解析
上篇博客中,我们通过学习了解了C语言中一种自定义类型结构体的相关知识,那么该语言中是否还拥有相似的自定义类型呢?这将是我们今天学习的目标。 1.联合体 联合体其实跟结构体类似,也是由一个或多个成员构成,这些成员…...
P1113 杂务-拓扑排序
拓扑排序 P1113 杂务 题目来源-洛谷 题意 求出完成所有任务的最短时间 思路 要求完成所有任务的最短时间,即每个任务尽可能最短,所以再求完成所有任务中的最大值(需要最长时间的任务都完成了才叫全部完成) 问题化解…...
Flink介绍——实时计算核心论文之Kafka论文总结
引入 大数据系统中的数据来源 在开始深入探讨Kafka之前,我们得先搞清楚一个问题:大数据系统中的数据究竟是从哪里来的呢?其实,这些数据大部分都是由各种应用系统或者业务系统产生的“日志”。 比如,互联网公司的广告…...
模拟投资大师思维:AI对冲基金开源项目详解
这里写目录标题 引言项目概述核心功能详解多样化的AI投资智能体灵活的运行模式透明的决策过程 安装和使用教程环境要求安装步骤基本使用方法运行对冲基金模式运行回测模式 应用场景和实际价值教育和研究价值潜在的商业应用与现有解决方案的对比局限性与发展方向 结论 引言 随着…...
DAY4:数据库对象与高级查询深度解析:从视图到多表关联实战
一、数据库对象精要指南 1.1 视图(View)的进阶应用 视图是存储在数据库中的虚拟表,本质是预编译的SQL查询语句。通过视图可以简化复杂查询、实现数据安全隔离、保持业务逻辑一致性。 创建语法示例: CREATE VIEW sales_summary…...
【Matlab】中国东海阴影立体感地图
【Matlab】中国东海阴影立体感地图 【Matlab】中国东海阴影立体感地图 【Matlab】中国东海阴影图立体感画法 以前分享过一次,链接如下: 中国海域地形图 但是以前还是有些小问题,这次修改了。 另外,增加了新的画法: 另…...
python文件类操作:json/ini配置文件、logging日志统计、excel表格数据读写、os操作库
文章目录 一、with open文件操作二、csv表格数据读写三、Excel表格数据读写四、json配置文件读写五、ini配置文件读写六、logging日志统计七、os操作库(文件拼接、创建、判断等) 打开文件使用不同参数有着不同的含义,比如只读、只写、二进制读…...
VSCode安装与环境配置(Mac环境)
20250419 - 概述 大概是非常久之前了,装了VSCode,估计都得21的时候了,电脑上也没更新过。当时安装也直接装上就完事了。这次把版本更新一下,同时记录一下这个安装过程。 安装 mac下安装非常简单,直接从官网下载&am…...
【信息系统项目管理师】高分论文:论信息系统项目的采购管理(“营业工单系统”项目)
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 论文1、规划采购管理2、实施采购3、控制采购论文 2018年1月,我参加了 XX运营商集团公司某省分公司的“营业工单系统”的信息化建设项目,我有幸担任项目经理。该项目投资1000万元人民币,建设工期为12个月。该…...
XCVU13P-2FHGA2104I Xilinx Virtex UltraScale+ FPGA
XCVU13P-2FHGA2104I 是 Xilinx(现为 AMD)Virtex UltraScale™ FPGA 系列中的高端 Premium 器件,基于 16nm FinFET 工艺并采用 3D IC 堆叠硅互连(SSI)技术,提供业内顶级的计算密度和带宽。该芯片集成约 3,…...
@Validated与@Valid的正确使用姿势
验证代码 Validated RestController public class A {PostMappingpublic void test(Min(value 1) Integer count) {} // 校验规则生效 }RestController public class A {PostMappingpublic void test(Validated Min(value 1) Integer count) {} // 校验规则不生效 }RestCont…...
Ubuntu20.04下Docker方案实现多平台SDK编译
0 前言 熟悉嵌入式平台Linux SDK编译流程的小伙伴都知道,假如平台a要求必须在Ubuntu18.04下编译,平台b要求要Ubuntu22.04的环境,那我只有Ubuntu20.04,或者说我的电脑硬件配置最高只能支持Ubuntu20.04怎么办?强行在Ubuntu20.04下编译,编又编不过,换到旧版本我又不愿意,…...
树莓派超全系列教程文档--(34)树莓派配置GPIO
配置GPIO GPIO控制gpio 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 GPIO控制 gpio 通过 gpio 指令,可以在启动时将 GPIO 引脚设置为特定模式和值,而以前需要自定义 dt-blob.bin 文件。每一行都对一组引脚应用相同的设…...
C语言 数组(下)
目录 1.二维数组的创建 2.二位数组的初始化 3.二维数组的使用 4.二维数组在内存中的储存 1.二维数组的创建 1.1二维数组的概念 前面学习的数组被称为一维数组,数组的元素都是内置类型的,如果我们把一维数组做为数组的元 素,这时候就是…...
opencv图像旋转(单点旋转的原理)
首先我们以最简单的一个点的旋转为例子,且以最简单的情况举例,令旋转中心为坐标系中心O(0,0),假设有一点P_{0}(x_{0},y_{0}),P_{0}离旋转中心O的距离为r,OP_{0}与坐标轴x轴的夹角为\…...
针对MCP认证考试中的常见技术难题进行实战分析与解决方案分享
一、身份与权限管理类难题 场景1:Active Directory组策略(GPO)不生效 问题现象:客户端计算机未应用新建的组策略。排查步骤: 检查GPO链接顺序:使用gpresult /r查看策略优先级,确保目标OU的GPO…...
systemctl管理指令
今天我们来继续学习服务管理指令,接下来才是重头戏-systemctl,那么话不多说,直接开始吧. systemctl管理指令 1.基本语法: systemctl [start | stop | restart | status]服务 注:systemctl指令管理的服务在/usr/lib/ systemd/system查看 2.systemctl设置服务的自…...
DataWhale AI春训营 问题汇总
1.没用下载训练集导致出错,爆错如下。 这个时候需要去比赛官网下载对应的初赛训练集 unzip -d /mnt/workspace/sais_third_new_energy_baseline/data /mnt/workspace/sais_third_new_energy_baseline/初赛训练集.zip 在命令行执行这个命令解压 2.没定义测试集 te…...
当算力遇上马拉松:一场科技与肉身的极限碰撞
目录 一、从"肉身苦修"到"科技修仙" 二、马拉松的"新大陆战争" 三、肉身会被算法"优化"吗? 马拉松的下一站是"人机共生"时代 当AI能预测你的马拉松成绩,算法能规划最佳补给方案,智能装备让训练效率翻倍——你还会用传…...
n8n 中文系列教程_02. 自动化平台深度解析:核心优势与场景适配指南
在低代码与AI技术深度融合的今天,n8n作为开源自动化平台正成为开发者提效的新利器。本文深度剖析其四大核心技术优势——极简部署、服务集成、AI工作流与混合开发模式,并基于真实场景测试数据,厘清其在C端高并发、多媒体处理等场景的边界。 一…...