Java 性能调优实战
刘超
前金山软件技术经理
59174 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 49 讲
开篇词 (1讲)
模块一 · 概述 (2讲)
结束语 (1讲)
Java 性能调优实战
15
15
1.0x
00:00/00:00
登录|注册

04 | 慎重使用正则表达式

独占模式
懒惰模式
贪婪模式
如何减少回溯问题
NFA自动机的回溯
NFA自动机
DFA自动机
减少捕获嵌套
减少分支选择
少用贪婪模式,多用独占模式
正则表达式引擎
正则表达式的优化
正则表达式的相关内容
可能引起回溯问题的Split()方法

该思维导图由 AI 生成,仅供参考

你好,我是刘超。
上一讲,我在讲 String 对象优化时,提到了 Split() 方法,该方法使用的正则表达式可能引起回溯问题,今天我们就来深入了解下,这究竟是怎么回事?
开始之前,我们先来看一个案例,可以帮助你更好地理解内容。
在一次小型项目开发中,我遇到过这样一个问题。为了宣传新品,我们开发了一个小程序,按照之前评估的访问量,这次活动预计参与用户量 30W+,TPS(每秒事务处理量)最高 3000 左右。
这个结果来自我对接口做的微基准性能测试。我习惯使用 ab 工具(通过 yum -y install httpd-tools 可以快速安装)在另一台机器上对 http 请求接口进行测试。
我可以通过设置 -n 请求数 /-c 并发用户数来模拟线上的峰值请求,再通过 TPS、RT(每秒响应时间)以及每秒请求时间分布情况这三个指标来衡量接口的性能,如下图所示(图中隐藏部分为我的服务器地址):
就在做性能测试的时候,我发现有一个提交接口的 TPS 一直上不去,按理说这个业务非常简单,存在性能瓶颈的可能性并不大。
我迅速使用了排除法查找问题。首先将方法里面的业务代码全部注释,留一个空方法在这里,再看性能如何。这种方式能够很好地区分是框架性能问题,还是业务代码性能问题。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

正则表达式在计算机科学中扮演着重要角色,它使用特定的元字符来检索、匹配和替换符合规则的字符串。文章介绍了正则表达式的基本概念和相关技术特点。正则表达式引擎是实现正则表达式的核心算法,目前有两种实现方式:DFA自动机和NFA自动机。文章对比了它们的优劣,指出DFA自动机的执行效率高于NFA自动机。此外,文章还详细解释了NFA自动机的匹配过程和回溯问题。通过实例说明,阐述了NFA自动机在匹配复杂正则表达式时可能引起的大量回溯,从而占用大量CPU时间,带来系统性能开销。这些内容有助于读者深入了解正则表达式的工作原理和性能特点。此外,文章还提供了几种正则表达式的优化方法,包括少用贪婪模式、多用独占模式、减少分支选择和减少捕获嵌套等。这些优化方法可以帮助开发人员提高正则表达式的性能。文章内容丰富,对于需要深入了解正则表达式工作原理和性能优化的读者具有重要的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 性能调优实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(69)

  • 最新
  • 精选
  • Geek_99fab9
    我没有你们优秀,我就明白以后少用点正则😄

    编辑回复: 不一样的优秀~恭喜你学到了精华!

    2019-05-28
    2
    76
  • 陆离
    老师{1,3}的意思不是最少匹配一次,最多匹配三次吗,独占模式那个例子为什么会不匹配呢?

    作者回复: 你好,老师这里更正一下独占模式的例子,落了一个字符。ab{1,3}+bc

    2019-05-28
    18
  • K
    \\?(([A-Za-z0-9-~_=%]++\\&{0,1})+)。老师好,麻烦您讲解一下实际您当时是怎么优化的吗?从哪个正则改成了哪个正则,为什么能有这种优化。谢谢老师。

    作者回复: 如果是单个+的情况下,是最大匹配规则,遇到特殊字符串时,会出现回溯问题。这里增加了一个+,变成两个++,变成了独占模式,避免回溯。

    2019-06-01
    17
  • 没有小名的曲儿
    老师,那个(X|Y|Z)三次index是什么意思呢

    作者回复: 指的是String中的indexof方法

    2019-05-28
    2
    17
  • Liam
    文中提供的split性能消耗大的例子: \?(([A-Za-z0-9-~_=%]+)\&{0,1})$" 一个+ 表示量词,至少1个,不是独占模式吧,这里能否详细解释下优化点在哪里

    作者回复: 你好,一个+表示匹配一个或多个,表示尽量多的匹配。我们这个再加一个+,\\?(([A-Za-z0-9-~_=%]++\\&{0,1})+)。提供的这个是没有优化的例子。

    2019-05-29
    14
  • ID171
    还是上边的例子,在字符后面加一个“+”,就可以开启独占模式。 text=“abbc” regex=“ab{1,3}+bc” 结果是不匹配,结束匹配,不会发生回溯问题。 这里的每一步做了什么,在最大匹配之后又发生了什么

    作者回复: 1、匹配regex中的a和text中的a,匹配成功,继续匹配下一个字符; 2、匹配regex中的b{1,3}+,这个时候是最大匹配规则,也就是说text中会尽量多的去匹配b,直到满足3个b字符匹配成功,才会结束b{1,3}的匹配,这里可以直接匹配到text中的abb; 3、由于还没有满足最大3个的匹配需求,会继续匹配text中的c,发现不匹配,这个时候regex会跳到后面这个字符b,拿这个字符继续匹配; 4、regex中的b发现与text中的c不匹配,则进行回溯,回溯到text中的前一个字符b,发现匹配成功; 5、继续regex的下一个字符c与text中的c字符匹配,匹配成功,匹配结束。

    2019-06-11
    12
    12
  • ABC
    看完明白了回溯是什么意思,我总结如下: 回溯就比如,食堂吃饭,你一下拿了3个馒头。吃完两个,发现第三个不是你想吃的口味的时候,又把第三个放回去,这就造成了资源浪费。 避免的办法就是,一开始就只拿两个,觉得需要了再去继续拿,也就是懒惰模式。

    作者回复: 理解很到位,懒惰就是有拿到馒头就走,非常懒,还有馒头拿也不要了。

    2019-05-30
    9
  • WL
    请问一下老师 "NFA 的状态数"这个概念感觉有点抽象我不太理解, 状态数是什么意思, 是NFA可以匹配的字符串的格式枚举吗?

    作者回复: 你好 WL,就是不同的匹配格式,例如 ab{1,2}c,则状态数为2, 即 abc abbc。

    2019-05-28
    8
  • 13524265609
    非捕获分组不用括号括起来不就好了么?

    作者回复: 这个最直接了,效果是一样的

    2019-09-09
    5
  • 郁陌陵
    老师,我理解独占模式可以减少回溯,但是不能避免回溯: String regex = "^ab{1,3}+c$"; String str = "abbc"; 这个例子里,b{1,3}+ 在匹配到 abb后,无法匹配c,是需要回溯的

    作者回复: 是的,你理解的很到位,可以减少回溯,但是无法避免。这种第一次匹配会是匹配失败。具体的过程是text的a与regex的a匹配,然后继续text的b与b匹配,也匹配,这个时候由于是懒惰模式,要尽可能少的匹配,所以下一个text的b将与c匹配,匹配失败,这个时候又会回溯一次,将text的b与regex的b进行匹配,成功了,再将text中的c与c匹配,最后匹配成功。 这种方式与贪婪模式的匹配的方式是不一样的,虽然也发生了回溯,但回溯的方式不一样,是尽可能少的去匹配而发生的回溯。

    2019-07-05
    4
    2
收起评论
显示
设置
留言
69
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部