当前位置: 首页 > news >正文

记录--解决前端内存泄漏:问题概览与实用解决方案

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

内存泄漏是前端开发中的一个常见问题,可能导致项目变得缓慢、不稳定甚至崩溃。在本文中,我们将深入探讨在JavaScript、Vue和React项目中可能导致内存泄漏的情况,并提供详细的代码示例,以帮助开发人员更好地理解和解决这些问题。

第一部分:JavaScript中的内存泄漏

1. 未正确清理事件处理器

JavaScript中的事件处理器是内存泄漏的常见来源之一。当你向DOM元素添加事件处理器时,如果不适当地删除这些事件处理器,它们会持有对DOM的引用,妨碍垃圾回收器释放相关的内存。

// 错误的示例:未删除事件处理器
const button = document.querySelector('#myButton');button.addEventListener('click', function() {// 一些操作
});// 忘记删除事件处理器
// button.removeEventListener('click', ??);

解决方法:在不再需要事件处理器时,务必使用removeEventListener来移除它们。

2. 循环引用

循环引用是另一个可能导致内存泄漏的情况。当两个或多个对象相互引用时,即使你不再使用它们,它们也无法被垃圾回收。

// 错误的示例:循环引用
function createObjects() {const obj1 = {};const obj2 = {};obj1.ref = obj2;obj2.ref = obj1;return 'Objects created';
}createObjects();

解决方法:确保在不再需要对象时,将其引用设置为null,打破循环引用。

function createObjects() {const obj1 = {};const obj2 = {};obj1.ref = obj2;obj2.ref = obj1;// 手动打破循环引用obj1.ref = null;obj2.ref = null;return 'Objects created';
}

3. 未释放大型数据结构

在JavaScript项目中,特别是处理大型数据集合时,未释放这些数据结构可能导致内存泄漏。

// 错误的示例:未释放大型数据结构
let largeData = null;function loadLargeData() {largeData = [...Array(1000000).keys()]; // 创建一个包含100万项的数组
}loadLargeData();// 忘记将largeData设置为null

解决方法:当你不再需要大型数据结构时,将其设置为null以释放内存。

function loadLargeData() {largeData = [...Array(1000000).keys()];// 使用largeData后// 不再需要它largeData = null;
}

4. 未正确清理定时器和间隔器

使用setTimeoutsetInterval创建定时器和间隔器时,如果不及时清理它们,它们会持续运行,可能导致内存泄漏。

// 错误的示例:未清理定时器
let timer;function startTimer() {timer = setInterval(function() {// 一些操作}, 1000);
}startTimer();// 忘记清理定时器
// clearInterval(timer);

解决方法:在不再需要定时器或间隔器时,使用clearTimeoutclearInterval来清理它们。

5. 使用闭包保留对外部作用域的引用

在JavaScript中,闭包可以访问其父作用域的变量。如果不小心,闭包可能会保留对外部作用域的引用,导致外部作用域的变量无法被垃圾回收。

// 错误的示例:使用闭包保留外部作用域的引用
function createClosure() {const data = '敏感数据';return function() {console.log(data);};
}const closure = createClosure();// closure保留了对data的引用,即使不再需要data

解决方法:在不再需要闭包时,确保解除对外部作用域的引用。

function createClosure() {const data = '敏感数据';return function() {console.log(data);};
}let closure = createClosure();// 在不再需要闭包时,解除引用
closure = null;

这些是JavaScript中可能导致内存泄漏的常见情况。现在让我们深入了解Vue和React中的内存泄漏问题。

第二部分:Vue中的内存泄漏

1. 未取消事件监听

在Vue中,当你使用$on方法添加事件监听器时,如果在组件销毁前未取消监听,可能会导致内存泄漏。

<template><div><button @click="startListening">Start Listening</button></div>
</template><script>
export default {methods: {startListening() {this.$on('custom-event', this.handleCustomEvent);},handleCustomEvent() {// 处理自定义事件},beforeDestroy() {// 错误的示例:未取消事件监听// this.$off('custom-event', this.handleCustomEvent);}}
};
</script>

在上述示例中,我们添加了一个自定义事件监听器,但在组件销毁前未取消监听。

解决方法:确保在组件销毁前使用$off来取消事件监听。

<template><div><button @click="startListening">Start Listening</button></div>
</template><script>
export default{methods: {startListening() {this.$on('custom-event', this.handleCustomEvent);},handleCustomEvent() {// 处理自定义事件},beforeDestroy() {// 取消事件监听this.$off('custom-event', this.handleCustomEvent);}}
};
</script>

2. 未正确清理定时器

在Vue中,使用setIntervalsetTimeout创建定时器时,需要注意清理定时器,否则它们将在组件销毁后继续运行。

<template><div><button @click="startTimer">Start Timer</button></div>
</template><script>
export default {data() {return {message: 'Hello, Vue!'};},methods: {startTimer() {this.timer = setInterval(() => {// 一些操作}, 1000);},beforeDestroy() {// 错误的示例:未清理定时器// clearInterval(this.timer);}}
};
</script>

在上述示例中,我们创建了一个定时器,但在组件销毁前没有清理它。

解决方法:在beforeDestroy钩子中清理定时器。

<template><div><button @click="startTimer">Start Timer</button></div>
</template><script>
export default {data() {return {message: 'Hello, Vue!'};},methods: {startTimer() {this.timer = setInterval(() => {// 一些操作}, 1000);},beforeDestroy() {// 清理定时器clearInterval(this.timer);}}
};
</script>

3. 未销毁Vue的子组件

在Vue中,如果子组件未正确销毁,可能会导致内存泄漏。这经常发生在使用动态组件或路由时。

<template><div><button @click="toggleComponent">Toggle Component</button><keep-alive><my-component v-if="showComponent" /></keep-alive></div>
</template><script>
import MyComponent from './MyComponent.vue';export default {data() {return {showComponent: false};},components: {MyComponent},methods: {toggleComponent() {this.showComponent = !this.showComponent;}}
};
</script>

在上述示例中,我们使用<keep-alive>包裹了<my-component>,以保持其状态,但如果在组件销毁前未将其销毁,可能会导致内存泄漏。

解决方法:确保在不再需要组件时,调用$destroy方法,以手动销毁Vue子组件。

<template><div><button @click="toggleComponent">Toggle Component</button><keep-alive><my-component v-if="showComponent" ref="myComponent" /></keep-alive></div>
</template><script>
import MyComponent from './MyComponent.vue';export default {data() {return {showComponent: false};},components: {MyComponent},methods: {toggleComponent() {if (this.showComponent) {// 销毁组件this.$refs.myComponent.$destroy();}this.showComponent = !this.showComponent;}}
};
</script>

4. 未取消异步操作或请求

在Vue中,如果组件中存在未取消的异步操作或HTTP请求,这些操作可能会保留对组件的引用,即使组件已销毁,也会导致内存泄漏。

<template><div><p>{{ message }}</p></div>
</template><script>
export default {data() {return {message: 'Hello, Vue!'};},created() {this.fetchData(); // 发起HTTP请求},beforeDestroy() {// 错误的示例:未取消HTTP请求// this.cancelHttpRequest();},methods: {fetchData() {this.$http.get('/api/data').then(response => {this.message = response.data;});},cancelHttpRequest() {// 取消HTTP请求逻辑}}
};
</script>

在上述示例中,我们发起了一个HTTP请求,但在组件销毁前未取消它。

解决方法:确保在组件销毁前取消异步操作、清理未完成的请求或使用适当的取消机制。

<template><div><p>{{ message }}</p></div>
</template><script>
export default {data() {return {message: 'Hello, Vue!'};},created() {this.fetchData(); // 发起HTTP请求},beforeDestroy() {// 取消HTTP请求this.cancelHttpRequest();},methods: {fetchData() {this.$http.get('/api/data').then(response => {this.message = response.data;});},cancelHttpRequest() {// 取消HTTP请求逻辑// 注意:需要实现取消HTTP请求的逻辑}}
};
</script>

5. 长时间保持全局状态

在Vue应用中,如果全局状态(例如使用Vuex管理的状态)被长时间保持,即使不再需要,也可能导致内存泄漏。

// 错误的示例:长时间保持全局状态
const store = new Vuex.Store({state: {// 大型全局状态},mutations: {// 修改全局状态}
});// 在整个应用生命周期中保持了store的引用
解决方法:在不再需要全局状态时,可以销毁它,或者在适当的时候清理它以释放内存。
// 正确的示例:销毁全局状态
const store = new Vuex.Store({state: {// 大型全局状态},mutations: {// 修改全局状态}
});// 在不再需要全局状态时,销毁它
store.dispatch('logout'); // 示例:登出操作

这些是Vue中可能导致内存泄漏的一些情况。接下来,我们将讨论React中的内存泄漏问题。

第三部分:React中的内存泄漏

1. 使用第三方库或插件

在React项目中使用第三方库或插件时,如果这些库不正确地管理自己的资源或事件监听器,可能会导致内存泄漏。这些库可能会在组件被销毁时保留对组件的引用。

import React, { Component } from 'react';
import ThirdPartyLibrary from 'third-party-library';class MyComponent extends Component {componentDidMount() {this.thirdPartyInstance = new ThirdPartyLibrary();this.thirdPartyInstance.init();}componentWillUnmount() {// 错误的示例:未正确销毁第三方库的实例// this.thirdPartyInstance.destroy();}render() {return <div>My Component</div>;}
}

在上述示例中,我们在componentDidMount中创建了一个第三方库的实例,但在componentWillUnmount中未正确销毁它。

解决方法:当使用第三方库或插件时,请查看其文档,了解如何正确销毁和清理资源。确保在组件卸载时调用所需的销毁方法。

import React, { Component } from 'react';
import ThirdPartyLibrary from 'third-party-library';class MyComponent extends Component {componentDidMount() {this.thirdPartyInstance = new ThirdPartyLibrary();this.thirdPartyInstance.init();}componentWillUnmount() {// 正确的示例:销毁第三方库的实例this.thirdPartyInstance.destroy();}render() {return <div>My Component</div>;}
}

2. 使用React Portals(续)

在React中,如果使用React Portals来渲染内容到其他DOM树的部分,需要确保在组件销毁时正确卸载Portal,以免内存泄漏。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';class PortalComponent extends Component {constructor(props) {super(props);this.portalContainer = document.createElement('div');}componentDidMount() {// 错误的示例:未卸载Portaldocument.body.appendChild(this.portalContainer);ReactDOM.createPortal(<div>Portal Content</div>, this.portalContainer);}componentWillUnmount() {// 错误的示例:未卸载Portaldocument.body.removeChild(this.portalContainer);}render() {return null;}
}

在上述示例中,我们创建了一个Portal,并将其附加到了DOM中,但未在组件销毁时正确卸载它。

解决方法:确保在组件卸载前正确卸载Portal。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';class PortalComponent extends Component {constructor(props) {super(props);this.portalContainer = document.createElement('div');}componentDidMount() {document.body.appendChild(this.portalContainer);}componentWillUnmount() {// 正确的示例:卸载Portaldocument.body.removeChild(this.portalContainer);}render() {// 在组件卸载后,Portal被正确卸载return ReactDOM.createPortal(<div>Portal Content</div>, this.portalContainer);}
}

3. 长时间保持Context

在React中,如果使用React Context来管理全局状态,并且长时间保持了对Context的引用,可能会导致内存泄漏。

// 错误的示例:长时间保持Context引用
const MyContext = React.createContext();function MyApp() {const contextValue = useContext(MyContext);// 长时间保持对Context的引用// 导致相关组件无法被垃圾回收
}

解决方法:在不再需要Context时,确保取消对它的引用,以便相关组件可以被垃圾回收。

// 正确的示例:取消Context引用
const MyContext = React.createContext();function MyApp() {const contextValue = useContext(MyContext);// 在不再需要Context时,解除引用// contextValue = null;
}

这些是React中可能导致内存泄漏的一些情况。通过了解这些潜在问题以及如何解决它们,你可以更好地编写稳定和高性能的React项目。

4、长时间保持未卸载的组件

在React中,如果长时间保持未卸载的组件实例,可能会导致内存泄漏。这通常发生在路由导航或动态组件加载的情况下。

import React, { Component } from 'react';
import { Route } from 'react-router-dom';class App extends Component {render() {return (<div>{/* 错误的示例:长时间保持未卸载的组件 */}<Route path="/page1" component={Page1} /><Route path="/page2" component={Page2} /></div>);}
}

在上述示例中,如果用户在/page1/page2之间切换,组件Page1Page2的实例将一直存在,即使不再需要。

解决方法:确保在不再需要的情况下卸载组件。使用React Router等路由库时,React会自动卸载不再匹配的组件。

import React, { Component } from 'react';
import { Route } from 'react-router-dom';class App extends Component {render() {return (<div>{/* 正确的示例:React会自动卸载不匹配的组件 */}<Route path="/page1" component={Page1} /><Route path="/page2" component={Page2} /></div>);}
}

5. 遗留的事件监听器

在React中,使用类组件时,未正确清理事件监听器可能会导致内存泄漏。

import React, { Component } from 'react';class MyComponent extends Component {componentDidMount() {window.addEventListener('resize', this.handleResize);}componentWillUnmount() {// 错误的示例:未移除事件监听器// window.removeEventListener('resize', this.handleResize);}handleResize() {// 处理窗口大小调整事件}render() {return <div>My Component</div>;}
}

在上述示例中,我们添加了窗口大小调整事件的监听器,但在组件卸载前未正确移除它。

解决方法:确保在组件卸载时移除所有事件监听器。

import React, { Component } from 'react';class MyComponent extends Component {componentDidMount() {window.addEventListener('resize', this.handleResize);}componentWillUnmount() {// 正确的示例:移除事件监听器window.removeEventListener('resize', this.handleResize);}handleResize() {// 处理窗口大小调整事件}render() {return <div>My Component</div>;}
}

总结

内存泄漏是前端开发中一个常见但容易忽视的问题。在JavaScript、Vue和React项目中,不正确的内存管理可能导致性能下降、项目不稳定甚至崩溃。为了避免内存泄漏,我们应谨慎处理事件处理器、定时器、循环引用和引用非受控组件等问题,并确保在组件销毁前正确清理资源。使用开发者工具和性能分析工具来监测和诊断潜在的内存泄漏问题,以确保你的前端项目在长时间运行时表现出色。通过正确处理内存管理问题,你可以提高项目的性能、稳定性和用户体验。

本文转载于:

https://juejin.cn/post/7272013476222763060

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

相关文章:

记录--解决前端内存泄漏:问题概览与实用解决方案

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 内存泄漏是前端开发中的一个常见问题&#xff0c;可能导致项目变得缓慢、不稳定甚至崩溃。在本文中&#xff0c;我们将深入探讨在JavaScript、Vue和React项目中可能导致内存泄漏的情况&#xff0c;并提…...

IP初学习

1.IP报文 首部长度指的是报头长度&#xff0c;用于分离报头和有效载荷 2.网段划分 IP地址 目标网络 目标主机 3.例子 4.特殊的IP地址 5.真正的网络环境 6.调制解调器 “猫”&#xff0c;学名叫宽带无线猫 7.NAT 源IP在内网环境不断被替换 8.私有IP不能出现在公网上 因…...

live5555 testProgs目录

文章目录 测试testProgs视频流直播流注意&#xff1a; 测试 testProgs 当涉及到许多示例程序时&#xff0c;解释每一个都可能会变得非常冗长。然而&#xff0c;我可以为你提供一些关键示例程序的简要解释&#xff0c;以帮助你了解每个示例的用途和功能&#xff1a; testOnDem…...

yolov5模型s,l,m,x的区别

yolov5s 是什么&#xff1f;yolov5系列最小的模型&#xff0c;s是small。 适合什么情况下使用&#xff1f;适合在计算资源有限的设备上使用。如移动设备或边缘设备。 速度和准确率&#xff1a;速度最快&#xff0c;准确率最低。 输入分辨率&#xff1a;通常为640x640 # Param…...

Springboot 实践(13)spring boot 整合RabbitMq

前文讲解了RabbitMQ的下载和安装&#xff0c;此文讲解springboot整合RabbitMq实现消息的发送和消费。 1、创建web project项目&#xff0c;名称为“SpringbootAction-RabbitMQ” 2、修改pom.xml文件&#xff0c;添加amqp使用jar包 <!-- RabbitMQ --> <dependency&g…...

YoloV8改进策略:轻量级Slim Neck打造极致的YoloV8

文章目录 摘要Yolov8官方结果源码改进方法测试结果总结摘要 论文链接:https://arxiv.org/ftp/arxiv/papers/2206/2206.02424.pdf 作者研究了增强 CNN 学习能力的通用方法,例如 DensNet、VoVNet 和 CSPNet,然后根据这些方法的理论设计了 Slim-Neck 结构。 使用轻量级卷积…...

使用java代码给Excel加水印,代码全,进阶版

以下代码&#xff0c;亲测可以跑通 1、上一篇博客用了Apache POI库3.8的版本的形式对Excel加了水印&#xff0c;但是最近主线版本用了4.1.2的形式&#xff0c;由于为了保持版本的兼容性&#xff0c;下面有开发了Apache POI的4.1.2的版本号的方案。 pom文件为&#xff1a; <d…...

day37:网编day4,多点通信和并发服务器

一、广播接收方&#xff1a; #include <myhead.h>#define ERR_MSG(msg) do{\ fprintf(stderr,"__%d__\n",__LINE__);\ perror(msg);\ }while(0)#define BRD_IP "192.168.114.255" #define BRD_PORT 8888int main(int argc, const char *argv[]) {//…...

STM32 硬件IIC 控制OLED I2C卡死问题

1. STM32L151C8T6 硬件IIC 控制OLED 屏&#xff0c;OLED 驱动IC CH1116G, 查阅OLED 数据手册 2. STM32 硬件IIC 初始化&#xff0c;用的标准库&#xff0c;固件库 // stm32l151c8t6 as master, oled control ic (CH1116G) as slave, and communicate by master iic2 void STM3…...

Redis图文指南

1、什么是 Redis&#xff1f; Redis&#xff08;REmote DIctionary Service&#xff09;是一个开源的键值对数据库服务器。 Redis 更准确的描述是一个数据结构服务器。Redis 的这种特殊性质让它在开发人员中很受欢迎。 Redis不是通过迭代或者排序方式处理数据&#xff0c;而是…...

C++17 std::string_view介绍与使用

std::string_view介绍 std::string_view是C17增加的新内容。它是一个轻量级的、只读的字符串视图&#xff0c;可以用来表示一个字符串或字符串的一部分。std::string_view可以提高代码的可读性、可维护性和性能。 std::string_view与std::string的主要区别在于&#xff0c;st…...

写得了代码,焊得了板!嵌入式开发工程师必修之代码管理方案(下)

目录 极狐GitLab嵌入式开发场景解决方案 3.1 高可用部署与灾备 3.2 组织管理 3.3 分支策略 3.4 分支保护 3.5 推送规则 3.6 代码评审 3.7 数据保护 3.8 其他相关 本文来自 武让 极狐GitLab 高级解决方案架构师 &#x1f4a1; 前两篇文章&#xff0c;作者介绍了嵌入式开…...

Matlab论文插图绘制模板第110期—水平双向柱状图

在之前的文章中&#xff0c;分享了很多Matlab柱状图的绘制模板&#xff1a; 进一步&#xff0c;再来看一种特殊的柱状图&#xff1a;水平双向柱状图。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自行下…...

【广州华锐互动】VR全景工厂虚拟导览,虚拟现实技术提升企业数字化信息管理水平

随着工业4.0的到来&#xff0c;VR工厂全景制作成为了越来越多工业企业的选择。传统的工厂管理方式往往存在诸多问题&#xff0c;如信息不对称、安全隐患等。为了解决这些问题&#xff0c;VR工厂全景制作应运而生&#xff0c;它通过结合虚拟现实现实技术和数据采集技术&#xff…...

idea 创建mybatis xml文件时找不到

1、File >Settings 如图 &#xff1a; 2、添加模板&#xff1a;如下图 3、添加xml模板 如下图&#xff1a; 模板内容&#xff1a; <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//E…...

Python钢筋混凝土结构计算.pdf-混凝土构件计算

计算原理&#xff1a; 代码实现&#xff1a; #钢筋混凝土参数 def c_hrb(): global fcuk,HRB,Ec,fc,ft,ftk,Es,fy,fyp,fyk global a1,epsilon_cu fcukEcfcftftk0.0 HRBEsfyfypfyk0.0 #矩形应力图系数a1&#xff0c;C50以下为1.0 a11.0 #正截面混凝土极限压应变epsilon_cu&#…...

mysql5.7-基于docker-compose搭建主从同步

一、环境信息 系统版本&#xff1a;CentOS Linux release 7.9.2009 (Core) cat /etc/centos-release Docker版本&#xff1a;Docker version 20.10.6, build 370c289 docker --version Docker-compose版本&#xff1a;Docker Compose version v2.10.2 docker-compose --versio…...

【USRP】调制解调系列5:16QAM、32QAM、64QAM、256QAM、1024QAM、基于labview的实现

QAM 正交振幅键控是一种将两种调幅信号&#xff08;2ASK和2PSK&#xff09;汇合到一个信道的方法&#xff0c;因此会双倍扩展有效带宽&#xff0c;正交调幅被用于脉冲调幅。正交调幅信号有两个相同频率的载波&#xff0c;但是相位相差90度&#xff08;四分之一周期&#xff0c…...

Odoo|5分钟创建自定义的业务系统唯一序列号

在业务操作中&#xff0c;经常会遇到需要生成全局唯一序列号数据的情况&#xff0c;比如订单号、报价单号等。为了确保数据的唯一性和准确性&#xff0c;通常我们会使用Redis或其他分布式锁机制来实现。然而&#xff0c;很多人可能不知道&#xff0c;odoo框架本身提供了一个原生…...

mysql索引为什么提高查询速度(底层原理)

一、索引原理图 二、索引数据存储到硬盘而不是内存&#xff1f; 硬盘内存 成本低成本高 容量大容量小 读写速度一般读取速度快 断电后数据永久存储断电后数据清空 三、硬盘数据为什么要读取到内存&#xff1f;为啥不直接…...

算法通关村——位运算在查找重复元素中的妙用

用4KB内存寻找重复元素 给定一个数组&#xff0c;包含从1到N的整数&#xff0c;N最大为32000&#xff0c;数组可能还有重复值&#xff0c;且N的取值不定&#xff0c;若只有4KB的内存可用&#xff0c;该如何打印数组中所有重复元素。 如果不要求使用4KB&#xff0c;最简单就是…...

使用环境中的视觉地标和扩展卡尔曼滤波器定位移动机器人研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

【python基础知识】5.for循环和while循环

文章目录 前言for...in...循环语句for循环&#xff1a;空房间for循环&#xff1a;一群排队办业务的人range()函数for循环&#xff1a;办事流程 while循环while循环&#xff1a;放行条件while循环&#xff1a;办事流程 两种循环对比 前言 上一关&#xff0c;我们学习了两种新的…...

STM32CUBEMX_创建时间片轮询架构的软件框架

STM32CUBEMX_创建时间片轮询架构的软件框架 说明&#xff1a; 1、这种架构避免在更新STM32CUBEMX配置后把用户代码清除掉 2、利用这种时间片的架构可以使得代码架构清晰易于维护 创建步骤&#xff1a; 1、使用STM32CUBEMX创建基础工程 2、新建用户代码目录 3、构建基础的代码框…...

vue 插槽Slots

vue插槽官网 <button class"fancy-btn"><slot></slot> <!-- 插槽出口 --> </button><slot> 元素是一个插槽出口 (slot outlet)&#xff0c;标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。 // 定义一个Child.vue…...

论文阅读《Nougat:Neural Optical Understanding for Academic Documents》

摘要 科学知识主要存储在书籍和科学期刊中&#xff0c;通常以PDF的形式。然而PDF格式会导致语义信息的损失&#xff0c;特别是对于数学表达式。我们提出了Nougat&#xff0c;这是一种视觉transformer模型&#xff0c;它执行OCR任务&#xff0c;用于将科学文档处理成标记语言&a…...

较难的换根dp:P6213 「SWTR-04」Collecting Coins

传送门 前题提要:感觉这道换根dp可以说是集中了换根dp的所有较高难度的操作和思想,以及较高的一些实现细节,可以说能够完全写出这道题才叫真正理解了换根dp,非常值得一做. 首先读完题意,不难发现这道题有很多限制.点的访问次数限制,必须访问某一个点,想要获得最大的贡献,没有…...

Springboot - 15.二级分布式缓存集成-Caffeine

&#x1f440;中文文档 Caffeine &#x1f440;使用Caffeine &#xff08;本地缓存&#xff09; 当与Spring Boot结合使用时&#xff0c;Caffeine提供了一个直观且功能强大的二级缓存解决方案。Spring Boot的缓存抽象使得整合Caffeine变得相当简单。以下是如何在Spring Boot…...

二叉树的介绍及二叉树的链式结构的实现(C语言版)

前言 二叉树是一种特殊的树&#xff0c;它最大的度为2&#xff0c;每个节点至多只有两个子树。它是一种基础的数据结构&#xff0c;后面很多重要的数据结构都是依靠它来进行实现的。了解并且掌握它是很重要的。 目录 1.二叉树的介绍 1.1概念 1.2现实中的二叉树 1.3特殊的二叉…...

不同写法的性能差异

“ 达到相同目的,可以有多种写法,每种写法有性能、可读性方面的区别,本文旨在探讨不同写法之间的性能差异 len(str) vs str "" 本部分参考自: [问个 Go 问题&#xff0c;字符串 len 0 和 字符串 "" &#xff0c;有啥区别&#xff1f;](https://segmentf…...