垃圾收集算法,垃圾收集器

这些是我需要调整GC时通常会看到的一些准则和技巧。 主要由以下两本书组成,而根据我的经验却很少:

  • Java性能
  • JBoss AS 5性能调优

希望它们对在那里的其他人有用!

垃圾收集器

XX:+AggressiveOpts将HotSpot内部布尔变量设置为true以启用其他性能优化

****************************************************** ******************************************************

由于大多数对象在其生命周期内最多只能被一个线程锁定,因此启用-XX:+ UseBiasedLocking可使该线程将锁定偏向自身。 一旦有偏见,该线程便可以随后锁定和解锁对象,而无需诉诸昂贵的原子指令

****************************************************** ******************************************************

要打印默认的人体工程学值:

java -XX:+PrintCommandLineFlags -version

****************************************************** ******************************************************

-XX:+PrintGCDetails打印更多且更有价值的垃圾收集信息。

以下示例显示了通过-XX:+UseParallelGC-XX:+UseParallelOldGC启用的Java 6 Update 25吞吐量垃圾收集器的-XX:+PrintGCDetails输出示例。 输出分布在多行中,以便于阅读。

[GC
[PSYoungGen: 99952K->14688K(109312K)]
422212K->341136K(764672K), 0.0631991 secs]
[Times: user=0.83 sys=0.00, real=0.06 secs]

****************************************************** ******************************************************

包括日期和时间戳

-XX:+PrintGCTimeStamps

YYYY-MM-DD-T-HH-MM-SS.mmm-TZ

-XX:+PrintGCDetails-Xloggc:<filename>结合使用时,即使不指定-XX:+PrintGCTimeStamps ,输出也会自动带有时间戳作为前缀。

****************************************************** ******************************************************

[Full GC (System)
[PSYoungGen: 99608K->0K(114688K)]
[PSOldGen: 317110K->191711K(655360K)]
416718K->191711K(770048K)
[PSPermGen: 15639K->15639K(22528K)],
0.0279619 secs]
[Times: user=0.02 sys=0.00, real=0.02 secs]

系统意味着代码中有一个System.gc()

****************************************************** ******************************************************

http://sysadminsjourney.com/2008/09/15/profile-gc-with-gchisto/
****************************************************** ******************************************************

VisualVM和VisualGC插件

如果远程,则需要安装jstatd守护程序

****************************************************** ****************************************************

分层服务器运行时是通过-server -XX:+TieredCompilationcommand行选项启用的。

小费

如果您不知道最初选择哪个运行时,请从服务器运行时开始。 如果无法满足启动时间或内存占用量要求,并且您正在使用Java 6 Update 25或更高版本,请尝试分层服务器运行时。 如果您没有运行Java 6 Update 25或更高版本,或者分层服务器运行时无法满足启动时间或内存占用量要求,请切换到客户端运行时。

****************************************************** ****************************************************

32位或64位JVM

操作系统 Java堆大小 32位或64位JVM
视窗 小于1300 MB 32位
视窗 介于1500 MB和32 GB之间[*] 64位-d64 -XX:+ UseCompressedOops命令行选项
视窗 超过32 GB 带-d64命令行选项的64位
的Linux 小于2 GB 32位
的Linux 2到32 GB之间[*] 64位-d64 -XX:+ UseCompressedOops命令行选项
的Linux 超过32 GB 带-d64命令行选项的64位
Oracle Solaris 小于3 GB 32位
Oracle Solaris 介于3到32 GB之间[*] 64位-d64 -XX:+ UseCompressedOops命令行选项
Oracle Solaris 超过32 GB 带-d64命令行选项的64位

[*]在具有-XX:+UseCompressedOops的64位HotSpot VM中,最佳性能约为最大Java堆大小约26 GB或更少。

Java 6 Update 18以后的HotSpot VM版本默认基于最大Java堆大小自动启用-XX:+UseCompressedOops

****************************************************** ****************************************************

从parallelOldDC开始:年轻的和老的收藏是多线程的

吞吐量垃圾收集器由HotSpot VM命令行选项-XX:+UseParallelOldGC-XX:+UseParallelGC 。 如果-XX:+UseParallelOldGC在您使用的HotSpot VM版本中不可用,请使用-XX:+UseParallelGC 。 两者之间的区别在于-XX:+UseParallelOldGC启用了多线程的年轻代垃圾收集器和多线程的旧世代垃圾收集器,即次要垃圾收集和完整垃圾收集都是多线程的。 -XX:+UseParallelGC仅启用多线程年轻代垃圾收集器。 与-XX:+UseParallelGC一起使用的旧式垃圾收集器是单线程的。 使用-XX:+UseParallelOldGC也会自动启用-XX:+UseParallelGC 。 因此,如果要同时使用多线程年轻代垃圾收集器和多线程旧代垃圾收集器,则只需指定-XX:+UseParallelOldGC

****************************************************** ****************************************************

垃圾收集日志记录:

-XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:<filename>

在将HotSpot VM调整为低延迟时,以下两个命令行选项很有用,因为它们报告了由于VM安全点操作而导致应用程序被阻止的时间,以及应用程序在安全点操作之间执行了多长时间。

-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCApplicationConcurrentTime

选项-XX:+PrintSafepointStatistics可以帮助区分垃圾回收安全点和其他安全点。

可以使用-XX:+PrintGCApplicationConcurrentTime命令行选项来确定应用程序在感兴趣的某个观察到的响应时间超过应用程序要求的某个时间段内是否正在执行以及执行了多长时间。

****************************************************** ****************************************************

建议的GC日志记录命令行选项

GC命令行选项 最适用
-XX:+ PrintGCTimeStamps
-XX:+ PrintGC详细信息
-Xloggc:<文件名>
为所有应用程序启用的最少的命令行选项集。
-XX:PrintGCDateStamps 在希望查看日历日期和时间而不是指示自JVM启动以来的秒数的时间戳时使用。 需要Java 6 Update 4或更高版本。
-XX:+ PrintGCApplicationStoppedTime
-XX:+ PrintGCApplicationConcurrentTime
-XX:+ PrintSafepointStatistics
在调整应用程序以降低响应时间/延迟时很有用,有助于区分VM安全点操作和其他来源引起的暂停事件。

XX:+PrintCommandLineFlags在HotSpot VM初始化时将选定的初始堆大小和最大堆大小打印为-XX:InitialHeapSize=<n>

-XX:+PrintTenuringDistribution

****************************************************** ****************************************************** ************************

-XX:MaxHeapSize=<m> ,其中<n>是初始Java堆大小(以字节为单位),而<m>是最大Java堆大小(以字节为单位)

****************************************************** ****************************************************** ************************

空间 命令行选项 占用率
Java堆 -Xms和-Xmx 完全垃圾收集后,老一代空间占用率为3到4倍
永久世代 -XX:PermSize -XX:MaxPermSize 完全垃圾收集后,永久生成空间占用率为1.2x到1.5x
年轻一代 -Xmn 完全垃圾收集后,老一代空间占用率为1x到1.5x
老一辈 从Java总堆大小减去年轻代大小中隐含 完全垃圾收集后,老一代空间占用率为2到3倍

****************************************************** ****************************************************** ************************

年轻空间

-XX:NewSize=<n>[g|m|k]

-XX:MaxNewSize=<n>[g|m|k]

-Xmn<n>[g|m|k]

-Xmn可以方便地确定年轻一代空间的初始大小和最大大小

如果(-Xmx != -Xms) && -Xmn存在

Java堆大小的增长或收缩不会调整年轻代空间的大小。

随Java堆大小的任何增长或收缩,年轻代空间的大小将保持不变。 因此,仅当-Xms-Xmx设置为相同的值时, -Xmn应使用-Xmn

****************************************************** ****************************************************** ************************

烫发大小

-XX:PermSize=<n>[g|m|k]

-XX:MaxPermSize=<n>[g|m|k]

强调性能的Java应用程序应将初始和最大永久生成大小( -XX:PermSize-XX:MaxPermSize )的大小都设置为相同的值,因为增加或缩小永久生成空间需要完整的垃圾收集。

****************************************************** ****************************************************** ************************

-XX:-ScavengeBeforeFullGC将在完整垃圾收集上禁用年轻一代空间垃圾收集。

****************************************************** ****************************************************** ************************

2010-11-25T18:51:03.895-0600: [Full GC
[PSYoungGen: 279700K->267300K(358400K)][ParOldGen: 685165K->685165K(685170K)]
964865K->964865K(1043570K)
[PSPermGen: 32390K->32390K(65536K)],
0.2499342 secs]
[Times: user=0.08 sys=0.00, real=0.05 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space2010-11-25T18:26:37.755-0600: [Full GC
[PSYoungGen: 0K->0K(141632K)]
[ParOldGen: 132538K->132538K(350208K)]
32538K->32538K(491840K)[PSPermGen: 65536K->65536K(65536K)],
0.2430136 secs]
[Times: user=0.37 sys=0.00, real=0.24 secs]
java.lang.OutOfMemoryError: PermGen space

如果您在垃圾回收日志中观察到OutOfMemoryError ,请尝试将Java堆大小增加到JVM可用物理内存的80%到90%。

例如,对于旧世代空间OutOfMemoryErrors,增加-Xmsand -Xmx ,对于永久世代OutOfMemoryErrors,增加-XX:PermSize-XX:MaxPermSize

下一步是计算应用程序的实时数据大小。

****************************************************** ****************************************************** ************************

计算实时数据大小

除了实时数据大小外,处于稳定状态的完整垃圾收集还提供了由于完整垃圾收集而导致的最坏情况下的延迟。

您可以使用实时数据(应用程序繁忙时间内的perm空间+满GC后的旧空间)来计算初始堆大小:

通常,初始和最大Java堆大小命令行选项-Xms和-Xmx的值应设置为旧空间的实时数据大小的三到四倍。

完全垃圾回收后的旧一代空间占用为295111K,或大约295 MB。因此,实时数据大小约为295 MB。

因此,为此应用程序指定的建议的初始Java堆大小和最大Java堆大小应为885到1180兆字节之间的值,即-Xms1180m -Xmx1180m是实时数据大小的四倍。

同样作为一般规则,初始和最大永久世代大小-XX:PermSize-XX:MaxPermSize应该比永久世代空间的活动数据大小大1.2倍至1.5倍。

在上图所示的示例完整垃圾收集中,完整垃圾收集后的永久生成空间占用为32390K,约32兆字节。 因此,为此应用程序指定的建议的初始和最大永久生成空间大小应在38兆字节和48兆字节之间,即-XX:PermSize = 48m -XX:MaxPermSize = 48m,是永久生成实时数据大小的1.5倍。

作为附加的一般规则,年轻代空间应为旧代空间活动数据大小的1到1.5倍。

结果,建议的年轻代大小应在295到442兆字节之间。 在上图中,年轻一代的空间大小为358400K,约358兆字节。 358兆字节在建议的大小以内。

如果初始和最大Java堆大小是实时数据大小的3倍至4倍,而年轻代空间是实时数据大小的1倍至1.5倍,则旧代空间的大小应在实时数据大小的2倍至3倍之间。

基于上图中的垃圾收集数据,应用这些常规大小调整规则的组合Java命令行为

$ java -Xms1180m -Xmx1180m -Xmn295m
-XX:PermSize=48m -XX:MaxPermSize=48m

空间 命令行选项 占用率
Java堆 -Xms和-Xmx 完全垃圾收集后,老一代空间占用率为3到4倍
永久世代 -XX:PermSize -XX:MaxPermSize 完全垃圾收集后,永久生成空间占用率为1.2x到1.5x
年轻一代 -Xmn 完全垃圾收集后,老一代空间占用率为1x到1.5x
老一辈 从Java总堆大小减去年轻代大小中隐含 完全垃圾收集后,老一代空间占用率为2到3倍

****************************************************** ****************************************************** ************************

音调延迟/响应能力

评估垃圾收集器对延迟的影响涉及以下活动:

  • 测量次要垃圾收集时间
  • 测量次要垃圾收集频率
  • 测量最坏情况下的完整垃圾收集持续时间
  • 测量最坏情况下的全部垃圾收集频率

调整年轻代的大小

从parallelGC到并发-XX:+UseConcMarkSweepGC

如果最坏的情况下,完整垃圾收集持续时间或频率收集频率太高

随着年龄的增长,要记住的其他一般准则是

  • 老一代的空间大小不应小于实时数据大小的1.5倍。 有关实时数据大小的定义和其他旧版本调整大小的准则,请参见上一节“ 确定内存占用空间 ”。
  • 年轻代的空间大小至少应为Java堆大小的10%,该值指定为-Xmx和-Xms。 很小的年轻一代可能适得其反。 它导致频繁的次要垃圾收集。
  • 当增加Java堆大小时,请注意不要超过JVM可用的物理内存量。 Java堆大小消耗的内存足以导致基础系统交换到虚拟内存,从而导致垃圾收集器和应用程序性能下降。

调整旧一代的大小

这项任务的目的是评估由完整垃圾收集引起的最坏情况下的暂停时间以及完整垃圾收集的频率。

如果您仅观察完整的垃圾收集

当修改旧世代空间的大小时,旧世代大小可能会与年轻世代大小失去平衡,并导致应用程序仅经历完整的垃圾回收。 通常,这发生在旧的一代空间不够大而无法容纳所有从年轻一代空间提升的对象时,即使在进行完整的垃圾回收之后。

老式空间不够大的关键指标是,老式空间中的回收空间很小(ParOldGen标签右侧的值),并且在每个完整空间之后,大部分年轻空间仍然被占用。垃圾收集。 当旧一代中没有足够的空间来处理年轻一代的提升对象时,如先前输出中所观察到的,对象将“备份”到年轻一代空间中。

如果由于完整的垃圾收集持续时间太长而无法满足应用程序最坏情况下的延迟要求,那么您应该切换到使用并发垃圾收集器

使用HotSpot命令行选项启用并发垃圾收集器:

-XX:+UseConcMarkSweepGC

****************************************************** ****************************************************** ************************
避免幸存者空间溢出是通过调整幸存者空间的大小来实现的,以使幸存者空间足够大,可以将幸存的对象放置足够长的时间,以便在一段时间内老化。 有效的老化只会将寿命长的物体提升到旧的空间。

小费

老化是将对象保留在年轻一代中直至无法再访问的一种方法,以便为寿命更长的对象保留老一代空间。

使用HotSpot命令行选项调整幸存者空间的大小:
-XX:SurvivorRatio=<ratio>

<ratio>的值必须大于0。- -XX:SurvivorRatio=<ratio>表示每个幸存者空间与eden空间之间的空间比率。 以下公式可用于确定幸存者空间大小:
生存者空间大小= -Xmn<value>/(-XX:SurvivorRatio=<ratio> + 2)

指定为比率的值越大,幸存者空间大小越小。
权属阈值说明

小费

在年轻一代中进行有效的对象老化,以防止它们过早地提升到老一代空间,这降低了老一代的占用率。 这减少了CMS垃圾回收周期必须执行的频率,还减少了碎片的可能性。

还有一个HotSpot虚拟机命令行选项, -XX:MaxTenuringThreshold=<n>可用于询问HotSpot虚拟机仅一个对象的年龄之后,以促进对象的老一代空间超出的值<n>

对于Java 5 Update 6和更高版本,最大使用期限阈值可以设置为0–15,对于Java 5 Update 5和更低版本,可以设置为0–31。

不建议将最大使用期限阈值设置为0。这会导致在分配对象后,在下一个次要垃圾回收中将对象立即从年轻一代提升到老一代。 这将非常Swift地扩展旧一代的空间,并导致频繁的完整垃圾收集。

也建议不要将最大使用期限阈值设置为大于可能的最大值。 这将导致对象保留在幸存者空间中,直到幸存者空间溢出为止。 如果它们溢出,则对象将被无差别地提升为老一代,也就是说,它们不会根据其年龄来提升。 结果,可以在寿命较长的对象之前提升寿命较短的对象,这防止了有效的对象老化。

小费

通常,观察新的占位阈值始终小于最大占位阈值,或者观察所需的幸存者大小小于幸存总字节数(对象年龄的最后一行和最右边的列的值)表明幸存者空间太小。

****************************************************** ****************************************************** ************************

启动CMS收集周期

停止世界压缩垃圾收集是最坏情况下垃圾收集导致的延迟

CMS周期的启动基于旧空间的占用

如果观察到世界各地的压缩垃圾收集,则可以调整CMS周期何时开始。 并发模式故障会在垃圾收集输出中标识CMS中的“停止世界”压缩垃圾收集。 以下是一个示例:

174.445: [GC 174.446: [ParNew: 66408K->66408K(66416K), 0.0000618
secs]174.446: [CMS (concurrent mode failure): 161928K->162118K(175104K),
4.0975124 secs] 228336K->162118K(241520K)

如果您在垃圾回收输出中观察到并发模式故障,则可以使用命令行选项指示HotSpot VM提前启动CMS周期的开始:

-XX:CMSInitiatingOccupancyFraction=<percent>

指定的值是CMS垃圾回收周期应开始的旧占用率的百分比。 例如,如果您希望CMS周期从旧的空间占用率为65%开始,请设置-XX:CMSInitiatingOccupancyFraction=65 。 第二个HotSpot命令行选项应与– XX:CMSInitiatingOccupancyFraction=<percent>结合使用

-XX:+UseCMSInitiatingOccupancyOnly

-Xmx1536m -Xms1536m -Xmn512m
-XX:CMSInitiatingOccupancyFraction = 51
-XX:+仅使用CMSInitiatingOccupancy

显式垃圾回收

如果观察到完整的垃圾回收,这些回收是通过显式调用System.gc() ,那么在使用并发垃圾回收器时有两种处理方法:

  1. 您可以使用HotSpot VM命令行选项请求HotSpot VM作为并发垃圾回收周期执行它们:
  2. -XX:+ ExplicitGCInvokesConcurrent
  3. 要么
  4. -XX:+ ExplicitGCInvokesConcurrentAndUnloadsClasses
  5. 首先需要Java 6或更高版本。 第二个要求Java 6 Update 4或更高版本。 如果您正在使用的JDK版本支持-XX:+ ExplicitGCInvokesConcurrentAndUnloadsClasses,通常会更好。
  6. 您可以使用Hotspot命令行选项让HotSpot VM忽略对System.gc()的显式调用:
  7. -XX:+ DisableExplicitGC
  8. 此命令行选项还忽略其他HotSpot VM垃圾收集器中对System.gc()的显式调用。

尽管在垃圾收集输出中报告了CMS Perm标签,但默认情况下,HotSpot VM不会使用CMS垃圾收集永久生成空间。 要启用CMS永久生成垃圾收集,您必须指定以下HotSpot VM命令行选项:
-XX:+CMSClassUnloadingEnabled
如果使用的是Java 6 Update 3或更早版本,则除了-XX:+ CMSClassUnloadingEnabled外,还必须指定以下命令行选项: -XX:+CMSPermGenSweepingEnabled

CMS暂停时间调整

备注阶段中使用的线程数可以由以下HotSpot VM命令行选项控制:

-XX:ParallelGCThreads=<n>

在某些情况下,可以通过指定以下内容来缩短备注阶段的持续时间:

-XX:+CMSScavengeBeforeRemark

此命令行选项强制HotSpot VM在CMS注释之前执行次要垃圾回收。 在备注之前进行次要的垃圾收集可以通过减少年轻一代空间中可以从旧一代空间到达的对象的数量来最大程度地减少备注阶段的工作量。

如果应用程序中有大量要处理的引用或可终结对象,则指定以下HotSpot VM命令行选项可以帮助减少垃圾收集时间:

-XX:+ParallelRefProcEnabled

最新和最优化

当新的性能优化集成到HotSpot VM中时,通常在命令行选项-XX:+AggressiveOpts下引入它们。

如果应用程序涉众正在寻求其他性能并愿意接受与启用最新优化相关的其他小风险,则应考虑使用-XX:+AggressiveOpts命令行选项。

转义分析

转义分析是一种评估Java对象范围的技术。 特别是,如果某个执行线程分配的Java对象可以被其他线程看到,则该对象“转义”。 如果Java对象无法逃脱,则可以应用其他优化技术。 因此,优化技术称为逃逸分析。

使用以下命令行选项启用HotSpot VM中的转义分析优化:

-XX:+DoEscapeAnalysis

Linux上的大页面

-XX:+UseLargePages

参考:来自我们的JCG合作伙伴 Marco Castigliego的垃圾收集器指南和提示 ,位于“ 删除重复并修复不良名称”博客上。

翻译自: https://www.javacodegeeks.com/2013/12/garbage-collector-guidelines-and-tips.html

垃圾收集算法,垃圾收集器

垃圾收集算法,垃圾收集器_垃圾收集器准则和提示相关推荐

  1. ppt复制切片器_切片器化繁为简,盘它 !

    与Power BI 相伴多年的时光里(不知牺牲了我多少游戏娱乐的时间),Power BI 越来越丰富的功能渐渐改变了我们使用Power BI报告的方式,如书签.按钮和选择等功能~~现在,大多数业务用户 ...

  2. webgl 着色器_“着色器”是什么意思? 如何使用HTML5和WebGL创建它们

    webgl 着色器 本文是Microsoft的Web开发技术系列的一部分. 感谢您支持使SitePoint成为可能的合作伙伴. 您可能已经注意到,去年我们第一次谈论了babylon.js ,最近我们发 ...

  3. 使用什么优化器_优化器怎么选?一文教你选择适合不同ML项目的优化器

    选自lightly.ai 机器之心编译 编辑:小舟.杜伟 为机器学习项目选择合适的优化器不是一件简单的事. 优化器是深度学习领域的重要组成模块之一,执行深度学习任务时采用不同的优化器会产生截然不同的效 ...

  4. mysql cbo优化器_查询优化器介绍 - PolarDB-X 云原生分布式数据库 - 阿里云

    PolarDB-X接收到一条SQL后的执行过程大致如下: 语法解析器(Parser)将SQL文本解析成抽象语法树(AST). 语法树被转化成基于关系代数的逻辑计划. 优化器(Optimizer)对逻辑 ...

  5. 如何听节拍器_节拍器使用方法

    节 拍器使用方法 节 拍器是一种可以 设 定每分 钟发 出有 规 律的特定 节 拍的机械,一般 节 拍器可以分 为 机械式和 电 子式两种.机械 节 拍器有个 带 有刻度的 钟摆 ,刻度一般从 每分 ...

  6. java类加载器_类加载器ClassLoader

    上篇文章说到,Class类可以通过一个类的全限定名去加载类,那么底层是如何去加载的呢?这就是我们今天要聊的类加载器ClassLoader,其可以通过一个类的全限定名来获取描述此类的二进制字节流,也即是 ...

  7. java类加载器_类加载器

    回顾一下类加载过程 类加载过程:加载->连接->初始化.连接过程又可分为三步:验证->准备->解析. 一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的 ...

  8. java 装饰器_装饰器模式(Java)

    什么是装饰器模式? 装饰器模式允许你向一个现有的对象添加新的功能,同时又不改变其结构,它是作为现有的类的一个包装.这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额 ...

  9. ssm 新建拦截器_拦截器在springboot项目和ssm架构项目的应用

    1.拦截器的主要功能 在访问某节点url前拦截客户端发来的请求,判断该请求是否符合自己定义的要求,如果不符合,返回false,该节点url的对应代码不会被执行:如果符合,返回true,可以执行该节点u ...

最新文章

  1. 蚂蚁金服面试经历-临场发挥
  2. 【转】python编码大坑详解2
  3. 关于spring事务管理
  4. 非阻塞算法(Lock-Free)的实现
  5. 使用C#编程解决数独求解过程(从图片识别到数独求解)第二篇
  6. jmeter使用中的问题
  7. Open×××多处理之-为什么不
  8. 503 service unavailable php,503service unavailable错误提示解决方法
  9. 中国高新技术企业名单数据
  10. Android Serach框架使详解
  11. gimp 抠图_制作假条(wps与gimp)
  12. 电脑XP系统最大支持多大内存?
  13. 5.16 图层合并的几种方式 [原创Ps教程]
  14. 《信息学奥赛一本通》宠物小精灵之收服
  15. POJ 2248 搜索
  16. MySQL 8.0 高可用之如何解决从库数据被修改引起的主从同步错误
  17. Towards Better Understanding of Self-Supervised Representations / Q-Score
  18. 安卓打包出现“app:processReleaseManifest“问题的一种解决方案
  19. VScode与VSstdio差别该如何选择C语言IDE(集成开发环境)
  20. Pr_cc 学习笔记(十)关键帧 特效

热门文章

  1. 【AC自动机】单词(luogu 3966/ybtoj AC自动机-2)
  2. 4、oracle数据库的查询基础
  3. K8S Learning(8)—— Service
  4. 如何快速开发一个 Dubbo 应用
  5. 深入浅出讲解语言模型
  6. JavaFX UI控件教程(二十三)之Menu
  7. 一个正则表达式酿成的惨案
  8. Git 12 岁了,送给你 12 个 Git 使用技巧
  9. Spring思维导图,让Spring不再难懂(mvc篇)
  10. sql事务、视图和索引