JVM:ZGC详解(染色指针,内存管理,算法流程,分代ZGC)
1,ZGC(JDK21之前)
ZGC 的核心是一个并发垃圾收集器,所有繁重的工作都在Java 线程继续执行的同时完成。这极大地降低了垃圾收集对应用程序响应时间的影响。
- ZGC为了支持太字节(TB)级内存,设计了基于页面(page)的分页管理(类似于G1的分区Region);
- ZGC为了能够快速对对象进行并发标记和并发移动,对内存空间重新进行了划分,这就是ZGC中新引入的指针染色;
- 仅支持 Linux 64 位系统,不支持 32 位平台。因此也不支持压缩指针。
- 同时ZGC为了能更加高效地管理内存,设计了物理内存和虚拟内存两级内存管理。
- 支持NUMA-Aware内存分配:在NUMA(非统一内存访问架构)架构下,每个处理器核心有独立管理的本地内存,访问其他核心的内存较慢。ZGC通过优先在请求线程所在处理器的本地内存上分配对象,优化了内存访问效率。
1.1,传统对象地址
【传统GC指令地址设计】在ZGC出现之前,GC信息被保存在对象头的Mark Word当中。64位JVM主要指的是JVM可以使用64位的地址空间(即64位指针),而不是每个对象的大小必须是64字节。
- 对象头:
- Mark Word:
- 存储对象的哈希码(如果是第一次计算哈希时会计算并缓存)。
- GC状态:用于GC时标记对象的状态(如是否可达)。
- 锁信息:在对象被锁定时存储锁的状态,如轻量级锁、重量级锁、偏向锁等。
- Klass Pointer(类指针):指向该对象的类元数据,实际上是指向对象的类信息(
Class
对象)。该指针指向Class对象的内存地址,通过这个指针,JVM能够查找到该对象的类型信息,Class对象包含了该类的结构信息,比如类的字段、方法以及接口等。- 实例数据:实例数据部分存储对象的实际数据。即类中定义的实例变量(属性)。这些数据按照类的字段顺序在内存中排列。例如,如果一个类中有一个int类型和一个String类型的字段,实例数据部分就依次存储这两个字段的值。
- 对齐填充:为了确保对象在内存中的对齐,JVM通常会对对象的内存布局进行填充。例如,32位机器上,通常要求对象的大小是8的倍数。如果对象的实际数据占用内存不满足对齐要求,JVM会插入额外的填充字节。
public class Person {int age;String name; }
内存布局示意图(假设64位系统,按默认的内存布局):总共占用的内存可能是 8 + 8 + 4 + 8 = 28字节,但为了满足对齐要求,可能会有额外的填充字节,最终对象的大小通常会是32字节(假设JVM默认按照8字节对齐)。
1.2,ZGC对象地址
【ZGC虚拟地址空间】HotSpot虚拟机的几种收集器有不同的标记实现方案,有的把标记直接记录在对象头上(如Serial收集器),有的把标记记录在与对象相互独立的数据结构上(如G1、Shenandoah使用了一种相当于堆内存的1/64大小的,称为BitMap的结构来记录标记信息),ZGC的染色指针直接把标记信息记在引用对象的指针上(这个时候,与其说可达性分析是遍历对象图来标记对象,还不如说是遍历“引用图”来标记“引用”了),通过这四个标志位,JVM 可以从指针上直接看到对象的三色标记状态(Marked0、Marked1)、是否进入了重分配集(Remapped)、是否需要通过 finalize 方法来访问到(Finalizable)等信息。无需进行对象访问就可以获得 GC 信息,这大大提高了 GC 效率。 🚀🚀🚀
- Remappd:对象被重新映射到新内存位置(移动过)。
- M1:上次GC标识过。
- M0:本次GC标识过。
注意:X86_64 处理器硬件的限制,目前 X86_64 处理器地址线只有 48 条(CPU设计时位为了降低成本,仅支持48位地址),除去 4 位染色指针,剩余可用对象地址 44 位,理论上支持 16TB 的内存。
【问题】那为啥总说ZGC最大支持内存是4TB?
【答案】目前支持的 4TB 只是人为的限制,主要是为了平衡性能、稳定性和实际需求(压根没有4TB的机器)。由于 42 位(0-41)地址最大的寻址空间就是 4TB,这就是 ZGC 一直宣称自己最大支持 4TB 内存的原因。
6 4 4 4 4 4 03 7 6 5 2 1 0 +-------------------+-+----+-----------------------------------------------+ |00000000 00000000 0|0|1111|11 11111111 11111111 11111111 11111111 11111111| +-------------------+-+----+-----------------------------------------------+ | | | | | | | * 41-0 Object Offset (42-bits, 4TB address space) | | | | | * 45-42 Metadata Bits (4-bits) 0001 = Marked0 | | 0010 = Marked1 | | 0100 = Remapped | | 1000 = Finalizable | | | * 46-46 Unused (1-bit, always zero) | * 63-47 Fixed (17-bits, always zero)
1.3,ZGC内存管理
【物理内存】物理内存非常直观,就是真实存在的,其大小就是插在主板内存槽上的内存条的容量大小。
【虚拟内存】虚拟地址是操作系统根据 CPU 的寻址能力,支持访问的虚拟空间,比如前些年大家使用的 32 位操作系统,对应的虚拟地址空间为 0~232 ,即 0~4GB,而我们计算机的物理内存可能只有 512MB,所以涉及物理内存和虚拟内存的映射。
【操作系统内存映射机制】虚拟内存和物理内存大小并不匹配,所以需要一个额外的机制把两者关联起来。当程序试图访问一个虚拟内存页面时,这个请求会通过操作系统来访问真正的内存。
- 首先到页面表中查询该页是否已映射到物理页框中,并记录在页表中。
- 如果已记录,则会通过内存管理单元(Memory Management Unit,MMU)把页码转换成页框码(frame),并加上虚拟地址提供的页内偏移量形成物理地址后去访问物理内存;
- 如果未记录,则意味着该虚拟内存页面还没有被载入内存,这时 MMU 就会通知操作系统发生了一个页面访问错误(也称为缺页故障(page fault)),接下来系统会启动所谓的 “请页” 机制,即调用相应的系统操作函数,判断该虚拟地址是否为有效地址。
- 如果是有效的地址,就从虚拟内存中将该地址指向的页面读入内存中的一个空闲页框中,并在页表中添加相对应的表项,最后处理器将从发生页面错误的地方重新开始运行;
- 如果是无效的地址,则表明进程在试图访问一个不存在的虚拟地址,此时操作系统将终止此次访问。
- 在请页成功之后,内存中已经没有空闲物理页框了,这时,系统必须启动所谓的 “交换” 机制,即调用相应的内核操作函数,在物理页框中寻找一个当前不再使用或者近期可能不会用到的页面所占据的页框。找到后,就把其中的页移出,以装载新的页面。对移出页面根据两种情况来处理:
- 如果该页未被修改过,则删除它;
- 如果该页曾经被修改过,则系统必须将该页写回辅存。
【问题】Java虚拟机作为一个普普通通的进程,这样随意重新定义内存中某些指针的其中几位,操作系统是否支持?处理器是否支持?
【答案】程序代码最终都要转换为机器指令流交付给处理器去执行,处理器可不会管指令流中的指针哪部分存的是标志位,哪部分才是真正的寻址地址,只会把整个指针都视作一个内存地址来对待。在Solaris/SPARC平台上,硬件层面直接支持虚拟地址掩码,能够轻松忽略染色指针中的标志位,从而简化了ZGC的设计。而在x86-64平台上,没有类似的硬件支持,ZGC设计者必须依赖其他的技术手段,主要是虚拟内存映射技术,以弥补这一缺陷。
【答案】ZGC仅支持64位系统,它把64位虚拟地址空间划分为多个子空间。当创建对象时,首先在堆空间申请一个虚拟地址,该虚拟地址并不会映射到真正的物理地址。同时,ZGC 会在 M0、M1、Remapped 空间中为该对象分别申请一个虚拟地址,且三个虚拟地址都映射到同一个物理地址。ZGC 就是通过这三个视图空间的切换,来完成并发的垃圾回收。
假如你要去 “中山一路3号” 这个地址拜访一位朋友,根据你所处城市的不同,譬如在广州或者在上海,是能够通过这个“相同的地址”定位到两个完全独立的物理位置的,这时地址与物理位置是一对多关系映射。
1.4,读屏障
当程序尝试读取一个对象时,读屏障会触发以下操作:
- 检查指针染色:读屏障首先检查指向对象的指针的颜色信息。
- 处理移动的对象:如果指针表示对象已经被移动(例如,在垃圾回收过程中),读屏障将确保返回对象的新位置。
- 确保一致性:通过这种方式,ZGC 能够在并发移动对象时保持内存访问的一致性,从而减少对应用程序停顿的需要。
// 伪代码示例,展示读屏障的概念性实现 Object* read_barrier(Object* ref) {//如果对象已经被移动,返回新地址if (is_forwarded(ref)) {return get_forwarded_address(ref); // 获取对象的新地址}return ref; // 对象未移动,返回原始引用 }
读屏障可能被GC线程和业务线程触发,并且只会在访问堆内对象时触发,访问的对象位于GC Roots时不会触发,这也是扫描GC Roots时需要STW的原因。
1.5,ZGC工作流程
【初始态】在 ZGC 中,内存被划分为固定大小的页面(通常是 2MB),这些页面用于存储对象和管理内存。
【初始标记】ZGC 标记所有从 GC Root 直接可达的对象。
【并发标记&重新映射】
- 【初次GC】从GC Root开始对堆中对象进行可达性分析。
- 【二次GC】把上次GC "并发迁移" 阶段迁移的对象指针修正指向到新分区。
【再标记】标记上一次标记过程新产生的对象。
【并发转移准备】为对象转移做一些前置准备,比如引用处理、弱引用清理和重定位集选择等。
【初始转移】迁移根节点直接引用的对象到新分区,这个阶段需要停顿所有的应用线程(STW),但由于只迁移根节点直接引用的对象,所以停顿时间很短。
【并发转移】并发迁移“并发标记”阶段标记的对象到新分区(对象引用指针未修改,仍指向旧分区)。
其实,在标记阶段存在两个地址视图M0和M1,上面的过程显示只用了一个地址视图。之所以设计成两个,是为了区别前一次标记和当前标记。第二次进入并发标记阶段后,地址视图调整为M1,而非M0。
【问题】为何并发转移阶段,对象已转移至新分区后,却没有修改线程栈上实际的引用,依然指向旧分区?
【答案】因为如果此时再扫描线程栈,修改引用地址,要扫描的量太大,效率太低。刚好下一个GC周期也要进行扫描标记,可以利用扫描标记的时间,同时把对象引用修正指向到新分区,以此提升效率,减少停顿时间。
【问题】并发转移阶段对象已迁移,但引用指针仍指向旧分区,如何保证旧分区被清理后对象仍然可以访问?
【答案】由于未修改对象引用指针,为防止旧分区被清理,导致对象找不到的问题,此处引入了读屏障和转发表。
- 转发表记录了对象从旧位置到新位置的映射关系,实现类似一个hash表,key是旧分区的位置,value是新分区的位置,此时当访问旧位置的对象时,通过转发表可以获取新位置。这样可以避免在整个堆空间中更新对象引用的开销,因为只需要更新转发表中的条目即可。
- 读屏障的作用是在读取对象引用时,检查对象的标记状态并获取转发表中的映射关系。通过读屏障,ZGC能够在读取对象引用时,将访问重定向到新位置,以确保对象的访问仍然有效。如下图:每次读取引用时会触发一次读屏障。
1.6,ZGC性能
不仅应用在并发转移阶段,还应用在并发标记阶段:将对象设置为已标记,传统的垃圾回收器需要进行一次内存访问,并将对象存活信息放在对象头中;而在ZGC中,只需要设置指针地址的第42-45位即可,并且因为是寄存器访问,所以速度比访问内存更快。
【ZGC触发时机】
- 阻塞内存分配请求触发:当垃圾来不及回收,垃圾将堆占满时,会导致部分线程阻塞。应当避免出现这种触发方式。日志中关键字是“Allocation Stall”。
- 基于分配速率的自适应算法:最主要的GC触发方式,其算法原理可简单描述为”ZGC根据近期的对象分配速率以及GC时间,计算出当内存占用达到什么阈值时触发下一次GC”。通过ZAllocationSpikeTolerance参数控制阈值大小,该参数默认2,数值越大,越早的触发GC。通过调整此参数解决了一些问题。日志中关键字是“Allocation Rate”。
- 基于固定时间间隔:通过ZCollectionInterval控制,适合应对突增流量场景。流量平稳变化时,自适应算法可能在堆使用率达到95%以上才触发GC。流量突增时,自适应算法触发的时机可能会过晚,导致部分线程阻塞。通过调整此参数解决流量突增场景的问题,比如定时活动、秒杀等场景。日志中关键字是“Timer”。
- 主动触发规则:类似于固定间隔规则,但时间间隔不固定,是ZGC自行算出来的时机,服务因为已经加了基于固定时间间隔的触发机制,所以通过-ZProactive参数将该功能关闭,以免GC频繁,影响服务可用性。 日志中关键字是“Proactive”。
- 预热规则:服务刚启动时出现,一般不需要关注。日志中关键字是“Warmup”。
- 外部触发:代码中显式调用System.gc()触发。 日志中关键字是“System.gc()”。
- 元数据分配触发:元数据区不足时导致,一般不需要关注。 日志中关键字是“Metadata GC Threshold”。
2,分代ZGC
2.1,JDK21在ZGC上的升级
【支持分代】增加了对分代的支持,提高垃圾回收的性能。
- JDK21之前:ZGC 的堆内存也是基于 Region 来分布,不过 ZGC 是不区分新生代老年代的。
- JDK21之后:分代ZGC为年轻和年老的对象保留不同的世代,这将使 ZGC 能够更频繁地收集年轻对象,因为年轻对象往往在很年轻时就会死亡。
【分代的必要性】在程序运行过程中很多对象生命期较短,对这些短生命期对象进行回收,可以回收很多内存空间;剩余那部分生命期较长的对象,一般也不会被回收掉,所以对这些长生命期对象进行回收,可以回收的内存就比较有限了。不应该对所有对象都一视同仁,对于那些生命期短的对象要经常回收,获取高收益,对于那些生命期长的对象尽量不要浪费时间去回收。
- 配置参数简单:-XX:+UseZGC -XX:+ZGenerational +Xmx 64g
- 自动调节:
不需要配置 -Xmn (年轻代、老年代动态变化)
不需要配置 -XTenuringThreshold (什么时候晋升老年代动态变化)
不需要配置 -XX:InitiatingHeapOccupancyPercent (G1 混合回收)
不需要配置 -XX:ConcGCThreads (GC线程数动态变化)
ZGC 采用一种称为彩色指针的技术。为了避免掩码指针的开销,ZGC 采用了多重映射技术。多重映射是指将多段虚拟内存映射到同一段物理内存。 ZGC使用Java堆的3个视图(“marked0”,“marked1”,“remapped”),即3种不同“颜色”的堆指针和同一个堆的3个虚拟内存映射。因此,操作系统可能会报告 3 倍大的内存使用量。例如,对于 512 MB 的堆,报告的已提交内存可能高达 1.5 GB,不包括堆以外的内存。注意:多重映射会影响报告的使用内存,但物理上堆仍将使用 512 MB 的 RAM。这有时会导致一个有趣的效果,即进程的 RSS 看起来大于物理 RAM 的数量。
2.2,如何解决ZGC的RSS指标翻3倍的问题?
【ZGC染色指针】如果读者了解过普通ZGC,就一定了解它的颜色指针,通过虚拟内存高位的4个bit位标志当前的引用垃圾回收状态。这4个bit位中,有一位没有使用,而其它3位同一时间内只有1位为1,但是不管哪位为1,都要指向相同的物理地址,也就映射3次,最终造成普通ZGC的RSS指标(RSS统计的虚拟内存地址)翻了3倍。
【分代ZGC染色指针】分代ZGC需要更多的标记位,如果还使用muli-map的方式,第一可用内存会因为多加标记位减少;第二RSS指标可能是实际使用内存的4*4*4(每代4个指针)倍?所以分代ZGC在把虚拟内存交给操作系统的时候,需要清除标记位。这也是为啥ZGC一开始不支持分代的原因。
- 保存在内存中的Java对象引用地址是有颜色的。
- 读取出来处理的时候,通过 Load Barrier 将颜色去掉,之后再去寻址。
- 存储的时候,通过 Store Barrier 将颜色恢复。
PS:Load Barrier 和 Store Barrier 是 ZGC 消耗 CPU 大的一个重要原因。
对象的有效地址为46位,相对于64位操作系统对用户空间47位的限制,只少了1位,比起普通ZGC多了2位(64TB)。同时颜色指针放在了低位,有12位之多。load color(R):染色指针,跟读屏障有关。
【操作系统地址-无色指针地址】当JVM把分代ZGC中的虚拟地址交给操作系统使用时,会去掉12位染色指针,转换为如下的形式。所以操作系统看到的就是标准的虚拟地址(RSS不会翻倍),这个过程通过读屏障来实现。
2.3,如何在不产生额外成本的情况下去除和恢复颜色?
【ZGC读屏障】检查指针颜色是否是好的;普通ZGC在度屏障中先加载地址(rbx寄存器中的地址转换为虚拟地址)到rax寄存器,然后通过颜色指针验证地址是否有效(testq),如果不是有效地址则进入slow_path中(remap操作完成对象指针修复,转变为有效地址,转发表)。由于指针信息直接给到了操作系统,所以普通ZGC需要将三个虚拟地址映射到同一个物理地址上。
【分代ZGC读屏障】分代ZGC先加载地址到rax寄存器中,然后右移address_shift位(右移位数于GC阶段有关),然后判断CF和ZF是否都为0(ja指令的作用),如果该条件成立,则进入slow_path完成对象指针修复(并发标记阶段的指针修复)。
【address_shift操作】右移最右移除的低位为1时CF为1,否则CF为0。右移操作得到的结果为全0,那么ZF为1,否则ZF为0。由于地址右移时不会得到全0结果,所以这里ZF可以认为是一个0常量。关键要看CF,而CF的结果由address_shift所决定。
一共4中情况,分别对应于不同的GC阶段的有效地址,有效地址的4个R位中根据当前所处阶段,只有1位为1。在每种情况中address_shift的值恰好可以把墨绿色的唯一的1移除掉(绿色右侧的移除)。由于JVM中地址是按8对齐的,对于一个有效的地址来说最小为8,所以低3位一定为0(00001000=8),本着能省就省的宗旨,低3位的0和读标记区进行了重叠。
由于在读地址的时候把指针信息删除了,所以在写的时候,就要把信息恢复,分代ZGC不得不在写屏障完成这个操作。在写入的时候,12个染色指针都需要参与。
【ZGC写操作】普通ZGC写入的时候只是保存了地址信息。
【分代ZGC写操作】分代ZGC在写入时则多做了4个操作。前两个操作合起来就是检测地址是否需要处理,如果需要处理进入slow_path中处理,这里slow_path主要做了如下操作:
并行年轻代SATB 染色;
并行老年代SATB 染色;
并行Remember Set 染色。
后两条指令这是把地址左移,然后把颜色指针还原。由此可见,在写入上必然会有性能损耗。
相关文章:
JVM:ZGC详解(染色指针,内存管理,算法流程,分代ZGC)
1,ZGC(JDK21之前) ZGC 的核心是一个并发垃圾收集器,所有繁重的工作都在Java 线程继续执行的同时完成。这极大地降低了垃圾收集对应用程序响应时间的影响。 ZGC为了支持太字节(TB)级内存,设计了基…...
在 Ubuntu 上安装和配置 Redis
在 Ubuntu 上安装和配置 Redis,并使用发布-订阅(Pub/Sub)功能,可以按照以下步骤进行: 一、安装 Redis 1. 更新包列表 首先,更新本地的包列表以确保获取到最新的软件包信息: sudo apt update…...
【WPS】【WORDEXCEL】【VB】实现微软WORD自动更正的效果
1. 代码规范方面 添加 Option Explicit:强制要求显式声明所有变量,这样可以避免因变量名拼写错误等情况而出现难以排查的逻辑错误,提高代码的健壮性。使用 On Error GoTo 进行错误处理:通过设置错误处理机制,当代码执行…...
相机SD卡照片数据不小心全部删除了怎么办?有什么方法恢复吗?
前几天,小编在后台友收到网友反馈说他在整理相机里的SD卡,原本是想把那些记录着美好瞬间的照片导出来慢慢欣赏。结果手一抖,不小心点了“删除所有照片”,等他反应过来,屏幕上已经显示“删除成功”。那一刻,…...
【机器学习:十四、TensorFlow与PyTorch的对比分析】
1. 发展背景与社区支持 1.1 TensorFlow的背景与发展 TensorFlow是Google于2015年发布的开源深度学习框架,基于其前身DistBelief系统。作为Google大规模深度学习研究成果的延续,TensorFlow从一开始就定位为生产级框架,强调跨平台部署能力和性…...
从零搭建一个Vue3 + Typescript的脚手架——day1
1.开发环境搭建 (1).配置vite vite简介 Vite 是一个由尤雨溪开发的现代化前端构建工具,它利用了浏览器对 ES 模块的原生支持,极大地提升了开发服务器的启动速度和热更新效率。Vite 不仅适用于 Vue.js,还支持 React、Svelte 等多种框架&…...
unity打包sdk热更新笔记
基础打包需要知识: 安装包大小不要超过2G,AB包数量过多会影响加载和构建,多次IO,用Gradle打包,要支持64位系统,不同的渠道包:让做sdk的人支持,提供渠道包的打包工具 配置系统环境变量…...
算法-贪心算法简单介绍
下面是贪心算法视频课的导学内容. 目录 1. 什么是贪心算法?2. 贪心算法简单的三个例子:1. 找零问题2. 最小路径和问题3. 背包问题 3. 贪心算法的特点4. 贪心算法学习的方式? 1. 什么是贪心算法? 简单来说, 我们称以局部最优进而使得全局最优的一种思想实现出来的算法为贪心…...
1Hive概览
1Hive概览 1hive简介2hive架构3hive与Hadoop的关系4hive与传统数据库对比5hive的数据存储 1hive简介 Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能。 其本质是将SQL转换为MapReduce/Spark的任务进…...
Linux SUID提权
文章目录 1. SUID/SGID2. 查找SUID文件3. SUID/SGID提权3.1 SUID配置不当3.2 SUID systemctl提权3.3 $PATH变量劫持 参考 1. SUID/SGID SUID(Set User ID)意味着如果某个用户对属于自己的文件设置了这种权限,那么其他用户在执行这一脚本时也…...
RabbitMQ确保消息可靠性
消息丢失的可能性 支付服务先扣减余额和更新支付状态(这俩是同步调用),然后通过RabbitMq异步调用支付服务更新订单状态。但是有些情况下,可能订单已经支付 ,但是更新订单状态却失败了,这就出现了消息丢失。…...
用plotly制作一条带颜色的时间轴,显示学习情况
前一篇文章我写到用matplotlib制作一条带颜色的时间轴,显示学习情况-CSDN博客,这是我在工作地方写的程序,我回家后发现家里的笔记本用不了matplotlib,所以我尝试用plotly这另外的模块也写一段程序,让我的程序能够回家使…...
MySQL:索引
目录 1.MySQL索引是干什么的 2.铺垫知识 3.单个page的理解 4.页目录 单页情况 多页情况 1.MySQL索引是干什么的 MySQL的索引是提高查询效率,主要提高海量数据的检索速度。 2.铺垫知识 操作系统与磁盘之间IO的基本单位是4kb。 数据库是一个应用层软件&#…...
Kylin: `GLIBC_2.34‘ not found
需要查看服务器GLIBC版本 strings /lib64/libc.so.6 |grep GLIBC_如果没有,有两种办法,一种是libc.so.6降级,但是这样很容易将服务器搞崩溃 所以可以尝试下载对应版本 glibc 打包编译,重新建立软连,下列是RPM资源可以…...
ASP.NET Core - 依赖注入(四)
ASP.NET Core - 依赖注入(四) 4. ASP.NET Core默认服务5. 依赖注入配置变形 4. ASP.NET Core默认服务 之前讲了中间件,实际上一个中间件要正常进行工作,通常需要许多的服务配合进行,而中间件中的服务自然也是通过 Ioc…...
【全套】基于分类算法的学业警示预测信息管理系统
【全套】基于分类算法的学业警示预测信息管理系统 【摘 要】 随着网络技术的发展基于分类算法的学业警示预测信息管理系统是一种新的管理方式,同时也是现代学业预测信息管理的基础,利用互联网的时代与实际情况相结合来改变过去传统的学业预测信息管理中…...
《零基础Go语言算法实战》【题目 2-25】goroutine 的执行权问题
《零基础Go语言算法实战》 【题目 2-25】goroutine 的执行权问题 请说明以下这段代码为什么会卡死。 package main import ( "fmt" "runtime" ) func main() { var i byte go func() { for i 0; i < 255; i { } }() fmt.Println("start&quo…...
回归预测 | MATLAB实RVM相关向量机多输入单输出回归预测
回归预测 | MATLAB实RVM相关向量机多输入单输出回归预测 目录 回归预测 | MATLAB实RVM相关向量机多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 RVM-Adaboost相关向量机集成学习多输入单输出回归预测是一种先进的机器学习方法,用于处理…...
【OJ刷题】同向双指针问题3
这里是阿川的博客,祝您变得更强 ✨ 个人主页:在线OJ的阿川 💖文章专栏:OJ刷题入门到进阶 🌏代码仓库: 写在开头 现在您看到的是我的结论或想法,但在这背后凝结了大量的思考、经验和讨论 目录 1…...
数据挖掘实训:天气数据分析与机器学习模型构建
随着气候变化对各行各业的影响日益加剧,精准的天气预测已经变得尤为重要。降雨预测在日常生活中尤其关键,例如农业、交通和灾害预警等领域。本文将通过机器学习方法,利用历史天气数据预测明天是否会下雨,具体内容包括数据预处理、…...
RAG 带来的一些问题
RAG (Retrieval-Augmented Generation) 提高了查询的准确性,但也引入了一些新的问题。主要问题集中在信息检索和生成模型的结合方式上,这些问题影响了系统的性能、效率和输出质量。以下是 RAG 带来的主要问题以及相应的解决方法。 1. 依赖外部检索系统的…...
大疆上云API基于源码部署
文章目录 大疆上云API基于源码部署注意事项1、学习官网2、环境准备注意事项3、注册成为DJI开发者4、下载前后端运行所需要的包/依赖前端依赖下载后端所需要的Maven依赖包 用到的软件可以在这里下载5、MySQL数据库安装安装MySQL启动MySQL服务在IDEA中配置MySQL的连接信息 6、Red…...
【Python系列】Python 中使用 pymysql 连接 MySQL 数据库进行数据查询
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
【数据结构学习笔记】19:跳表(Skip List)
介绍 跳表是一个能在 O ( n l o g n ) O(nlogn) O(nlogn)时间完成查找、插入、删除的数据结构,相比于树形结构优点就是很好写(所以也用于实现Redis ZSet)。其核心思想就是维护一个元素有序的,能随机提升索引层数的链表。最下面一…...
《计算机网络》课后探研题书面报告_网际校验和算法
网际校验和算法 摘 要 本文旨在研究和实现网际校验和(Internet Checksum)算法。通过阅读《RFC 1071》文档理解该算法的工作原理,并使用编程语言实现网际校验和的计算过程。本项目将对不同类型的网络报文(包括ICMP、TCP、UDP等&a…...
【论文阅读+复现】High-fidelity Person-centric Subject-to-Image Synthesis
以人物为中心的主体到图像的高保真合成,CVPR2024 code:CodeGoat24/Face-diffuser: [CVPR2024] Official implementation of High-fidelity Person-centric Subject-to-Image Synthesis. paper:2311.10329 背景 研究问题:这篇文…...
Flink集成TDEngine来批处理或流式读取数据进行流批一体化计算(Flink SQL)拿来即用的案例
Flink 以其流批一体化的编程模型而备受青睐。它支持高吞吐、低延迟的实时流计算,同时在批处理方面也表现出色。Flink 提供了丰富的 API,如 DataStream API 和 DataSet API,方便开发者进行数据处理操作,包括转换、聚合、连接等,使得开发者能够轻松构建复杂的数据处理逻辑。…...
Zookeeper特性与节点数据类型详解
1、 Zookeeper介绍 ZooKeeper 是一个开源的分布式协调框架,是Apache Hadoop 的一个子项目,主要用来解决分布式集群中应用系统的一致性问题。Zookeeper 的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集…...
C# HslCommunication库
C# HslCommunication库是一个用于建立TCP连接并进行Modbus通讯的库。下面将详细介绍如何使用该库进行TCP通讯。 首先,需要在C#项目中引用HslCommunication库。 创建一个TCP连接对象,可以使用HslCommunication.ModBus.ModbusTcpNet类,例如&am…...
springMVC实现文件上传
目录 一、创建项目 二、引入依赖 三、web.xml 四、编写上传文件的jsp页面 五、spring-mvc.xml 六、controller 七、运行 一、创建项目 二、引入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.o…...
【深度学习】Windows系统Anaconda + CUDA + cuDNN + Pytorch环境配置
在做深度学习内容之前,为GPU配置anaconda CUDA cuDNN pytorch环境,在网络上参考了很多帖子,但pytorch的安装部分都有些问题或者比较复杂繁琐,这里总结了相对简单快速的配置方式 文章目录 AnacondaCUDAcuDNNpytorchtorchtorchau…...
springboot整合rabbitmq
1. 添加依赖 首先,在你的 pom.xml 文件中添加 RabbitMQ 的依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency> 2. 配置 RabbitMQ …...
【React】脚手架进阶
目录 暴露webpack配置package.json的变化修改webpack.config.js配置less修改域名、端口号浏览器兼容处理处理跨域 暴露webpack配置 react-scripts对脚手架中的打包命令进行封装,如何暴露这些打包配置呢?上篇写到在package.json中的scripts配置项中有eje…...
Unreal Engine 5 (UE5) Metahuman 的头部材质
在图中,你展示了 Unreal Engine 5 (UE5) Metahuman 的头部材质部分,列出了头部材质的多个元素。以下是对每个部分的解释: 材质解释 Element 0 - MI_HeadSynthesized_Baked 作用: 这是 Metahuman 的主要头部材质,控制整…...
当自动包布机遇上Profinet转ModbusTCP网关,“妙啊”,工业智能“前景无限
在自动化控制技术日新月异的当下,Profinet与ModbusTCP这两种协议在工业通信领域占据着举足轻重的地位。ModbusTCP是基于以太网的串行通信协议,而Profinet则是依托工业以太网的现场总线协议。它们在数据传输速度、实时性表现以及兼容性等方面各具特色。不…...
Elasticsearch 批量导入数据(_bluk方法)
官方API:https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html 建议先看API POST /<索引名>/_bulk 格式要求: POST _bulk { "index" : { "_index" : "test", "_id" : &q…...
lammps应用于热电材料
文章目录 1.热传导理论1.热导率2.晶格振动3.晶体热容4.声子平均自由程5.傅里叶定律 2.lammps计算Ar热导率3.lammps模拟SiGe热电材料4.平衡分子动力学(EMD) 1.热传导理论 1.热导率 热传递机制随介质材料相的不同而改变:固体(热传导)、液体(热对流)、气体(对流和辐射…...
SAP资产盘盈盘亏的过账处理、入账价值错误调整、资产减值准备
文章目录 一、SAP资产盘盈盘亏处理1、ABNAN盘盈 (往年资产) ABZON (当年资产)2、ABAVN盘亏 二、资产价值入账错了(价值多了或少了),怎么调账1、价值少了2、价值多了 三、资产减值准备1、启用重估2、指定间隔…...
Adobe与MIT推出自回归实时视频生成技术CausVid。AI可以边生成视频边实时播放!
传统的双向扩散模型(顶部)可提供高质量的输出,但存在显著的延迟,需要 219 秒才能生成 128 帧的视频。用户必须等待整个序列完成才能查看任何结果。相比之下CausVid将双向扩散模型提炼为几步自回归生成器(底部ÿ…...
MYSQL学习笔记(一):准备数据和数据库的最基本命令
前言: 学习和使用数据库可以说是程序员必须具备能力,这里将更新关于MYSQL的使用讲解,大概应该会更新30篇,涵盖入门、进阶、高级(一些原理分析);这一篇是入门准备数据和一些关于数据库的操作命令;虽然MYSQL命令很多&…...
求矩阵不靠边元素之和(PTA)C语言
求矩阵的所有不靠边元素之和,矩阵行的值m从键盘读入(2<m<10),调用自定义函数Input实现矩阵元素从键盘输入,调用Sum函数实现求和。(只考虑float型,且不需考虑求和的结果可能超出float型能表示的范围)。 函数接口定义&#x…...
仿infobip模板功能-可通过占位符配置模板内容
模仿infobip制作的模板功能,正文可在任意位置加参数的功能。如下图所示:在正文中通过{{\d}}进行占位,在使用模板时,可在此位置自定制内容,并预览效果。 代码: <template><div class"templa…...
STM32第6章、WWDG
一、简介 WWDG:全称Window watchdog,即窗口看门狗,本质上是一个能产生系统复位信号和提前唤醒中断的计数器。 特性: 是一个递减计数器。 看门狗被激活后, 当递减计数器值从 0x40减到0x3F时会产生复位(即T6位…...
没有正确使用HTTP Range Request,导致访问Azure Blob存储的视频没有实现流式播放
引文: 组里的小伙伴在修改视频播放相关的代码,修改之前的方案使用CDN转发,可以实现流式播放,修改之后的代码因为没有正确的使用Http Range Request, 导致画面访问Azure Blob存储的视频没有实现流式播放,整理下线索在这…...
React中Fiber树构建过程详解——react中render一个App组件(包含子组件)的流程详解
在 React 中,渲染一个包含子组件的组件涉及一系列底层流程,包括构建虚拟 DOM(React Element)、协调(Reconciliation)、Fiber 树管理和最终的 DOM 操作。以下是一个从底层解析的详细流程: 1. 初始…...
机器学习赋能的智能光子学器件系统研究与应用
在人工智能与光子学设计融合的背景下,科研的边界持续扩展,创新成果不断涌现。从理论模型的整合到光学现象的复杂模拟,从数据驱动的探索到光场的智能分析,机器学习正以前所未有的动力推动光子学领域的革新。据调查,目前…...
晨辉面试抽签和评分管理系统之七:面试成绩核算的三种方式
晨辉面试抽签和评分管理系统(下载地址:www.chenhuisoft.cn)是公务员招录面试、教师资格考试面试、企业招录面试等各类面试通用的考生编排、考生入场抽签、候考室倒计时管理、面试考官抽签、面试评分记录和成绩核算的面试全流程信息化管理软件。提供了考生…...
语音合成的预训练模型
语音合成的预训练模型 与 ASR(语音识别)和音频分类任务相比,语音合成的预训练模型检查点明显较少。在 Hugging Hub 上,可以找到近 300 个适合的检查点。 在这些预训练模型中,重点关注两种在 Huggingface Transformers 库中开箱即用的架构——SpeechT5 和 Massive Multili…...
Windows怎么搭建rust环境?
在Windows上搭建Rust开发环境相对简单,主要步骤如下: ### 1. 安装Rust 最简单的方法是使用官方提供的安装脚本。打开命令提示符(Command Prompt)或PowerShell,然后运行以下命令来下载并安装Rust: bash cu…...
【Flink】Flink内存管理
Flink内存整体结构图: JobManager内存管理 JVM 进程总内存(Total Process Memory)Flink总内存(Total Flink Memory):JVM进程总内存减去JVM Metaspace(元空间)和JVM Overhead(运行时开销)上图解释: JVM进程总内存为2G;JVM运行时开销(JVM Overh…...