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

Webpack: 并行构建

概述

受限于 Node.js 的单线程架构,原生 Webpack 对所有资源文件做的所有解析、转译、合并操作本质上都是在同一个线程内串行执行,CPU 利用率极低,因此,理所当然地,社区出现了一些以多进程方式运行 Webpack,或 Webpack 构建过程某部分工作的方案(从而提升单位时间利用率),例如:

  • HappyPack:多进程方式运行资源加载(Loader)逻辑;
  • Thread-loader:Webpack 官方出品,同样以多进程方式运行资源加载逻辑;
  • Parallel-Webpack:多进程方式运行多个 Webpack 构建实例;
  • TerserWebpackPlugin:支持多进程方式执行代码压缩、uglify 功能。

这些方案的核心设计都很类似:针对某种计算任务创建子进程,之后将运行所需参数通过 IPC 传递到子进程并启动计算操作,计算完毕后子进程再将结果通过 IPC 传递回主进程,寄宿在主进程的组件实例,再将结果提交给 Webpack。

使用 HappyPack

HappyPack 能够将耗时的文件加载(Loader)操作拆散到多个子进程中并发执行,子进程执行完毕后再将结果合并回传到 Webpack 进程,从而提升构建性能。不过,HappyPack 的用法稍微有点难以理解,需要同时:

  • 使用 happypack/loader 代替原本的 Loader 序列;
  • 使用 HappyPack 插件注入代理执行 Loader 序列的逻辑。

基本用法:

  1. 安装依赖:

    yarn add -D happypack
    
  2. 将原有 loader 配置替换为 happypack/loader,如:

    module.exports = {// ...module: {rules: [{test: /\.js$/,use: "happypack/loader",// 原始配置如:// use: [//  {//      loader: 'babel-loader',//      options: {//          presets: ['@babel/preset-env']//      }//  },//  'eslint-loader'// ]},],},
    };
    
  3. 创建 happypack 插件实例,并将原有 loader 配置迁移到插件中,完整配置:

    const HappyPack = require("happypack");module.exports = {// ...module: {rules: [{test: /\.js$/,use: "happypack/loader",// 原始配置如:// use: [//  {//      loader: 'babel-loader',//      options: {//          presets: ['@babel/preset-env']//      }//  },//  'eslint-loader'// ]},],},plugins: [new HappyPack({// 将原本定义在 `module.rules.use` 中的 Loader 配置迁移到 HappyPack 实例中loaders: [{loader: "babel-loader",option: {presets: ["@babel/preset-env"],},},"eslint-loader",],}),],
    };
    

配置完毕后,再次启动 npx webpack 命令,即可使用 HappyPack 的多进程能力提升构建性能。以 Three.js 为例,该项目包含 362 份 JS 文件,合计约 3w 行代码:
在这里插入图片描述
开启 HappyPack 前,构建耗时大约为 11000ms 到 18000ms 之间,开启后耗时降低到 5800ms 到 8000ms 之间,提升约47%。

上述示例仅演示了使用 HappyPack 加载单一资源类型的场景,实践中我们还可以创建多个 HappyPack 插件实例,来加载多种资源类型 —— 只需要用 id 参数做好 Loader 与 Plugin 实例的关联即可,例如:

const HappyPack = require('happypack');module.exports = {// ...module: {rules: [{test: /\.js?$/,// 使用 `id` 参数标识该 Loader 对应的 HappyPack 插件示例use: 'happypack/loader?id=js'},{test: /\.less$/,use: 'happypack/loader?id=styles'},]},plugins: [new HappyPack({// 注意这里要明确提供 id 属性id: 'js',loaders: ['babel-loader', 'eslint-loader']}),new HappyPack({id: 'styles',loaders: ['style-loader', 'css-loader', 'less-loader']})]
};

这里的重点是:

  • jsless 资源都使用 happypack/loader 作为唯一加载器,并分别赋予 id = 'js' | 'styles' 参数;
  • 创建了两个 HappyPack 插件实例并分别配置 id 属性,以及用于处理 js 与 css 的 loaders 数组;
  • 启动后,happypack/loaderHappyPack 插件实例将通过 id 值产生关联,以此实现对不同资源执行不同 Loader 序列。

上面这种多实例模式虽然能应对多种类型资源的加载需求,但默认情况下,HappyPack 插件实例 自行管理 自身所消费的进程,需要导致频繁创建、销毁进程实例 —— 这是非常昂贵的操作,反而会带来新的性能损耗。

为此,HappyPack 提供了一套简单易用的共享进程池接口,只需要创建 HappyPack.ThreadPool 对象,并通过 size 参数限定进程总量,之后将该例配置到各个 HappyPack 插件的 threadPool 属性上即可,例如:

const os = require('os')
const HappyPack = require('happypack');
const happyThreadPool = HappyPack.ThreadPool({// 设置进程池大小size: os.cpus().length - 1
});module.exports = {// ...plugins: [new HappyPack({id: 'js',// 设置共享进程池threadPool: happyThreadPool,loaders: ['babel-loader', 'eslint-loader']}),new HappyPack({id: 'styles',threadPool: happyThreadPool,loaders: ['style-loader', 'css-loader', 'less-loader']})]
};

使用 HappyPack.ThreadPool 接口后,HappyPack 会预先创建好一组工作进程,所有插件实例的资源转译任务会通过内置的 HappyThread 对象转发到空闲进程做处理,避免频繁创建、销毁进程。

最后,我们再来看看 HappyPack 的执行流程:

核心步骤:

  • happlypack/loader 接受到转译请求后,从 Webpack 配置中读取出相应 HappyPack 插件实例;
  • 调用插件实例的 compile 方法,创建 HappyThread 实例(或从 HappyThreadPool 取出空闲实例);
  • HappyThread 内部调用 child_process.fork 创建子进程,并执行HappyWorkerChannel 文件;
  • HappyWorkerChannel 创建 HappyWorker ,开始执行 Loader 转译逻辑;

中间流程辗转了几层,最终由 HappyWorker 类重新实现了一套与 Webpack Loader 相似的转译逻辑,代码复杂度较高,大家稍作了解即可。

HappyPack 虽然确实能有效提升 Webpack 的打包构建速度,但它有一些明显的缺点:

  • 作者已经明确表示不会继续维护,扩展性与稳定性缺乏保障,随着 Webpack 本身的发展迭代,可以预见总有一天 HappyPack 无法完全兼容 Webpack;
  • HappyPack 底层以自己的方式重新实现了加载器逻辑,源码与使用方法都不如 Thread-loader 清爽简单,而且会导致一些意想不到的兼容性问题,如 awesome-typescript-loader
  • HappyPack 主要作用于文件加载阶段,并不会影响后续的产物生成、合并、优化等功能,性能收益有限。

使用 Thread-loader

Thread-loader 与 HappyPack 功能类似,都是以多进程方式加载文件的 Webpack 组件,两者主要区别:

  1. Thread-loader 由 Webpack 官方提供,目前还处于持续迭代维护状态,理论上更可靠;
  2. Thread-loader 只提供了一个 Loader 组件,用法简单很多;
  3. HappyPack 启动后会创建一套 Mock 上下文环境 —— 包含 emitFile 等接口,并传递给 Loader,因此对大多数 Loader 来说,运行在 HappyPack 与运行在 Webpack 原生环境相比没有太大差异;但 Thread-loader 并不具备这一特性,所以要求 Loader 内不能调用特定上下文接口,兼容性较差。

说一千道一万,先来看看基本用法:

  1. 安装依赖:

    yarn add -D thread-loader
    
  2. 将 Thread-loader 放在 use 数组首位,确保最先运行,如:

    module.exports = {module: {rules: [{test: /\.js$/,use: ["thread-loader", "babel-loader", "eslint-loader"],},],},
    };
    

启动后,Thread-loader 会在加载文件时创建新的进程,在子进程中使用 loader-runner 库运行 thread-loader 之后的 Loader 组件,执行完毕后再将结果回传到 Webpack 主进程,从而实现性能更佳的文件加载转译效果。

以 Three.js 为例,使用 Thread-loader 前,构建耗时大约为 11000ms 到 18000ms 之间,开启后耗时降低到 8000ms 左右,提升约37%。

此外,Thread-loader 还提供了一系列用于控制并发逻辑的配置项,包括:

  • workers:子进程总数,默认值为 require('os').cpus() - 1
  • workerParallelJobs:单个进程中并发执行的任务数;
  • poolTimeout:子进程如果一直保持空闲状态,超过这个时间后会被关闭;
  • poolRespawn:是否允许在子进程关闭后重新创建新的子进程,一般设置为 false 即可;
  • workerNodeArgs:用于设置启动子进程时,额外附加的参数。

使用方法跟其它 Loader 一样,都是通过 use.options 属性传递,如:

module.exports = {module: {rules: [{test: /\.js$/,use: [{loader: "thread-loader",options: {workers: 2,workerParallelJobs: 50,// ...},},"babel-loader","eslint-loader",],},],},
};

不过,Thread-loader 也同样面临着频繁的子进程创建、销毁所带来的性能问题,为此,Thread-loader 提供了 warmup 接口用于前置创建若干工作子进程,降低构建时延,用法:

const threadLoader = require("thread-loader");threadLoader.warmup({// 可传入上述 thread-loader 参数workers: 2,workerParallelJobs: 50,},[// 子进程中需要预加载的 node 模块"babel-loader","babel-preset-es2015","sass-loader",]
);

执行效果与 HappyPack.ThreadPool 相似,此处不再赘述。

与 HappyPack 相比,Thread-loader 有两个突出的优点,一是产自 Webpack 官方团队,后续有长期维护计划,稳定性有保障;二是用法更简单。但它不可避免的也存在一些问题:

  • 在 Thread-loader 中运行的 Loader 不能调用 emitAsset 等接口,这会导致 style-loader 这一类加载器无法正常工作,解决方案是将这类组件放置在 thread-loader 之前,如 ['style-loader', 'thread-loader', 'css-loader']
  • Loader 中不能获取 compilationcompiler 等实例对象,也无法获取 Webpack 配置。

这会导致一些 Loader 无法与 Thread-loader 共同使用,大家需要仔细加以甄别、测试。

使用 Parallel-Webpack

Thread-loader、HappyPack 这类组件所提供的并行能力都仅作用于文件加载过程,对后续 AST 解析、依赖收集、打包、优化代码等过程均没有影响,理论收益还是比较有限的。对此,社区还提供了另一种并行度更高,以多个独立进程运行 Webpack 实例的方案 —— Parallel-Webpack,基本用法:

  1. 安装依赖:

    yarn add -D parallel-webpack
    
  2. webpack.config.js 配置文件中导出多个 Webpack 配置对象,如:

    module.exports = [{entry: 'pageA.js',output: {path: './dist',filename: 'pageA.js'}
    }, {entry: 'pageB.js',output: {path: './dist',filename: 'pageB.js'}
    }];
    
  3. 执行 npx parallel-webpack 命令。

  • Parallel-Webpack 会为配置文件中导出的每个 Webpack 配置对象启动一个独立的构建进程,从而实现并行编译的效果。底层原理很简单,基本上就是在 Webpack 上套了个壳:

    • 根据传入的配置项数量,调用 worker-farm 创建复数个工作进程;
    • 工作进程内调用 Webpack 执行构建;
    • 工作进程执行完毕后,调用 node-ipc 向主进程发送结束信号。
  • 这种方式在需要同时执行多份配置的编译时特别有效,但若配置文件本身只是导出了单个配置对象则意义不大。

  • 为了更好地支持多种配置的编译,Parallel-Webpack 还提供了 createVariants 函数,用于根据给定变量组合,生成多份 Webpack 配置对象,如:

    const createVariants = require('parallel-webpack').createVariants
    const webpack = require('webpack')const baseOptions = {entry: './index.js'
    }// 配置变量组合
    // 属性名为 webpack 配置属性;属性值为可选的变量
    // 下述变量组合将最终产生 2*2*4 = 16 种形态的配置对象
    const variants = {minified: [true, false],debug: [true, false],target: ['commonjs2', 'var', 'umd', 'amd']
    }function createConfig (options) {const plugins = [new webpack.DefinePlugin({DEBUG: JSON.stringify(JSON.parse(options.debug))})]return {output: {path: './dist/',filename: 'MyLib.' +options.target +(options.minified ? '.min' : '') +(options.debug ? '.debug' : '') +'.js'},plugins: plugins}
    }module.exports = createVariants(baseOptions, variants, createConfig)
    
  • 上述示例使用 createVariants 函数,根据 variants 变量搭配出 16 种不同的 minifieddebugtarget 组合,最终生成如下产物:

    [WEBPACK] Building 16 targets in parallel
    [WEBPACK] Started building MyLib.umd.js
    [WEBPACK] Started building MyLib.umd.min.js
    [WEBPACK] Started building MyLib.umd.debug.js
    [WEBPACK] Started building MyLib.umd.min.debug.js[WEBPACK] Started building MyLib.amd.js
    [WEBPACK] Started building MyLib.amd.min.js
    [WEBPACK] Started building MyLib.amd.debug.js
    [WEBPACK] Started building MyLib.amd.min.debug.js[WEBPACK] Started building MyLib.commonjs2.js
    [WEBPACK] Started building MyLib.commonjs2.min.js
    [WEBPACK] Started building MyLib.commonjs2.debug.js
    [WEBPACK] Started building MyLib.commonjs2.min.debug.js[WEBPACK] Started building MyLib.var.js
    [WEBPACK] Started building MyLib.var.min.js
    [WEBPACK] Started building MyLib.var.debug.js
    [WEBPACK] Started building MyLib.var.min.debug.js
    
  • 虽然,parallel-webpack 相对于 Thread-loader、HappyPack 有更高的并行度,但进程实例之间并没有做任何形式的通讯,这可能导致相同的工作在不同进程 —— 或者说不同 CPU 核上被重复执行。

  • 例如需要对同一份代码同时打包出压缩和非压缩版本时,在 parallel-webpack 方案下,前置的资源加载、依赖解析、AST 分析等操作会被重复执行,仅仅最终阶段生成代码时有所差异。

  • 这种技术实现,对单 entry 的项目没有任何收益,只会徒增进程创建成本;但特别适合 MPA 等多 entry 场景,或者需要同时编译出 esm、umd、amd 等多种产物形态的类库场景。

并行压缩

Webpack4 默认使用 Uglify-js 实现代码压缩,Webpack5 之后则升级为 Terser —— 一种性能与兼容性更好的 JavaScript 代码压缩混淆工具,两种组件都原生实现了多进程并行压缩能力。

以 Terser 为例,TerserWebpackPlugin 插件默认已开启并行压缩,开发者也可以通过 parallel 参数(默认值为 require('os').cpus() - 1)设置具体的并发进程数量,如:

const TerserPlugin = require("terser-webpack-plugin");module.exports = {optimization: {minimize: true,minimizer: [new TerserPlugin({parallel: 2 // number | boolean})],},
};

上述配置即可设定最大并行进程数为 2。此外,Webpack4 所使用的 uglifyjs-webpack-plugin 也提供了类似的功能,用法与 Terser 相同,此处不再赘述。

总结

受限于 JavaScript 的单线程架构,Webpack 构建时并不能充分使用现代计算机的多核 CPU 能力,为此社区提供了若干基于多进程实现的并行构建组件,包括文中介绍的 HappyPack、Thread-loader、Parallel-Webpack、Terser。

  • 对于 Webpack4 之前的项目,可以使用 HappyPack 实现并行文件加载;

  • Webpack4 之后则建议使用 Thread-loader;

  • 多实例并行构建场景建议使用 Parallel-Webpack 实现并行;

  • 生产环境下还可配合 terser-webpack-plugin 的并行压缩功能,提升整体效率。

  • 理论上,并行确实能够提升系统运行效率,但 Node 单线程架构下,所谓的并行计算都只能依托与派生子进程执行,而创建进程这个动作本身就有不小的消耗 —— 大约 600ms,对于小型项目,构建成本可能可能很低,引入多进程技术反而导致整体成本增加,因此建议大家按实际需求斟酌使用上述多进程方案。

  • 可以思考,有没有可能使用 Node Worker 实现多线程形式的 Webpack 并行构建?社区是否已经有相关组件?与多进程相比,可能存在怎么样的优缺点?

相关文章:

Webpack: 并行构建

概述 受限于 Node.js 的单线程架构,原生 Webpack 对所有资源文件做的所有解析、转译、合并操作本质上都是在同一个线程内串行执行,CPU 利用率极低,因此,理所当然地,社区出现了一些以多进程方式运行 Webpack&#xff0…...

Vue的介绍与使用

1.Vue的介绍 内容讲解 【1】Vue介绍 1.vue属于一个前端框架,底层使用原生js编写的。主要用来进行前端和后台服务器之间的一个交互。 2.Vue是一套构建用户界面的渐进式前端框架。 “渐进式框架”简单的来说你可以将Vue作为你的应用一部分嵌入其中,代理…...

MYSQL双主双从,使用Keepalived双机热备+LVS高可用群集

MYSQL双主双从,使用Keepalived双机热备LVS高可用群集 ​ 文档只记录KeepalivedLVSmysql主从,不包含检验,如需检验,请自行添加web服务器 一、IP规划 服务器IP备注master1192.168.100.131master2的从master2192.168.100.132maste…...

9.计算机视觉—目标检测

目录 1.物体检测边缘框目标检测数据集总结边缘框代码实现2.锚框:目标检测的一种方法IoU—交并比赋予锚框标号使用非极大值抑制(NMS)输出总结代码实现1.物体检测 边缘框 一个边缘框可以通过四个数字定义 (左上x,左上y),(右下x,右下y)(左上x,左上y,宽,高)(中间x,中间y…...

构造函数深入理解

目录 构造函数构造函数体赋值初始化列表初始化列表格式初始化列表的意义以及注意点const修饰的成员变量初始化对象成员具体初始化的地方缺省值存在的意义例子1例子2 初始化与赋值引用成员变量的初始化注意点1注意点2我的疑惑 自定义类型成员初始化例子1例子2例子3例子4 初始化列…...

Rocky Linux 9 快速安装docker 教程

前述 CentOS 7系统将于2024年06月30日停止维护服务。CentOS官方不再提供CentOS 及后续版本,不再支持新的软件和补丁更新。CentOS用户现有业务随时面临宕机和安全风险,并无法确保及时恢复。由于 CentOS Stream 相对不稳定,刚好在寻找平替系统…...

go语言并发编程1-Gouroutine

参考文档:www.topgoer.com 使用方法 直接包装成函数,go关键字触发即可 注意事项 1 main方法结束后,main方法内启动的子协程会立即结束,无论是否执行完毕; 启动多个groutine 使用sync包的WaitGroup来控制&#xf…...

Sylar服务器框架——Http模块

1、http.h 定义了HttpMethod和HttpStatus /* Request Methods */ #define HTTP_METHOD_MAP(XX) \XX(0, DELETE, DELETE) \XX(1, GET, GET) \XX(2, HEAD, HEAD) \XX(3, POST, POST) \XX(4, PUT, …...

7km远距离WiFi实时图传模块,无人机海上无线传输方案,飞睿智能WiFi MESH自组网技术

在浩瀚无垠的海洋上,无人机正在开启一场前所未有的技术创新。它们不再只是天空的舞者,更是海洋的守望者,为我们带来前所未有的视野和数据。而这一切的背后,都离不开一项创新性的技术——飞睿智能远距离WiFi实时图传模块与无线Mesh…...

2024年上半年网络工程师下午真题及答案解析

试题一(20分) 某高校网络拓扑如下图所示,两校区核心(CORE-1、CORE-2),出口防火墙(NGFW-1、NGFW-2)通过校区间光缆互联,配置OSPF实现全校路由收敛,两校区相距40km。两校区默认由本地…...

Jmeter下载、安装及配置

1 Jmeter介绍 Jmeter是进行负载测试的工具,可以在任何支持Java虚拟机环境的平台上运行,比如Windows、Linux、Mac。 Jmeter模拟一组用户向目标服务器发送请求,并统计目标服务器的性能信息,比如CPU、memory usage。 2 Jmeter下载 …...

掌握高效实用的VS调试技巧

🔥 个人主页:大耳朵土土垚 1.编程常见的错误 1.1编译型错误 编程编译型错误是指在编译代码时发现的错误。编译器在编译过程中会检查代码是否符合语法规范和语义要求,如果发现错误会产生编译错误。 直接看错误提示信息(双击&#…...

实验2 字符及字符串输入输出与分支程序设计实验

字符及字符串输入输出 从键盘输入两个一位十进制数,计算这两个数之和,并将结果在屏幕上显示出来。 分支程序设计 从键盘输入一字符,判断该字符是小写字母、大写字母、数字或者其他字符。若输入为小写字母,显示“You Input a Lo…...

docker容器间网络仿真工具-pumba

docker-tc&pumba docker-tc:docker-tc项目仓库 pumba:pumba项目仓库 这两个项目理论上都可以实现对容器间的网络环境进行各种模拟干预,包括延迟,丢包,带宽限制等。 但是我在实际使用时,发现docker-tc这个工具在进行网络进行模…...

A36 STM32_HAL库函数 之PCD通用驱动 -- B -- 所有函数的介绍及使用

A36 STM32_HAL库函数 之PCD通用驱动 -- B -- 所有函数的介绍及使用 1 该驱动函数预览1.11 HAL_PCD_SOFCallback1.12 HAL_PCD_ResetCallback1.13 HAL_PCD_SuspendCallback1.14 HAL_PCD_ResumeCallback1.15 HAL_PCD_ISOOUTIncompleteCallback1.16 HAL_PCD_ISOINIncompleteCallbac…...

vue2 + element三级菜单实现模板

需求&#xff1a; 需要一个含有三级菜单的结构模板&#xff0c;用于业务快速开发。 解决&#xff1a; sidebar.vue <template><el-menu :default-active"defaultActive" class"el-menu-vertical-demo" active-text-color"#ffd04b"&…...

vue H5页面video 视频流自动播放, 解决ios不能自动播放问题

视频组件 <videostyle"width: 100%; height: 100%;object-fit: fill"class"player"refplayer_big_boxcontrolspreloadautoplay //自动播放muted //是否静音playsinline"true"x5-playsinline""webkit-playsinline"tru…...

自闭症儿童:探索症状背后的多彩内心世界

在星启帆自闭症康复中心&#xff0c;我们每天与一群独特而珍贵的孩子相遇——他们&#xff0c;是自闭症谱系障碍的患儿。自闭症&#xff0c;这一复杂的神经发育障碍&#xff0c;以其多样化的症状表现&#xff0c;为每个孩子的生活轨迹绘上了不同的色彩。 自闭症孩子的症状各异…...

在Centos7上安装PostgreSQL16的详细步骤

文章目录 环境一、准备二、postgresql下载方法一&#xff1a;wget下载方法二&#xff1a;下载压缩包解压 三、创建用户组、用户四、创建数据主目录五、配置环境变量六、initdb初使化数据库七、配置服务八、设置开机自启动九、设置防火墙十、启动数据库服务 环境 CPU: 4 核心或以…...

MySQL 图形化界面

填完信息之后&#xff0c;圆圈处可以验证是否可以连接数据库 展示所有数据库&#xff08;因为有的可能连上&#xff0c;却没有数据库显示&#xff09;...

【人工智能】GPT-5的即将到来:从高中生进化到,,,博士生?

GPT-5的即将到来&#xff1a;从高中生进化到,博士生&#xff1f; 随着近月GPT-4o的出世&#xff0c;OpenAI也在进行一系列的采访和介绍接下来的展望和目标。 在6月22日的采访中&#xff0c;美国达特茅斯工程学院公布了OpenAI首席技术官米拉穆拉蒂的访谈内容。穆拉蒂确认&#…...

【收录率高丨投稿范围广 | 往届均已EI检索】第四届光学与通信技术国际学术会议(ICOCT 2024,8月9-11)

欢迎参加第四届光学与通信技术国际学术会议&#xff08;ICOCT 2024&#xff09;&#xff0c;该会议将于2024年8月9-11日在南京举办。自2021年首次会议以来&#xff0c;ICOCT已经发展成为光学和通信领域较有影响力的国际会议之一&#xff0c;聚焦最前沿的技术进展与未来发展趋势…...

小阿轩yx-LVS负载均衡群集

小阿轩yx-LVS负载均衡群集 构建群集服务器—通过整合多台服务器使用 LVS 达到服务器的高可用和负载均衡并以同一个 IP 地址对外提供相同的服务 LVS 群集应用基础 群集称呼来自英文单词“Cluster”在服务器领域则表示大量服务器的集合体&#xff0c;区分单个服务器 Cluster …...

CPP知识点记录总结

1、类的const成员函数 const成员函数的const 实际修饰的是该成员函数隐含的this指针&#xff0c;表明在该成员函数中不能对类的任何成员进行修改。 class A {void fun() const {// 常成员函数&#xff0c;在函数名后用const修饰} } 一文带你入门C类和对象【十万字详解&#…...

Spring源码(一) 如何阅读 Spring 源码

学习 Spring 的源码&#xff0c;也可以通过 SpringBoot 搭环境。 不管是什么源码&#xff0c;最好写个 demo&#xff0c;跑起来&#xff0c;然后从常用的类和方法入手&#xff0c;跟踪调试。 配置对象 新建一个 SpringBoot 的项目&#xff0c; 详情见&#xff1a; https://b…...

【代码随想录训练营】【Day 63】【单调栈-2】| Leetcode 42, 84

【代码随想录训练营】【Day 63】【单调栈-2】| Leetcode 42, 84 需强化知识点 单调栈强化 题目 42. 接雨水 注意 python 数组反序用法 result [::-1] class Solution:def trap(self, height: List[int]) -> int:# n len(height)# leftMax, rightMax [0] * n, [0] * …...

CTF常用sql注入(一)联合注入和宽字节

0x01 前言 给自己总结一下sql注入的常用姿势吧&#xff0c;记录一下学习 0x02 联合 联合注入的关键词是union SQL的union联合注入原理是联合两个表进行注入攻击&#xff0c;使用union select关键词来进行联合查询。 那么为什么我们在题目中一般是只写一个呢 因为 $sql &quo…...

薄冰英语语法学习--冠词1

冠词有2个,the 和 a /an the 叫定冠词 常用形容一类事务、特指&#xff08;加强&#xff09;、放在转有名词前面。 就这3个 定冠词 1. 定冠词特指某个&#xff08;某些&#xff09;人或某个&#xff08;某些&#xff09;事物 Many people came here to visit the old cast…...

基于Java中的SSM框架实现野生动物公益保护系统项目【项目源码+论文说明】计算机毕业设计

基于Java中的SSM框架实现野生动物公益保护系统演示 摘要 本系统按照网站系统设计的基本流程&#xff0c;遵循系统开发生命周期法和结构化方法&#xff0c;基于Java语言设计并实现了野生动物公益保护系统。该系统基于浏览器/服务器模式&#xff0c;采用JSP技术&#xff0c;后台…...

c->c++(二):class

本文主要探讨C类的相关知识。 构造和析构函数 构造函数(可多个)&#xff1a;对象产生时调用初始化class属性、分配class内部需要的动态内存 析构函数&#xff08;一个&#xff09;&#xff1a;对对象消亡时调用回收分配动态内存 C提供默认构造和析构,…...

11 UDP的可靠传输协议QUIC

1.如何做到可靠性传输 2.UDP与TCP,我们如何选择 3.UDP如何可靠,KCP协议在哪些方面有优势 4.KCP协议精讲(重点讲解 5.OUIC时代是否已经到来 UDP如何做到可靠传输 ACK机制重传机制 重传策略序号机制(后发的包可能先到) 3 2 1-> 2 3 1重排机制 2 3 1-> 3 2 1窗口机制 流…...

14-20 Vision Transformer用AI的画笔描绘新世界

概述 毫无疑问,目前最受关注且不断发展的最重要的主题之一是使用人工智能生成图像、视频和文本。大型语言模型 (LLM) 已展示出其在文本生成方面的卓越能力。它们在文本生成方面的许多问题已得到解决。然而,LLM 面临的一个主要挑战是它们有时会产生幻觉反应。 最近推出的新模…...

LVS FILTER UNUSED OPTION

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 过滤一些版图与spice网表对不上的器件。 一般后端遇不到这个问题,因为通常是需要写到网表中的decap没有写出来造成的,如下图。...

Python后端面试题

1. 文件操作w和r的区别 在Python中&#xff0c;文件操作模式中的w和r都表示对文件的读写操作&#xff0c;但它们在打开文件时的行为有所不同&#xff1a; r模式&#xff1a; 读写&#xff1a;这种模式允许你同时读取和写入文件。文件必须已经存在&#xff0c;否则会抛出一个Fi…...

docker打包 arm32v7/debian 问题总结

1.架构不同 我的宿主是x86 ,但是打包的是arm架构 安装qemu sudo apt-get install binfmt-support qemu qemu-user-static 然后使用buildx打包 docker buildx build --no-cache --platform linux/arm/v7 -t tdc_post:1.0.1 . --load 保存tar docker save -o tdc_post.tar tdc_p…...

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(二十)

课程地址&#xff1a; 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程&#xff0c;一套精通鸿蒙应用开发 &#xff08;本篇笔记对应课程第 30 节&#xff09; P30《29.数据持久化-用户首选项》 实现数据持久化在harmonyOS中有很多种方式&#xff0c;比较常见的是以下两…...

Vuetify3:监听当前手机还是电脑

我们在开发的时候&#xff0c;实现根据移动设备或PC设备来改编一些交互样式&#xff0c;这个时候我们需要监听宽度&#xff0c;在Vuetify3中可我们可以参考 ​​​​显示 & 平台配合监听即可在窗口缩小的时候判断出手机还是电脑 <template><v-app><div v-if…...

Zabbix 配置钉钉告警

Zabbix 配置钉钉告警 随着企业IT运维需求的不断增加&#xff0c;及时、准确地获取系统告警信息显得尤为重要。在众多告警工具中&#xff0c;Zabbix 因其强大的监控功能和灵活的告警机制&#xff0c;成为了很多企业的首选。同时&#xff0c;随着企业内部沟通工具的多样化&#…...

TTL转RS232与USB转TTL

USB转TTL是一种常用的通信接口转换器&#xff0c;它将USB&#xff08;通用串行总线&#xff09;接口转换为TTL&#xff08;晶体管-晶体管逻辑&#xff09;电平的串行接口。这种转换器在许多场景下非常有用&#xff1a; USB转TTL&#xff1a; 功能&#xff1a; 将计算机的USB接…...

【力扣 896】单调数列 C++题解(循环)

如果数组是单调递增或单调递减的&#xff0c;那么它是 单调 的。 如果对于所有 i < j&#xff0c;nums[i] < nums[j]&#xff0c;那么数组 nums 是单调递增的。 如果对于所有 i < j&#xff0c;nums[i]> nums[j]&#xff0c;那么数组 nums 是单调递减的。 当给定…...

代码随想录Day71(图论Part07)

53.寻宝 题目&#xff1a;53. 寻宝&#xff08;第七期模拟笔试&#xff09; (kamacoder.com) 思路&#xff1a;首先&#xff0c;我不知道怎么存这样的东西&#xff0c;用三维数组吗&#xff0c;没搞懂&#xff0c;果断放弃 prim算法实现 import java.util.*;class Main {publi…...

[Mdp] lc 494. 目标和(01背包变种+dp+dfs)

文章目录 1. 题目来源2. 题目解析1. 题目来源 链接:494. 目标和 2. 题目解析 方法一:dfs 数据量比较小,长度只有 20,那么针对每一个数都有两种选择,正、负,即 2 20 = 100 w 2^{20} = 100w 220=100w 差不多的时间复杂度,dfs 解决即可。时间复杂度: O ( 2 n ) O(2^{n…...

React vs Vue:谁是构建现代Web应用的王者?

在前端开发领域&#xff0c;React 和 Vue 是两大备受推崇的框架&#xff08;React实为库&#xff09;&#xff0c;各自拥有庞大的社区和丰富的生态系统。本文旨在深入探讨这两者之间的区别&#xff0c;通过代码示例来分析它们各自的优势和适用场景&#xff0c;从而帮助开发者做…...

Linux CentOS 宝塔中禁用php8.2的eval函数详细图文教程

PHP_diseval_extension 这个方法是支持PHP8的, Suhosin禁用eval函数&#xff0c;不支持PHP8 一、安装 cd / git clone https://github.com/mk-j/PHP_diseval_extension.gitcd /PHP_diseval_extension/source/www/server/php/82/bin/phpize ./configure --with-php-config/ww…...

Matlab 中 fftshift 与 ifftshift

文章目录 【 1. fftshift、ifftshift 的区别】【 2. fftshift(fft(A)) 作图 】【 3. fftshift(fft(A)) 还原到 A 】Matlab 直接对信号进行 FFT 的结果中,前半部分是正频,后半部分是负频,为了更直观的表示,需要将 负频 部分移到 前面。【 1. fftshift、ifftshift 的区别】 M…...

被裁了(9年)

那年&#xff08;2015年&#xff09;我刚毕业有一年多&#xff08;20出头&#xff09;&#xff0c;阴差阳错来到了现在的单位。 那时互联网腾起&#xff0c;单位也迅速发展&#xff0c;部门从起初的不到30号人发展到500人&#xff1b;A轮、B轮.....D轮&#xff0c;一轮轮的融资…...

13. Revit API: Filter(过滤器)

13. Revit API: Filter&#xff08;过滤器&#xff09; 前言 在讲Selection之前&#xff0c;还是有必要先了解一下的过滤器的。 对了&#xff0c;关于查找一些比较偏的功能或者API的用法&#xff0c;可以这样查找 关键词 site:https://thebuildingcoder.typepad.com/ site是…...

hadoop 3.X 分布式HA集成Kerbos(保姆级教程)

前提&#xff1a;先安装Kerbos 1、创建keytab目录 在每台机器上上提前创建好对应的kertab目录 [hadooptv3-hadoop-01 ~]$ sudo mkdir -p /BigData/run/hadoop/keytab/ [hadooptv3-hadoop-01 ~]$ sudo mkdir -p /opt/security/ [hadooptv3-hadoop-01 ~]$ sudo chown hadoop:had…...

VDS虚拟导播切换台软件

VDS 导播软件是一款功能强大的虚拟导播系统软件&#xff0c;具有全媒体接入、播出内容丰富、调音台、快捷切播与导播键盘、云台控制等特点&#xff0c;同时支持向多个平台直播推流。以下是一些常见的 VDS 导播软件特点&#xff1a; 1. 全媒体接入&#xff1a;支持多种设备和网…...

UE4_材质_使用彩色半透明阴影

学习笔记&#xff0c;不喜勿喷&#xff01;侵权立删&#xff0c;祝愿大美临沂生活越来越好&#xff01; 本教程将介绍如何配置虚幻引擎来投射彩色半透明阴影。 此功能在许多应用中都很有用&#xff0c;常见例子就是透过彩色玻璃窗的彩色光。 一、半透明阴影颜色 阴影在穿过半…...

计算机网络面试常见题目(一)

计算机网络面试中常见的问题涉及多个层面&#xff0c;包括网络协议、网络体系结构、网络安全、数据传输等。以下是一些常见题目的详解&#xff1a; 1. OSI七层模型是什么&#xff1f;每层的功能是什么&#xff1f; OSI七层模型是国际标准化组织&#xff08;ISO&#xff09;制…...

Docker加速器配置指南:提升镜像下载速度的秘诀 加速安装Mysql Redis ES

在安装 Docker 镜像时&#xff0c;由于官方镜像下载速度较慢&#xff0c;我们可以使用阿里云的镜像加速器来提升下载速度。 使用阿里云镜像加速器 首先&#xff0c;找到并配置阿里云的镜像加速器。安装教程如下&#xff1a; 登录阿里云&#xff0c;进入容器镜像服务。直达链…...

AttackGen:一款基于LLM的网络安全事件响应测试工具

关于AttackGen AttackGen是一款功能强大的网络安全事件响应测试工具&#xff0c;该工具利用了大语言模型和MITRE ATT&CK框架的强大功能&#xff0c;并且能够根据研究人员选择的威胁行为组织以及自己组织的详细信息生成定制化的事件响应场景。 功能介绍 1、根据所选的威胁行…...

学习LLM的随笔

1、信息量、信息熵、交叉熵和困惑度 注&#xff1a;因为真实分布的概率为1&#xff0c;所以在分类任务中交叉熵可以简化为上述形式。 &#xff08;1&#xff09;信息熵 信息熵中使用 l o g 2 ( p ( x ) ) log_2(p(x)) log2​(p(x)) 来表示对 x x x 编码需要的编码长度。…...

VPN是什么?

VPN&#xff0c;全称Virtual Private Network&#xff0c;即“虚拟私人网络”&#xff0c;是一种在公共网络&#xff08;如互联网&#xff09;上建立加密、安全的连接通道的技术。简单来说&#xff0c;VPN就像是一条在公共道路上铺设的“秘密隧道”&#xff0c;通过这条隧道传输…...

隐式转换的魔法:Scala中隐式转换的深度解析

隐式转换的魔法&#xff1a;Scala中隐式转换的深度解析 在Scala编程语言的丰富特性中&#xff0c;隐式转换是一个强大而微妙的工具。它允许开发者在不改变现有代码的情况下&#xff0c;扩展或修改类的行为。本文将深入探讨Scala中隐式转换的工作原理&#xff0c;并通过详细的代…...

540°全域透明底盘“爸”气从容跨越障碍

无论孩子多大,在学业或工作上遇到的障碍,父亲总会以更宽广的视野为我们拨开云雾。为给全家人带来开挂级的开阔视野,而奇瑞舒享家配备540全域透明底盘,透明底盘+360高清全景影像,让障碍无处遁形。且可实现高清2D/3D视图切换,全方位观察车辆周围及车底的情况,一目了然;还…...

夜读朱大建:海菜花,清水的精灵

海菜花不光美丽,还是美味。去年6月5日世界环境日当天,我写的生态纪实文学《海菜花开》,由上海交通大学出版社召开出版座谈会,全国有十多家媒体刊发报道或书评。当月,该书就印了三次。去年9月,由上海交大创作、学生主演的校园话剧《海菜花开》在闵行校区菁菁堂演出。今年3…...

一串“蕉绿”、一辆BJ30,自在生活竟如此简单?

近日,一款外形金黄矮胖,长相酷似“小黄人”的苹果蕉火爆网络。据报道,苹果蕉养着养着,就会从绿变黄,意味着焦虑化散。因此,插上一串“蕉绿”也成为当代年轻人办公桌上的新景观。事实上,能够远离焦虑的不止苹果蕉,还有刚刚上市不久的北京汽车BJ30。作为北京汽车精心打造…...

浩江星灿面试(c++)

量化工程师&#xff1a;提供实时的数据&#xff0c;为炒股提供依据&#xff1b;稳定&#xff0c;快&#xff0c;准确&#xff1b; 对于性能的要求比较高&#xff1b; 文章目录 题目一、延迟最低的IPC(Inter-Process Communication)通信方式是什么&#xff1f;题目二、找出下面…...

解锁Android高效数据传输的秘钥 - Parcelable剖析

作为Android开发者&#xff0c;我们经常需要在不同的组件(Activity、Service等)之间传输数据。这里的"传输"往往不仅仅是简单的数据复制&#xff0c;还可能涉及跨进程的内存复制操作。当传输的数据量较大时&#xff0c;这种操作可能会带来严重的性能问题。而Android系…...

Python面试宝典:Python中与动态规划和排序算法相关的面试笔试题(1000加面试笔试题助你轻松捕获大厂Offer)

Python面试宝典:1000加python面试题助你轻松捕获大厂Offer【第二部分:Python高级特性:第十二章:高级数据结构和算法:第二节:Python中实现各类高级数据结构与算法三】 第十二章:高级数据结构和算法第二节:Python中实现各类高级数据结构与算法2.3、python中与动态规划和排…...