JVM常见概念之条件移动
问题
当我们有分支频率数据时,有什么有趣的技巧可以做吗?什么是条件移动?
基础知识
如果您需要在来自一个分支的两个结果之间进行选择,那么您可以在 ISA 级别做两件不同的事情。
首先,你可以创建一个分支:
# %r = (%rCond == 1) ? $v1 : $v2cmp %rCond, $1jne Amov %r, $v1jmp EA: mov %r, $v2E:
其次,您可以执行依赖于比较结果的预测指令 。在 x86 中,这采用条件移动 (CMOV) 的形式,当选定条件成立时执行操作:
# %r = (%rCond == 1) ? $v1 : $v2mov %r, $v1 ; put $v1 to %rcmp %rCond, ...cmovne %r, $v2 ; put $v2 to %r if condition is false
执行条件移动的优点是它有时会生成更紧凑的代码,就像在这个例子中一样,并且它不会受到可能的分支预测错误惩罚。缺点是它需要在选择返回哪一边之前计算两边,这可能会花费过多的 CPU 周期,增加寄存器压力等。在分支情况下,我们可以选择在检查条件后不计算内容。预测良好的分支将优于条件移动。
因此,是否执行条件移动的选择在很大程度上取决于其成本预测。这就是分支分析可以帮助我们的地方:它可以说出哪些分支可能没有被完美预测,因此适合 CMOV 替换。当然, 实际成本模型还包括我们正在处理的参数类型、两个计算分支的相对深度等。
实验
源码-用例1
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class BranchFrequency {@Benchmarkpublic void fair() {doCall(true);doCall(false);}@CompilerControl(CompilerControl.Mode.DONT_INLINE)public int doCall(boolean condition) {if (condition) {return 1;} else {return 2;}}
}
执行结果
我们在每次调用时都会在分支之间进行切换,这意味着它的运行时配置文件在它们之间大约是 50%-50%。如果我们通过提供 -XX:ConditionalMoveLimit=0 来限制条件移动替换,那么我们就可以清楚地看到替换的发生。
# doCall, out of box variant4.36% ...4ac: mov $0x1,%r11d ; move $1 -> %r113.24% ...4b2: mov $0x2,%eax ; move $2 -> %res8.46% ...4b7: test %edx,%edx ; test boolean0.02% ...4b9: cmovne %r11d,%eax ; if false, move %r11 -> %res7.88% ...4bd: add $0x10,%rsp ; exit the method8.12% ...4c1: pop %rbp18.60% ...4c2: cmp 0x340(%r15),%rsp...4c9: ja ...4d00.14% ...4cf: retq# doCall, CMOV conversion inhibited6.48% ...cac: test %edx,%edx ; test boolean╭ ...cae: je ...cc8│ ; if true...│ ...cb0: mov $0x1,%eax ; move $1 -> %res7.41% │↗ ...cb5: add $0x10,%rsp ; exit the method0.02% ││ ...cb9: pop %rbp27.43% ││ ...cba: cmp 0x340(%r15),%rsp││ ...cc1: ja ...ccf3.28% ││ ...cc7: retq││ ; if false...7.04% ↘│ ...cc8: mov $0x2,%eax ; move $2 -> %res0.02% ╰ ...ccd: jmp ...cb5 ; jump back
在此示例中,CMOV 版本的表现稍好一些:
Benchmark Mode Cnt Score Error Units# Branches
BranchFrequency.fair avgt 25 5.422 ± 0.026 ns/op
BranchFrequency.fair:L1-dcache-loads avgt 5 12.078 ± 0.226 #/op
BranchFrequency.fair:L1-dcache-stores avgt 5 5.037 ± 0.120 #/op
BranchFrequency.fair:branch-misses avgt 5 0.001 ± 0.003 #/op
BranchFrequency.fair:branches avgt 5 10.037 ± 0.216 #/op
BranchFrequency.fair:cycles avgt 5 14.659 ± 0.285 #/op
BranchFrequency.fair:instructions avgt 5 35.184 ± 0.559 #/op# CMOVs
BranchFrequency.fair avgt 25 4.799 ± 0.094 ns/op
BranchFrequency.fair:L1-dcache-loads avgt 5 12.014 ± 0.329 #/op
BranchFrequency.fair:L1-dcache-stores avgt 5 5.005 ± 0.167 #/op
BranchFrequency.fair:branch-misses avgt 5 ≈ 10⁻⁴ #/op
BranchFrequency.fair:branches avgt 5 7.054 ± 0.118 #/op
BranchFrequency.fair:cycles avgt 5 12.964 ± 1.451 #/op
BranchFrequency.fair:instructions avgt 5 36.285 ± 0.713 #/op
您可能认为这是因为 CMOV 没有分支预测失误惩罚,但这种解释与计数器不一致。请注意,在两种情况下,“分支失误”几乎为零。这是因为硬件分支预测器实际上可以记住一个短暂的分支历史,而这种反复出现的分支对它们来说没有任何问题。性能差异的实际原因是分支情况下的跳跃:我们在关键路径上有一条额外的控制流指令。
源码-用例2
@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
public class AdjustableBranchFreq {@Param("50")int percent;boolean[] arr;@Setup(Level.Iteration)public void setup() {final int SIZE = 100_000;final int Q = 1_000_000;final int THRESH = percent * Q / 100;arr = new boolean[SIZE];ThreadLocalRandom current = ThreadLocalRandom.current();for (int c = 0; c < SIZE; c++) {arr[c] = current.nextInt(Q) < THRESH;}// Avoid uncommon traps on both branches.doCall(true);doCall(false);}@Benchmarkpublic void test() {for (boolean cond : arr) {doCall(cond);}}@CompilerControl(CompilerControl.Mode.DONT_INLINE)public int doCall(boolean condition) {if (condition) {return 1;} else {return 2;}}
}
执行结果
使用不同的 percent 值和 -prof perfnorm JMH 分析器运行它将产生以下结果:
依据上图,你可以清楚地看到几件事:
- 每个测试的分支数约为 5,而 CMOV 转换将其降至 4。这与之前的反汇编转储相关:我们将测试中的一个分支转换为 CMOV。另外 4 个分支来自测试基础设施本身。
- 如果没有 CMOV,分支测试性能会受到影响,在 50% 的分支概率下会变得最差。这个峰值反映了硬件分支预测器几乎完全混乱,因为它每次操作都会遇到大约 0.5 次分支失误。这意味着分支预测器并不是一直猜错(这太荒谬了!),而只是一半的时间猜错。我推测基于历史的预测器会放弃,让静态预测器选择最近的分支,而我们只选择了一半的时间。
- 使用 CMOV 后,我们可以看到操作时间几乎持平 。该图表明 CMOV 成本模型对于此测试来说可能过于保守,并且切换得有点晚。这并不一定意味着它有错误,因为其他情况的表现很可能会有所不同。尽管如此,当进行 CMOV 转换时,对分支情况的改进是巨大的。
- 您可能会注意到,当分支预测准确率为 >97% 时,分支变体会低于 CMOV 中间平均值。当然,这又是测试、硬件、虚拟机特有的事情。
总结
分支分析允许在执行概率敏感指令选择时做出或多或少明智的选择。条件移动替换通常使用分支频率信息来驱动替换。这再次强调了使用与真实数据类似的数据来预热 JIT 编译代码的必要性,以便编译器能够针对特定情况进行有效优化。
相关文章:
JVM常见概念之条件移动
问题 当我们有分支频率数据时,有什么有趣的技巧可以做吗?什么是条件移动? 基础知识 如果您需要在来自一个分支的两个结果之间进行选择,那么您可以在 ISA 级别做两件不同的事情。 首先,你可以创建一个分支ÿ…...
k8s存储介绍(二)Secret
Kubernetes(K8s)提供了一种安全的方式来存储和管理敏感信息,如密码、OAuth 令牌和 SSH 密钥,这就是 Secret。使用 Secret 可以避免将敏感数据硬编码到 Pod 规范或容器镜像中,从而提高安全性和可管理性。 1. Secret 的…...
Css布局-常规流笔记
https://developer.mozilla.org/zh-CN/docs/Learn/CSS/CSS_layout/Normal_Floworghttps://developer.mozilla.org/zh-CN/docs/Learn/CSS/CSS_layout/Normal_Flow 前言 常规流布局是html元素默认布局,凡是没有设置过css布局的html元素,默认布局方式称为常…...
Linux系统管理与编程08:任务驱动综合应用
兰生幽谷,不为莫服而不芳; 君子行义,不为莫知而止休。 [环境] windows11、centos7.9.2207、zabbix6、MobaXterm、Internet环境 [要求] zabbix6.0安装环境:Lamp(linux httpd mysql8.0 php) [步骤] 3 …...
基于 OCO - 2 氧气 A 带辐射数据与地面台站气压观测数据构建近地面气压监测算法方案
基于 OCO - 2 氧气 A 带辐射数据与地面台站气压观测数据构建近地面气压监测算法方案 一、数据获取与准备 (一)OCO - 2 氧气 A 带辐射数据 数据下载:从 OCO - 2 官方数据发布平台(如 NASA 的相关数据存储库),按照研究所需的时间范围(例如,近 5 年的数据以获取足够的样本…...
Linux centos7 虚拟用户访问脚本
下面是脚本: #!/bin/bash #function:创建 vsftpd 虚拟用户脚本 #author: 20250324 IT小旋风# 判断是否是 root 用户 if [ "$USER" ! "root" ]; thenecho "不是 root 用户,无法进行安装操作"exit 1 fi# 关闭防火墙 system…...
HTTP 协议中请求与响应的详细解析
前言:HTTP(Hypertext Transfer Protocol,超文本传输协议)是用于在互联网上传输超文本的协议 --由一个请求和响应组成,一个完整的 HTTP 请求由请求行(Request Line)、请求头(Headers&…...
Collectors.toMap / list 转 map
前言 略 Collectors.toMap List<User> userList ...; Map<Long, User> userMap userList.stream().collect(Collectors.toMap(User::getUserId, Function.identity()));假如id存在重复值,则会报错Duplicate key xxx, 解决方案 两个重复id中&#…...
根据模板将 Excel 明细数据生成 PDF 文档 | PDF实现邮件合并功能
在日常办公中,我们常常会面临这样的需求:依据特定的模板,把 Excel 里的每一条数据转化为单独的 PDF 文档,且这些 PDF 文档中的部分内容会根据 Excel 数据动态变化。这一功能不仅能高效完成任务,还支持图片的动态替换&a…...
<KeepAlive>和<keep-alive>有什么区别
在不同的前端技术框架里,<KeepAlive> 和 <keep-alive> 有着不同的含义与使用场景,下面分别从 Vue 2 和 Vue 3 来为你详细介绍它们的区别。 Vue 2 中的 <keep-alive> 在 Vue 2 里,<keep-alive> 属于内置组件&#x…...
vscode正则表达式使用
小标题 ^\d.\d.\d\s.*$ ^表示匹配字符串的开头。\d\.\d\.\d表示匹配一到多个数字,接着一个小数点,再接着一到多个数字,然后又一个小数点和一到多个数字,用来匹配类似 “2.1.1” 这样的标题号部分。\s表示匹配一个空格。.*表示匹配…...
【LeetCode 题解】算法:4.寻找两个正序数组的中位数
1. 引言:挑战 LeetCode 经典算法题 在算法这片广袤无垠的天地里,一道道经典题目宛如夜空中熠熠生辉的星辰,持续吸引着开发者们投身其中,不断探索。今天,我们继续将目光聚焦于 LeetCode 平台上一道极具代表性的题目&am…...
2025.03.23【前沿工具】| CellPhoneDB:基因网络分析与可视化的利器
文章目录 1. CellPhoneDB工具简介2. CellPhoneDB的安装方法3. CellPhoneDB常用命令 1. CellPhoneDB工具简介 在单细胞生物学的迅猛发展中,理解细胞间的通讯机制对于揭示组织功能和疾病状态至关重要。CellPhoneDB工具,作为一个专门设计用来分析单细胞转录…...
Excel(进阶篇):powerquery详解、PowerQuery的各种用法,逆透视表格、双行表头如何制作透视表、不规则数据如何制作数据透视表
目录 PowerQuery工具基础修改现有数据理规则PowerQuery抓取数据的两种方式多文件合并透视不同表结构多表追加数据透视追加与合并整理横向表格:逆透视 数据用拆分工具整理数据算账龄 不等步长值组合合并文件夹中所有文件PowerQuery处理CSV文件双行表头、带合并单元格如何做数据…...
【WebGIS教程2】Web服务与地理空间服务解析
前言: 在万物互联的时代,Web服务作为跨平台协作的基石,正推动地理信息领域向开放共享迈进。地理空间Web服务通过标准化协议(如WMS、WFS)与松耦合架构,打破传统GIS的封闭性,实现数据与功能的无缝…...
[250325] Claude AI 现已支持网络搜索功能!| ReactOS 0.4.15 发布!
目录 Claude AI 现已支持网络搜索功能!ReactOS 0.4.15 发布! Claude AI 现已支持网络搜索功能! 近日,Anthropic 公司宣布,其 AI 助手 Claude 现在可以进行网络搜索,为用户提供更及时、更相关的回复。这项新…...
gitee第三方登录获取openid | python+Django |已跑通
注:此项目根据美多改编,qq第三方需要备案gitee不用 一、获取appid和appsecret 点击右侧账号设置 左侧菜单栏数据管理里有第三方应用 点击创建应用,根据你的具体情况设置 二、以下是事例代码,根据需要修改即可 setting.py #QQ登…...
Enovia许可分析的自动化解决方案
随着企业产品生命周期管理(PLM)需求的不断演变,Enovia许可分析已成为确保资源优化和合规性的关键环节。然而,传统的手动许可分析方法往往效率低下、易出错,并且难以应对大规模数据。为了解决这一挑战,Enovi…...
【模拟面试】计算机考研复试集训(第十四天)
文章目录 前言一、专业面试1、进程调度中的轮转调度(Round Robin)如何实现?时间片大小对系统性能有何影响?2、动态规划的核心思想是什么?举一例说明其与分治法的区别。3、事务的ACID特性中,“隔离性” 如何…...
ambiq apollo3 ADC实例程序注释
#include "am_mcu_apollo.h" // Apollo MCU 外设寄存器定义和HAL库 #include "am_bsp.h" // 板级支持包(引脚定义、LED函数等) #include "am_util.h" // 通用工具函数(如printf重…...
ECharts实现数据可视化
ECharts实现数据可视化 一、Echarts的简介二、Echarts使用教程1.下载echarts.min.js文件2.编写echarts代码(1)创建渲染实列(2)修改option达到预期的效果(3)创建配置项到实例中 三、Echarts的基础配置四、前…...
Json冲突崩溃问题
在一个项目中同时使用RapidJSON库后崩溃了。。。。 --- ### **一、潜在问题分析** 1. **符号重复定义(ODR冲突)** - **原因**:若您的库和上位机主程序均静态链接了RapidJSON(如编译为.a或.lib),或通…...
HeyGem.ai 全离线数字人生成引擎加入 GitCode:开启本地化 AIGC 创作新时代
在人工智能技术飞速演进的时代,数据隐私与创作自由正成为全球开发者关注的焦点。硅基智能旗下开源项目 HeyGem.ai 近日正式加入 GitCode,以全球首个全离线数字人生成引擎的颠覆性技术,重新定义人工智能生成内容(AIGC)的…...
Go常见问题与答案笔记
这是一篇值的收藏的go常见问题与答案的笔记,内容包括了go的高级,如:悲观锁与乐观锁区别,for range赋值、waitgroup底层原理、go同步原语、defer关键字讲解。 文章目录 1.悲观锁VS乐观锁的区别2.for range中赋值的变量,…...
Redis 服务搭建
💢欢迎来到张翊尘的开源技术站 💥开源如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Redis 服务搭建源代码编译安装获取源码安装依赖Ub…...
React-Router路由跳转、传参、抽象封装以及嵌套路由
React-Router 示例React-Router抽象路由模块步骤: 路由导航声明式导航编程式导航 路由导航传参searchParams传参params传参 嵌套路由配置默认二级路由404路由配置两种路由模式如何选择 示例 这里我创建两个页面,分别是主页和登录页分别使用编程式导航和…...
PhotoShop学习02
1.添加文本 这个工具栏是文字工具栏,快捷键是T。选择之后鼠标会变成一个竖杠外貌,我们可以借此在图片中写入文字。 选择后,上方的工具栏会变为专门调整文字工具 这个框点击旁边的小箭头可以选择我们我们电脑系统自带的字体,同时可…...
Isaac Sim与Isaac Lab初使用
目录 基于Omiverse下载Isaacsim安装Isaac Lab配置isaacsim环境测试克隆仓库配置python环境强化学习训练的测试 IsaacLab模板配置vscode环境ros接口安装 作为nvidia出品的仿真软件,很多机器人、机器狗【具身智能】都可以有很不错的效果,所以会使用isaac s…...
用户模块——自定义业务异常
用户信息查询接口 在开发用户系统时,一个最基本的需求就是获取用户的个人信息,比如昵称、头像、改名卡次数等。本部分将介绍如何实现一个用户信息查询接口,并结合项目中的用户背包表,查询用户是否有可用的改名卡。 1. 用户信息查…...
基于数据挖掘从经验方和医案探析岭南名医治疗妇科疾病的诊疗和用药规律
标题:基于数据挖掘从经验方和医案探析岭南名医治疗妇科疾病的诊疗和用药规律 内容:1.摘要 背景:岭南地区独特的地理环境、气候条件及人文风俗使该地区妇科疾病具有一定特点,岭南名医在长期临床实践中积累了丰富的治疗经验。目的:基于数据挖掘…...
从零到一开发一款 DeepSeek 聊天机器人
AI聊天机器人 目标设计方案系统架构技术选型功能模块 实现代码环境配置安装依赖 核心代码API 请求函数主循环函数 功能扩展1. 情感分析2. 多语言支持3. 上下文记忆4. 用户身份识别 总结附录 目标 开发一个智能聊天机器人,旨在为用户提供自然、流畅的对话体验。通过…...
开源CDN产品-GoEdge
一、背景 上篇文章分析了一下CDN的基本原理以及使用代码实现了一个乞丐版的智能DNS调度器。从整个例子我们可以清晰了解到CDN原理,也就那么回事。 但是,之前也讲过了,CDN产品融合的技术比较杂、也比较多。所以我就想着,万物皆有开…...
Resume全栈项目(一)(.NET)
文章目录 项目地址一、数据库创建/日志安装1.1 创建实体层1. Entities2. Enums 存放枚举 1.2 创建数据库层1. 安装Persistance层需要的库2. 创建ResumeDbContext3. 添加数据库配置/注册DBContext4. 执行Add-Migration5. 修改字段类型6. Enum支持Json 1.3 安装Serilog1. Api层安…...
如何快速下载并安装 Postman?
从下载、安装、启动 Postman 这三个方面为大家详细讲解下载安装 Postman 每一步操作,帮助初学者快速上手。 Postman 下载及安装教程(2025最新)...
【PICO】开发环境配置准备
Unity编辑器配置 安装Unity编辑器 安装UnityHub 安装Unity2021.3.34f1c1 添加安卓平台模块 Pico软件资源准备 资源准备地址:Pico Developer PICO SDK PICO Unity Integration SDK PICO Unity Integration SDK 为 PICO 基于 Unity 引擎研发的软件开发工具…...
Unity图形学Shader快速回顾
参考知识点来源于: 人间自有韬哥在, 唐老狮,窗外听轩雨 , 呆呆敲代码的小Y little_fat_sheep, AitTech, DeepSeek, 百度, 豆包 目录 一、渲染管线1.应用阶段2.几何阶段3.光栅化阶段 二、矩阵的几何意义1. 平移2. 旋转3. 缩放4.复合运算 三、…...
十六进制(Hexadecimal)简介
十六进制(Hexadecimal)简介 1.1 什么是十六进制? 十六进制是一种使用16个符号表示数值的系统:数字0-9(表示0-9),字母A-F(表示10-15)。 1.2 十六进制表示法 在编程中&a…...
1、pytest基本用法
目录 先给大家分享下学习资源 1. 安装pytest 2. 编写用例规则 3. 执行用例 最近在学习pytest的用法 并且用这套框架替换了原来的unittest, 同是测试框架 确实感觉到pytest更加便捷 这边分享给大家我得学习心得 先给大家分享下学习资源 1 官方文档 pytest 官方…...
2024年3月全国计算机等级考试真题(二级C语言)
😀 第1题 下列叙述中正确的是 A. 矩阵是非线性结构 B. 数组是长度固定的线性表 C. 对线性表只能作插入与删除运算 D. 线性表中各元素的数据类型可以不同 题目解析: A. 矩阵是非线性结构 错误。矩阵通常是二维数组,属…...
GitHub高级筛选小白使用手册
GitHub高级筛选小白使用手册 GitHub 提供了强大的搜索功能,允许用户通过高级筛选器来精确查找仓库、Issues、Pull Requests、代码等。下面是一些常用的高级筛选用法,帮助你更高效地使用 GitHub 搜索功能。 目录 搜索仓库搜索Issues搜索Pull Requests搜…...
如何用腾讯云建站做好一个多语言的建筑工程网站?海外用户访问量提升3倍!分享我的经验
作为新疆地区领先的工程建筑企业,我们深知在数字化浪潮中,一个专业、高效且具备国际视野的官方网站是企业形象与业务拓展的“门面担当”。然而,传统的建站流程复杂、技术门槛高、多语言适配难等问题,曾让我们在数字化转型中举步维…...
SpringBoot-配置文件中敏感信息的加密保姆级教程
前言 公司安全部门检查,要求系统配置文件中的敏感信息如数据库密码等,进行加密处理,否则将受到公司的安全处罚,无奈只要按照公司要求,对springboot项目配置文件的敏感信息进行加密和解密处理。详细教程如下。 快速上…...
数据结构——串
串是一种数据元素为字符的特殊的线性表。 1. 串的定义 零个或多个字符(字母、数字或其他字符)组成的有限序列。记为 S"a1a2...an"S"a1a2...an",长度为 nn,空串长度为0。 2.串的术语 串长度…...
使用python爬取网络资源
整体思路 网络资源爬取通常分为以下几个步骤: 发送 HTTP 请求:使用requests库向目标网站发送请求,获取网页的 HTML 内容。解析 HTML 内容:使用BeautifulSoup库解析 HTML 内容,从中提取所需的数据。处理数据ÿ…...
【MySQL | 七、存储引擎是什么?】
存储引擎是什么?作用于哪里? 1. 存储引擎的定义 存储引擎(Storage Engine)是数据库管理系统中负责 数据的存储、检索和管理 的核心组件。它决定了数据如何存储在磁盘上,以及如何从磁盘中读取数据。存储引擎是数据库与…...
Linux -- 进程间通信(IPC)-- 进程间通信、管道、system V 共享内存、system V 消息队列、责任链模式 、system V 信号量
一、什么是进程间通信 1.进程间通信的目的 数据传输:一个进程需要将它的数据发送给另一个进程。资源共享:多个进程之间共享同样的资源。通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发…...
远程登录服务(ssh)
一、远程登录服务概述 1. 概念 远程登录服务就像是一个神奇的桥梁,它让你能够跨越物理距离,通过网络连接到另一台计算机上进行操作。无论你身在何处,只要有网络连接,你就可以像坐在目标计算机前一样进行各种操作。 2. 功能 分享…...
【从零实现Json-Rpc框架】- 项目设计篇
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
EtherCAT转CANopen配置CANopen侧的PDO映射
EtherCAT转CANopen配置CANopen侧的PDO映射 在工业自动化领域,EtherCAT和CANopen是两种广泛应用的通信协议。它们各自具有独特的优势,但在某些应用场景下,需要将这两种协议进行转换以实现设备间的高效数据交换。本文将详细介绍如何在使用Ethe…...
Vite管理的Vue3项目中monaco editer的使用以及组件封装
文章目录 背景环境说明安装流程以及组件封装引入依赖封装组件 外部使用实现效果 v-model实现原理 背景 做oj系统的时候,需要使用代码编辑器,决定使用Monaco Editor,但是因为自身能力问题,读不懂官网文档,最终结合ai和网友的帖子成功引入&…...