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

G1(Garbage First)垃圾回收实战

GC过程

G1(Garbage First)是JVM中的一种垃圾回收器,设计用于处理具有大堆内存的应用程序,减少GC停顿时间,并提供更可预测的垃圾回收性能。G1的垃圾回收过程主要分为以下几个阶段:

1. 年轻代垃圾回收(Young GC)

这个阶段主要回收新生代的对象,回收发生在 Eden 区和 Survivor 区之间。

  • Eden 区满时触发:当 Eden 区的对象分配满时,触发 Young GC,将 Eden 区中存活的对象移至 Survivor 区或直接移至老年代。
  • 复制算法:Young GC 采用的是一种复制算法,将存活的对象从 Eden 和 Survivor 区中复制到新的 Survivor 区,或直接晋升到老年代。Young GC 是一个短暂停顿的过程。

2. 并发标记(Concurrent Marking)

这是老年代垃圾回收的第一个阶段,用于标记堆中的存活对象,检测哪些对象不再被引用,可以被回收。

  • 初始标记:这个阶段标记所有直接与 GC Root 相关的对象,伴随一个较短的停顿。
  • 并发标记:在应用程序运行时并发执行,递归地标记堆中所有可达的对象。这个过程不会停止应用线程。
  • 重新标记:在并发标记阶段结束后,重新标记那些由于应用线程运行而发生变化的引用,这会导致短暂的停顿。

3. 最终清理(Cleanup Phase)

最终清理阶段负责整理堆空间,并确定哪部分的内存需要进行压缩(回收空闲内存块)。

  • 清理空闲区域:标记阶段后,G1 识别出哪些区域是完全空闲的,并回收这些内存。
  • 整理部分区域:在需要时,G1 会选择部分老年代区域进行压缩,将存活的对象移动到新的内存块中,以释放连续的空闲空间。

4. 混合回收(Mixed GC)

混合回收是 G1 的一个特殊阶段,它不仅回收新生代,还会回收一部分老年代区域。

  • 触发条件:当老年代的使用率超过一定阈值时(默认 45%),混合 GC 被触发。
  • 年轻代和老年代混合回收:混合回收在每次 Young GC 的基础上,附加回收一部分老年代区域,目标是逐步减少老年代中存活对象的数量,从而避免老年代空间耗尽导致 Full GC。

5. 完全垃圾回收(Full GC)

这是 G1 回收器的最后一种回收模式,通常是应对内存压力过大时触发的。

  • Stop-the-world 停顿:Full GC 会完全暂停应用线程,并进行整个堆的垃圾回收,采用传统的单线程或多线程的标记-整理算法,效率较低,但能够回收整个堆中的所有垃圾对象。

阶段总结:

  • 年轻代回收(Young GC):只回收新生代,暂停时间短。
  • 并发标记:标记老年代中的存活对象,尽量避免停顿。
  • 混合回收(Mixed GC):回收新生代和部分老年代对象,减少 Full GC 触发的频率。
  • 完全垃圾回收(Full GC):应急阶段,全堆回收,停顿时间长。

通过这些阶段的配合,G1 能够平衡应用的吞吐量和暂停时间,适合大堆内存、低延迟要求的应用场景。

Young GC log

解析 G1 垃圾回收日志可以帮助我们更好地理解 G1 的各个阶段在实际应用中的执行情况。以下是一个典型的 G1 GC 日志片段,以及相关阶段的说明:

日志案例

[2024-10-10T14:15:23.123+0000][info ][gc,start       ] GC(0) Pause Young (Normal) (G1 Evacuation Pause)  (to-space exhausted)
[2024-10-10T14:15:23.124+0000][info ][gc,task        ] GC(0) Using 8 workers of 8 for evacuation
[2024-10-10T14:15:23.156+0000][info ][gc,phases      ] GC(0)   Pre Evacuate Collection Set: 0.0ms
[2024-10-10T14:15:23.157+0000][info ][gc,phases      ] GC(0)   Evacuate Collection Set: 32.5ms
[2024-10-10T14:15:23.157+0000][info ][gc,phases      ] GC(0)   Post Evacuate Collection Set: 0.7ms
[2024-10-10T14:15:23.157+0000][info ][gc,phases      ] GC(0)   Other: 0.4ms
[2024-10-10T14:15:23.157+0000][info ][gc,heap        ] GC(0) Eden regions: 12->0(10)
[2024-10-10T14:15:23.157+0000][info ][gc,heap        ] GC(0) Survivor regions: 0->2(2)
[2024-10-10T14:15:23.157+0000][info ][gc,heap        ] GC(0) Old regions: 0->0
[2024-10-10T14:15:23.157+0000][info ][gc,metaspace   ] GC(0) Metaspace: 14M->14M(105M)
[2024-10-10T14:15:23.157+0000][info ][gc             ] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 35.2ms

日志解析及相关阶段介绍

1. Young GC (Pause Young GC)

在日志中,我们看到以下内容:

GC(0) Pause Young (Normal) (G1 Evacuation Pause)

这表示 G1 垃圾回收器在执行一次 Young GC(年轻代垃圾回收)。Evacuation Pause 说明该 GC 事件是为了清理新生代的 Eden 区并将存活对象复制到 Survivor 区或老年代。

  • GC(0):这是本次 GC 的标识符,表示是 JVM 启动后第 0 次垃圾回收。
  • Pause Young (Normal):说明这是一次年轻代回收(Young GC),且回收过程发生了短暂停顿(STW)。
  • Evacuation Pause:G1 在 Young GC 中的对象会被从 Eden 区“撤离”(Evacuation),移动到 Survivor 区或老年代。
2. GC 任务执行
GC(0) Using 8 workers of 8 for evacuation

这说明了 G1 回收器使用了 8 个并行 GC 线程来执行对象的复制任务(Evacuation)。并行线程的使用有助于提高垃圾回收的效率,减少停顿时间。

3. GC 阶段耗时
GC(0)   Pre Evacuate Collection Set: 0.0ms
GC(0)   Evacuate Collection Set: 32.5ms
GC(0)   Post Evacuate Collection Set: 0.7ms
GC(0)   Other: 0.4ms

这些是 G1 不同阶段的耗时:

  • Pre Evacuate Collection Set:在开始实际清理之前的准备工作耗时,通常非常短,这里为 0.0ms。
  • Evacuate Collection Set:这个阶段是主要的对象移动阶段,将存活对象从 Eden 区和 Survivor 区复制到 Survivor 区或老年代,耗时 32.5ms。
  • Post Evacuate Collection Set:完成撤离之后的后续处理耗时,这里为 0.7ms。
  • Other:其他非核心操作耗时,通常与堆信息更新、统计等有关。
4. 堆状态变化
GC(0) Eden regions: 12->0(10)
GC(0) Survivor regions: 0->2(2)
GC(0) Old regions: 0->0

这些日志显示了 GC 前后各个内存区域的变化:

  • Eden regions: 12->0(10):GC 之前 Eden 区有 12 个 Region,GC 之后被清空(0),并且当前 Eden 区容量调整为 10 个 Region。
  • Survivor regions: 0->2(2):GC 之后,Survivor 区从 0 个 Region 增加到 2 个,容量为 2 个 Region。
  • Old regions: 0->0:本次 GC 未涉及老年代的对象,因此老年代保持不变。
5. Metaspace 状态
GC(0) Metaspace: 14M->14M(105M)

这里显示了 Metaspace(存放类元数据的区域)在 GC 期间的大小变化。可以看到,Metaspace 在此次 GC 过程中并没有变化,仍然占用 14MB,容量上限为 105MB。

6. GC 总耗时
GC(0) Pause Young (Normal) (G1 Evacuation Pause) 35.2ms

本次 GC 事件的总耗时为 35.2 毫秒,属于一次较快的年轻代回收。由于这是一次 Young GC,停顿时间较短(通常几十毫秒)。

分析总结

  • 这次垃圾回收是一次 年轻代垃圾回收(Young GC),主要清理了 Eden 区中的垃圾对象,并将存活的对象移至 Survivor 区或老年代。
  • G1 回收器采用并行处理,通过 8 个 GC 线程加速了对象撤离过程。
  • 本次 GC 的总耗时为 35.2ms,体现了 G1 在进行 Young GC 时较短的停顿时间。
  • 堆内存的变化显示,Eden 区得到了清理,Survivor 区得到了适量的存活对象,而老年代未被涉及。

通过这样的日志分析,可以发现 G1 回收器的回收行为及性能,帮助判断系统在垃圾回收上的表现是否达到预期,并据此优化 JVM 配置。

Mixed GC log

混合回收(Mixed GC)是 G1 垃圾回收器的一个关键特性,它不仅回收新生代(Eden 和 Survivor 区),还会同时回收部分老年代(Old Generation)中的区域。它通常在老年代占用空间超过一定阈值(默认是 45%)时触发,通过增量式回收老年代来避免 Full GC 的发生。

下面是一个典型的 G1 混合回收(Mixed GC)日志案例,以及相关阶段的详细介绍。

日志案例

[2024-10-10T14:25:35.789+0000][info ][gc,start       ] GC(15) Pause Young (Mixed) (G1 Evacuation Pause)
[2024-10-10T14:25:35.790+0000][info ][gc,task        ] GC(15) Using 8 workers of 8 for evacuation
[2024-10-10T14:25:35.830+0000][info ][gc,phases      ] GC(15)   Pre Evacuate Collection Set: 0.2ms
[2024-10-10T14:25:35.830+0000][info ][gc,phases      ] GC(15)   Evacuate Collection Set: 39.5ms
[2024-10-10T14:25:35.830+0000][info ][gc,phases      ] GC(15)   Post Evacuate Collection Set: 0.5ms
[2024-10-10T14:25:35.830+0000][info ][gc,phases      ] GC(15)   Other: 0.3ms
[2024-10-10T14:25:35.830+0000][info ][gc,heap        ] GC(15) Eden regions: 10->0(12)
[2024-10-10T14:25:35.830+0000][info ][gc,heap        ] GC(15) Survivor regions: 2->2(2)
[2024-10-10T14:25:35.830+0000][info ][gc,heap        ] GC(15) Old regions: 25->20
[2024-10-10T14:25:35.830+0000][info ][gc,metaspace   ] GC(15) Metaspace: 35M->35M(105M)
[2024-10-10T14:25:35.830+0000][info ][gc             ] GC(15) Pause Young (Mixed) (G1 Evacuation Pause) 40.1ms

日志解析及混合回收介绍

1. Mixed GC (Pause Young Mixed GC)
GC(15) Pause Young (Mixed) (G1 Evacuation Pause)

这段日志显示了一次 混合回收(Mixed GC) 事件,意味着这次回收不仅仅是 Young GC,还回收了部分老年代的内存区域。

  • Pause Young (Mixed):表示这次是 Young GC 和 Mixed GC 的混合,回收 Eden 区、Survivor 区以及部分老年代区域。
  • G1 Evacuation Pause:依旧是一次对象“撤离”(Evacuation),将存活的对象移动到 Survivor 区或老年代中,同时回收部分老年代区域的垃圾对象。
2. GC 任务执行
GC(15) Using 8 workers of 8 for evacuation

G1 使用了 8 个并行的 GC 线程来执行对象撤离任务,从 Eden 区、Survivor 区以及老年代区域中搬移对象。

3. GC 阶段耗时
GC(15)   Pre Evacuate Collection Set: 0.2ms
GC(15)   Evacuate Collection Set: 39.5ms
GC(15)   Post Evacuate Collection Set: 0.5ms
GC(15)   Other: 0.3ms

与之前的 Young GC 类似,Mixed GC 也分为几个阶段:

  • Pre Evacuate Collection Set:在准备清理前的一些初步操作,耗时 0.2 毫秒。
  • Evacuate Collection Set:这是真正执行对象撤离的阶段,耗时 39.5 毫秒,主要负责将 Eden 区的存活对象移动到 Survivor 区,将老年代的存活对象整理。
  • Post Evacuate Collection Set:完成对象撤离后的后处理,耗时 0.5 毫秒。
  • Other:一些其他辅助操作,耗时 0.3 毫秒。
4. 堆状态变化
GC(15) Eden regions: 10->0(12)
GC(15) Survivor regions: 2->2(2)
GC(15) Old regions: 25->20

这部分日志显示了堆内存区域在 GC 前后的变化:

  • Eden regions: 10->0(12):Eden 区在 GC 之前有 10 个区域,GC 之后被清空(0 个 Region),并调整了 Eden 区容量为 12 个 Region。
  • Survivor regions: 2->2(2):Survivor 区保持不变,有 2 个 Region。
  • Old regions: 25->20:老年代区域从 25 个减少到 20 个,表示部分老年代区域的垃圾对象被成功回收。
5. Metaspace 状态
GC(15) Metaspace: 35M->35M(105M)

Metaspace 没有发生变化,依然保持 35MB 的使用量,容量上限为 105MB。

6. GC 总耗时
GC(15) Pause Young (Mixed) (G1 Evacuation Pause) 40.1ms

此次混合回收(Mixed GC)总共耗时 40.1 毫秒,较一次普通的 Young GC 来说耗时略长,因为混合回收同时涉及了新生代和老年代的对象处理。

混合回收的触发条件

  • 老年代使用率阈值:当老年代使用量超过一定的阈值(默认是堆内存的 45%)时,G1 会触发并发标记阶段,标记老年代中的存活对象。
  • 并发标记完成后:当并发标记阶段完成后,G1 将在随后的 Young GC 过程中,混合回收部分老年代。这样做的好处是通过逐步清理老年代,延缓甚至避免 Full GC 的发生。

混合回收的意义

  • 减少 Full GC 频率:通过逐步清理老年代,G1 可以有效避免 Full GC 的频繁触发。Full GC 通常会暂停所有应用线程(Stop-the-World),是影响应用性能的一个大因素。
  • 可控的停顿时间:G1 的 Mixed GC 能够通过分批回收老年代内存,保持每次 GC 的停顿时间较短,避免单次 GC 占用过多时间,影响应用响应。
  • 增量回收老年代:通过多个 Mixed GC 回收部分老年代,G1 可以持续维持堆内存的健康状态,而不是等待老年代填满再执行一次耗时的 Full GC。

分析总结

这个混合回收日志显示:

  • Eden 区的对象成功撤离到 Survivor 区或老年代。
  • 老年代中的一些区域得到了回收,减少了 5 个 Region。
  • 总体上,GC 耗时 40.1ms,比普通 Young GC 稍长,但仍属于较短的停顿时间,说明 G1 的混合回收能有效控制暂停时间,避免 Full GC。

通过混合回收,G1 在回收年轻代的同时,逐步整理老年代,从而达到减少 Full GC 的目标。

Full GC log

Full GC 是 JVM 中最耗时、影响性能最大的垃圾回收事件。在 G1 垃圾回收器中,Full GC 发生的频率相对较低,但当内存紧张且老年代无法通过 Mixed GC 及时回收时,仍可能触发 Full GC。G1 的 Full GC 是通过单线程执行的 “Stop-the-World” 事件,会暂停所有应用线程,因此开发者通常尽量避免 Full GC。

接下来,我们结合一个实际 Full GC 的日志案例,逐步分析 Full GC 触发的过程、日志中的关键阶段以及相关信息。

Full GC 日志案例

[2024-10-10T14:45:55.123+0000][info ][gc,start       ] GC(25) Pause Full (G1 Evacuation Pause)
[2024-10-10T14:45:55.124+0000][info ][gc,phases,start] GC(25) Phase 1: Mark live objects
[2024-10-10T14:45:55.298+0000][info ][gc,phases      ] GC(25) Phase 1: Mark live objects 174.1ms
[2024-10-10T14:45:55.299+0000][info ][gc,phases,start] GC(25) Phase 2: Compute new object addresses
[2024-10-10T14:45:55.402+0000][info ][gc,phases      ] GC(25) Phase 2: Compute new object addresses 103.4ms
[2024-10-10T14:45:55.402+0000][info ][gc,phases,start] GC(25) Phase 3: Adjust pointers
[2024-10-10T14:45:55.523+0000][info ][gc,phases      ] GC(25) Phase 3: Adjust pointers 121.2ms
[2024-10-10T14:45:55.523+0000][info ][gc,phases,start] GC(25) Phase 4: Evacuate Collection Set
[2024-10-10T14:45:55.779+0000][info ][gc,phases      ] GC(25) Phase 4: Evacuate Collection Set 255.9ms
[2024-10-10T14:45:55.780+0000][info ][gc,heap        ] GC(25) Eden regions: 10->0(12)
[2024-10-10T14:45:55.780+0000][info ][gc,heap        ] GC(25) Survivor regions: 2->2(2)
[2024-10-10T14:45:55.780+0000][info ][gc,heap        ] GC(25) Old regions: 55->20
[2024-10-10T14:45:55.780+0000][info ][gc,metaspace   ] GC(25) Metaspace: 45M->44M(100M)
[2024-10-10T14:45:55.780+0000][info ][gc             ] GC(25) Pause Full (G1 Evacuation Pause) 657.4ms

日志解析及 Full GC 介绍

1. Full GC 事件开始
GC(25) Pause Full (G1 Evacuation Pause)

这次事件是一次 Full GC,表示整个堆(包括 Eden 区、Survivor 区和老年代)都被回收。

  • Pause Full:所有应用线程都被暂停,即“Stop-the-World”。
  • G1 Evacuation Pause:和年轻代和混合回收类似,Full GC 也执行了对象撤离(Evacuation),但这次是整个堆的对象处理。
2. Phase 1: Mark live objects
GC(25) Phase 1: Mark live objects 174.1ms

第一阶段是 标记存活对象。G1 会遍历整个堆(包括年轻代和老年代),标记所有存活的对象。这个过程耗时 174.1 毫秒。对于 Full GC,这个阶段是单线程的,会导致长时间的停顿。

3. Phase 2: Compute new object addresses
GC(25) Phase 2: Compute new object addresses 103.4ms

第二阶段是 计算新对象的地址。由于 G1 是区域化管理堆内存的,标记完成后,需要计算存活对象的新地址,确保对象被压缩到更紧凑的内存区域中。这个过程耗时 103.4 毫秒。

4. Phase 3: Adjust pointers
GC(25) Phase 3: Adjust pointers 121.2ms

第三阶段是 调整对象指针。随着对象被搬移到新的内存地址,所有指向这些对象的引用需要更新为新的地址。这个阶段耗时 121.2 毫秒。

5. Phase 4: Evacuate Collection Set
GC(25) Phase 4: Evacuate Collection Set 255.9ms

第四阶段是 对象撤离,即将存活的对象从 Eden 区、Survivor 区和老年代搬移到新的内存区域,并回收旧的内存区域。这个过程耗时 255.9 毫秒。

6. 堆内存状态变化
GC(25) Eden regions: 10->0(12)
GC(25) Survivor regions: 2->2(2)
GC(25) Old regions: 55->20

这部分日志描述了 Full GC 前后堆内存各区域的变化:

  • Eden regions: 10->0(12):Eden 区的 10 个 Region 被清空,并且恢复为 12 个可用的区域。
  • Survivor regions: 2->2(2):Survivor 区没有变化。
  • Old regions: 55->20:老年代的 Region 数量从 55 个减少到 20 个,意味着老年代的垃圾对象得到了显著回收。
7. Metaspace 状态
GC(25) Metaspace: 45M->44M(100M)

Metaspace 是 JVM 用来存储类元数据的内存区域。在 Full GC 中,Metaspace 也可能被回收。在这次 Full GC 中,Metaspace 的使用量从 45MB 减少到 44MB。

8. Full GC 总耗时
GC(25) Pause Full (G1 Evacuation Pause) 657.4ms

整个 Full GC 的总耗时为 657.4 毫秒,这是一次相对较长的垃圾回收停顿。相比 Young GC 或 Mixed GC,Full GC 的耗时通常要长很多,因为它涉及到整个堆的回收,并且是单线程执行的。

Full GC 触发的原因

Full GC 通常在以下情况下触发:

  1. 老年代无法回收:当老年代的内存占用达到较高水平,Mixed GC 不能及时清理足够的老年代区域时,G1 会触发 Full GC。
  2. 晋升失败:当从 Eden 区撤离的存活对象无法晋升到老年代,因为老年代空间不足时,会触发 Full GC。
  3. 元数据空间不足:当 Metaspace 空间不足时,也可能触发 Full GC。
  4. 系统资源压力:当 JVM 内存使用压力较大且回收效率低时,系统可能强制执行 Full GC 以释放内存。

Full GC 的影响

  • 长时间的停顿:Full GC 会暂停所有应用线程,导致应用长时间停止响应,这对高性能、低延迟的应用非常不利。
  • 单线程处理:相比于并行的 Young GC 或 Mixed GC,Full GC 是单线程处理的,因此速度较慢。
  • 最后的手段:Full GC 是垃圾回收器的最后手段,通常意味着内存管理已经到了非常紧张的状态,混合回收无法有效解决问题。

如何避免 Full GC

  1. 调整老年代阈值:可以通过调节 G1 的老年代启动 Mixed GC 的阈值,让老年代尽早参与混合回收,避免老年代过度膨胀。
  2. 增大堆内存:适当增大堆内存,使得老年代和新生代有更多的空间,避免频繁触发 Full GC。
  3. 优化应用内存使用:减少短生命周期的大对象创建,优化内存占用,减少垃圾产生。
  4. 监控和调优:使用监控工具如 Prometheus 或 JMX 监控垃圾回收情况,及时发现问题,进行调优。

通过以上方式,可以降低 Full GC 的频率,提升 JVM 性能。

Stop-The-World

“Stop-the-World” (STW) 事件指的是在垃圾回收过程中,所有应用线程都被暂停的阶段。在 G1 垃圾回收器中,Stop-the-World 事件的几个关键阶段与不同类型的 GC 有关。对于典型的 G1 GC,Stop-the-World 主要出现在 初始标记最终标记 以及 清除 阶段。

让我们逐步分析:

1. 初始标记(Initial Mark)

  • STW:是的,初始标记阶段是一个 Stop-the-World 事件。
  • 作用:标记根对象(GC Roots)以及其直接可达的对象。GC Roots 包括线程栈、全局静态变量等。
  • 时间较短:这个阶段的工作量较少,仅仅是标记直接可达的对象,通常时间较短。
[GC pause (G1 Evacuation Pause) (initial-mark) ...]

2. 并发标记(Concurrent Marking)

  • 非 STW:并发标记阶段不会暂停应用线程,垃圾收集线程和应用线程是并发运行的。
  • 作用:遍历堆中的所有存活对象,标记从 GC Roots 可达的所有对象。
  • 可能触发最终标记:并发标记过程中,如果标记过程中发现某些内存区域是空的或全是垃圾,可能会提前触发混合回收。
[GC concurrent-mark-start ...]
[GC concurrent-mark-end ...]

3. 最终标记(Final Remark/Remark)

  • STW:最终标记阶段是一个 Stop-the-World 事件。
  • 作用:由于并发标记过程中应用线程仍在运行,可能有新的对象被分配或对象引用被修改,因此需要一个短暂停顿来捕获这些变化,确保标记准确。
  • 时间较短:通常比并发标记快得多,因为只需要处理自并发标记开始后的增量变化。
[GC pause (G1 Evacuation Pause) (remark) ...]

4. 清理阶段(Cleanup/Cleanup Phase)

  • 部分 STW:清理阶段分为两部分:初期会有短暂的 Stop-the-World 暂停,标记出垃圾区域,并释放这些内存。后续阶段,回收是并发完成的。
  • 作用:回收空闲的堆内存区域,并将其重新加入可用的堆内存区域列表。
[GC cleanup-start ...]
[GC cleanup-end ...]

总结

在 G1 垃圾回收的几个阶段中,Stop-the-World 事件主要发生在以下几个阶段:

  1. 初始标记(Initial Mark)阶段 —— 短暂的 STW,用于标记 GC Roots。
  2. 最终标记(Final Remark)阶段 —— 短暂的 STW,用于标记并发标记期间未处理的对象变化。
  3. 部分清理阶段(Cleanup Phase)—— 有一个短暂的 STW,用于处理空闲区域的标记。

并发标记是非 STW 的,应用线程与垃圾回收线程并发工作,大大减少了对应用的影响。

相关文章:

G1(Garbage First)垃圾回收实战

GC过程 G1(Garbage First)是JVM中的一种垃圾回收器,设计用于处理具有大堆内存的应用程序,减少GC停顿时间,并提供更可预测的垃圾回收性能。G1的垃圾回收过程主要分为以下几个阶段: 1. 年轻代垃圾回收&…...

ESP32-IDF 通用定时器 GPTimer

目录 一、基本介绍1、配置结构体1.1 gptimer_config_t1.2 gptimer_event_callbacks_t1.3 gptimer_alarm_config_t 2、常用 API2.1 gptimer_new_timer2.2 gptimer_del_timer2.3 gptimer_set_raw_count2.4 gptimer_get_raw_count2.5 gptimer_get_resolution2.6 gptimer_get_captu…...

C#学习笔记(十)

C#学习笔记(十) 第七章 对象的构造方法与实例方法一、对象的构造方法1. 构造方法初识2. 构造方法的创建3. this关键字4. 构造方法的规范和重载4.1 构造方法的规范 5. 对象初始化器5.1 对象初始化器和构造方法的区别 二、对象的实例方法1. 简单应用2.实例…...

出手!快手可灵开源版,AI视频生成整合包!

在2024年,人工智能领域迎来了一位新星——AI视频生成技术。在这场技术革命中,快手推出的可灵AI无疑是最耀眼的明星之一。然而,其高昂的年费让不少用户望而却步,毕竟数千元的开销对于普通人来说是个不小的负担。 幸运的是&#xff…...

【Linux】进程池

目录 进程池 进程池的概念: 手搓进程池: 1、创建信道和子进程 2、通过channel控制子进程 3、回收管道和子进程 进程池 进程池的概念: 定义一个池子,在里面放上固定数量的进程,有需求来了,就拿一个池中…...

实验23:DA呼吸灯实验

电路硬件: 实现功能: 代码: public.h #ifndef _public_H #define _public_H#include "reg52.h" //#include "key.h"typedef unsigned int u16; typedef unsigned char u8;void delay_10us(u16 n); void delay_ms(u16 ms);#endif public.c #include …...

安科瑞智慧能源管理系统EMS3.0在浙江某能源集团有限公司的应用

安科瑞戴婷 Acrel-Fanny 一、项目背景 浙江某能源集团有限公司位于浙江省宁波前湾新区,主营业务范围包括了储能技术服务,光伏风力发电技术服务,充电桩技术服务,新能源项目的施工以及为企业提供配电房运维服务。 随着新能源的兴…...

线性代数学习

1.标量由只有一个元素的张量表示 import torchx torch.tensor([3,0]) y torch.tensor([2,0])x y, x * y, x / y, x**y 2.可以将向量视为标量值组成的列表 x torch.arange(4) x 3.通过张量的索引访问任一元素 x[3] 4.访问张量长度 len(x) 5.只有一个轴的张量&#xff0c…...

FineReport 数据显示格式

原始 修改 选择「单元格元素>格式」,选择「日期型」,改成 「yyyy 年 MM 月 dd 日」,如下图所示: 注:若列表中没有 yyyy 年 MM 月 dd 日 格式,可手动输入 选择运货费数据列单元格,选择「单元…...

leetcode.204.计数质数

#中等#枚举 给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。 埃氏筛 枚举没有考虑到数与数的关联性,因此难以再继续优化时间复杂度。接下来我们介绍一个常见的算法,该算法由希腊数学家厄拉多塞(Eratosthenes)提…...

Mysql环境安装

1,下载压缩包 下载压缩包解压 2,配置环境变量 i,高级系统设置-->环境变量-->系统变量-->path-->添加mysql的bin目录路径 ii,新建my.ini文件 basedir:MYSQL的路径 datadir:这个data路径不用手动创建&am…...

请问平面仓系统的盘点如何做?

盘点流程 一、盘点任务生成 手动发起:仓库管理人员可以根据实际需要,在系统中手动发起库存盘点任务。例如,定期进行全盘、抽盘或者在发现库存数据异常时发起盘点。自动触发:系统可以设置自动触发盘点的条件,如每隔一…...

STM32笔记(1)GPIO之点亮LED

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 总结 第一步:先看原理图。PB0输出高电平是,LED1点亮。 初始化完成了两项工作: (1)从时钟上启动所用GPIO所在的总线&#xff1b…...

自动化工具

自动化工具确保测试准确性的关键在于采取一系列综合性措施,包括但不限于以下几点: 环境一致性:确保测试环境与生产环境尽可能相似,减少环境差异导致的结果不准确。可以通过容器技术(如Docker和Kubernetes)确…...

CTFHUB技能树之HTTP协议——响应包源代码

开启靶场,打开链接: 是个贪吃蛇小游戏,看不出来有什么特别的地方 用burp抓包看看情况: 嗯?点击“开始”没有抓取到报文,先看看网页源代码是什么情况 居然直接给出flag了,不知道这题的意义何在 …...

Java会话技术,拦截器,过滤器,登录校验

目录 1.会话: 2.会话跟踪: 3.会话跟踪方案: 客户端会话跟踪技术:Cookie 服务端会话跟踪技术:Session JWT令牌技术(https://jwt.io/) 定义: 优点: 缺点: 组成: …...

Spring Security 如何进行权限验证

阅读本文之前,请投票支持这款 全新设计的脚手架 ,让 Java 再次伟大! FilterSecurityInterceptor FilterSecurityInterceptor 是负责权限验证的过滤器。一般来说,权限验证是一系列业务逻辑处理完成以后,最后需要解决的…...

计算机砖头书的学习建议

纸上得来终觉浅,绝知此事要躬行,技术来源于实践,光看不练意义不大,过阵子全忘记,并且没有实践来深化理论认知。 “砖头书”通常指的是那些厚重、内容详实且权威的书籍,对于计算机科学领域而言,…...

我与C语言二周目邂逅vlog——7.预处理

C语言预处理详解 C语言预处理是编译过程中的重要组成部分,用于对源代码进行文本替换和修改。预处理发生在编译的前期,通过特定的指令来控制代码的编译行为,最终生成可以交给编译器进行进一步处理的代码。预处理的目的是简化代码编写&#xf…...

Python无监督学习中的聚类:K均值与层次聚类实现详解

📘 Python无监督学习中的聚类:K均值与层次聚类实现详解 无监督学习是一类强大的算法,能够在没有标签的数据集中发现结构与模式。聚类作为无监督学习的重要组成部分,在各类数据分析任务中广泛应用。本文将深入讲解聚类算法中的两种…...

C++ 中 new 和 delete 详解,以及与 C 中 malloc 和 free 的区别

1. C 中 new 和 delete 的基本用法 在 C 中,new 和 delete 是用来动态分配和释放内存的关键字,它们是面向对象的替代方式,提供了比 C 语言更优雅的内存管理工具。 1.1 new 的使用 new 用于从堆中分配内存,并且自动调用对象的构造…...

YOLOv11来了 | 自定义目标检测

概述 YOLO11 在 2024 年 9 月 27 日的 YOLO Vision 2024 活动中宣布:https://www.youtube.com/watch?vrfI5vOo3-_A。 YOLO11 是 Ultralytics YOLO 系列的最新版本,结合了尖端的准确性、速度和效率,用于目标检测、分割、分类、定向边界框和…...

Vue3 集成Monaco Editor编辑器

Vue3 集成Monaco Editor编辑器 1. 安装依赖2. 使用3. 效果 Monaco Editor (官方链接 https://microsoft.github.io/monaco-editor/)是一个由微软开发的功能强大的在线代码编辑器,被广泛应用于各种 Web 开发场景中。以下是对 Monaco Editor 的…...

一文详解Mysql索引

背景 索引是存储引擎用于快速找到一条记录的数据结构。索引对良好的性能非常关键。尤其是当表中的数据量越来越大时,索引对性能的影响愈发重要。接下来,就来详细探索一下索引。 索引是什么 索引(Index)是帮助数据库高效获取数据的…...

基于JAVA+SpringBoot+Vue的旅游管理系统

基于JAVASpringBootVue的旅游管理系统 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末附源码下载链接🍅 哈喽兄…...

STM32_实验3_控制RGB灯

HAL_Delay 是 STM32 HAL 库中的一个函数,用于在程序中产生一个指定时间的延迟。这个函数是基于系统滴答定时器(SysTick)来实现的,因此可以实现毫秒级的延迟。 void HAL_Delay(uint32_t Delay); 配置引脚: 点击 1 到 IO…...

RISC-V笔记——Pipeline依赖

1. 前言 RISC-V的RVWMO模型主要包含了preserved program order、load value axiom、atomicity axiom、progress axiom和I/O Ordering。今天主要记录下preserved program order(保留程序顺序)中的Pipeline Dependencies(Pipeline依赖)。 2. Pipeline依赖 Pipeline依赖指的是&a…...

构建后端为etcd的CoreDNS的容器集群(六)、编写自动维护域名记录的代码脚本

本文为系列测试文章,拟基于自签名证书认证的etcd容器来构建coredns域名解析系统。 一、前置文章 构建后端为etcd的CoreDNS的容器集群(一)、生成自签名证书 构建后端为etcd的CoreDNS的容器集群(二)、下载最新的etcd容…...

Leetcode 剑指 Offer II 098.不同路径

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 一个机器人位于一个 m x n 网格的左上角 (起始点在下…...

LabVIEW智能螺杆空压机测试系统

基于LabVIEW软件开发的螺杆空压机测试系统利用虚拟仪器技术进行空压机的性能测试和监控。系统能够实现对螺杆空压机关键性能参数如压力、温度、流量、转速及功率的实时采集与分析,有效提高测试效率与准确性,同时减少人工操作,提升安全性。 项…...