浅谈正则表达式——C++正则替换引起的性能下降

news/2024/10/17 19:30:24/

目录

  • 问题引入
  • 正则替换测试
  • 常规方法测试
  • 模拟外部多次调用
  • 正则性能差的原因
  • 写在最后

问题引入

最近在一次解析大文件(10万+行)时,处理空格用到了正则替换,却没想到带来了性能上的问题,特别在此记录给需要的人避坑。假如要用C++处理一个字符串首尾的空格,可以用正则,可以用string自带的erase方法,下面是对这两种方法性能上的测试:

正则替换测试

#include <iostream>
#include <regex>
#include <chrono>using namespace std;void trimmed(std::string& str) {str = regex_replace(str, std::regex("^\\s+"), "");str = regex_replace(str, std::regex("\\s+$"), "");
}int main() {string str1 = "   123 45 tr54 ewre  "; //字符串首尾共5个空格cout << "str1.length = " << str1.length() << endl;auto t1 = std::chrono::steady_clock::now();trimmed(str1);auto t2 = std::chrono::steady_clock::now();double elapse = std::chrono::duration<double, std::milli>(t2-t1).count();cout << "regex replace use " << elapse << "ms" << endl;cout << "str1.length = " << str1.length() << endl;cout << str1 << endl;return 0;
}

测试结果如下:
在这里插入图片描述
使用正则替换,执行完成一次大概耗时0.4ms,看起来耗时很短,但如果乘以100000呢?
0.4ms * 100000 = 40000ms = 40s

常规方法测试

接下来使用string自带的erase方法测试

#include <iostream>
#include <regex>
#include <chrono>using namespace std;void Trimmed(std::string& str) {str = str.erase(0, str.find_first_not_of(" "));str = str.erase(str.find_last_not_of(" ") + 1);
}int main() {string str2 = "   123 45 tr54 ewre  "; //字符串首尾同样是5个空格cout << "str2.length = " << str2.length() << endl;auto t3 = std::chrono::steady_clock::now();Trimmed(str2);auto t4 = std::chrono::steady_clock::now();double elapse = std::chrono::duration<double, std::milli>(t4-t3).count();cout << "erase use " << elapse << "ms" << endl;cout << "str2.length = " << str2.length() << endl;cout << str2 << endl;return 0;
}

测试结果如下
在这里插入图片描述
使用erase去除空格,执行一次大概耗时0.0008ms,而正则替换耗时几乎是它的500倍(0.4ms),这个差距就很大了。即使乘以100000,erase耗时0.0008ms * 100000 = 80ms,erase给人的感觉是极致丝滑,正则替换则是程序半天无响应。而这个差距在多次外部调用的情况下更加明显,看下面的模拟测试:

模拟外部多次调用

void test01() {auto t1 = std::chrono::steady_clock::now();for (int i = 0; i < 100000; i++) {string str = "   123 45 tr54 ewre  ";trimmed(str);}auto t2 = std::chrono::steady_clock::now();double elapse = std::chrono::duration<double, std::milli>(t2-t1).count();cout << "regex----->" << elapse << "ms" << endl;
}void test02() {auto t1 = std::chrono::steady_clock::now();for (int i = 0; i < 100000; i++) {string str = "   123 45 tr54 ewre  ";Trimmed(str);}auto t2 = std::chrono::steady_clock::now();double elapse = std::chrono::duration<double, std::milli>(t2-t1).count();cout << "erase=====>" << elapse << "ms" << endl;
}

test01和test02分别模拟使用正则替换和erase处理10万行的文本中的首尾空格,结果如下:
在这里插入图片描述
现在这个差距已经不是500倍了,而是夸张的2300多倍!!!这在性能上是完全不可接受的,故而正则替换性能较差,不建议使用正则去空格。
在这里插入图片描述

正则性能差的原因

主要是正则表达式的引擎会导致字符匹配时会发生回溯,此处不做过多叙述,感兴趣的小伙伴可以去阅读正则表达式引起的性能下降一文,一定会有所收获的。

写在最后

不用不知道,正则虽然处理文本很强,但用错了地方,可能带来负面效果,coding就是从这个坑出来,掉进另一个坑里,这其中的乐趣,大概就是爬上坑的过程吧哈哈。


http://www.ppmy.cn/news/801.html

相关文章

Python编程 顺序执行与程序的主入口

作者简介&#xff1a;一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.顺序执行 1.顺序执行(了解) 2.程序主入口(熟悉) 前言 本章将会讲解P…

17条卢松松近期言论汇总

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 本文汇集了前段时间卢松松写的段子&#xff0c;有心情感悟、工作感悟、做直播带货、创业的感悟。关注互联网、草根创业者的朋友可以看看&#xff01; (1) 人最舒服的是什么时候呢?我认为&#xff…

使用[阿里问题定位神器]Arthas入门

目录 注意 安装 在线安装 离线安装 目前我接触到的实用命令 dashboard heapdump thread jad stack trace 注意 arthas本身有一定的性能消耗&#xff0c;所以生产环境小心使用 arthas本身有一定的性能消耗&#xff0c;所以生产环境小心使用 arthas本身有一定的性能…

HTML+CSS美食静态网页设计——简单牛排美食餐饮(9个页面)公司网站模板企业网站实现

&#x1f468;‍&#x1f393;静态网站的编写主要是用HTML DIVCSS JS等来完成页面的排版设计&#x1f469;‍&#x1f393;,常用的网页设计软件有Dreamweaver、EditPlus、HBuilderX、VScode 、Webstorm、Animate等等&#xff0c;用的最多的还是DW&#xff0c;当然不同软件写出的…

Perl时间处理函数用法介绍

一. Perl时间的表示函数 1. 表示日期的方式多种多样: "18Jan1973"; "18/01/1973"; "01/18/1973"; "Jan181973"; "18-01-73"; "18-01-1973"; "01/73". 其中一些格式意思不清(如"01-06-1973",…

SNMP信息收集与利用

SNMP信息收集与利用 任务环境说明: 服务器场景操作系统:Back Track five(用户名:root;密码:toor) 服务器场景操作系统:Microsoft Windows2003 Server(用户名:administrator;密码:123456) 第一步,打开网络拓扑,点击启动选项,启动实验虚拟机

LeetCode-1769. 移动所有球到每个盒子所需的最小操作数【数组,前缀和】

LeetCode-1769. 移动所有球到每个盒子所需的最小操作数【数组&#xff0c;前缀和】题目描述&#xff1a;解题思路一&#xff1a;简单暴力&#xff0c;对每个位置单独计算。解题思路二&#xff1a;根据前一个盒子的操作数得到下一个盒子的操作数,先初始化第0个位置的操作数和rig…

运放参数-共模输入范围-运算放大器

运放共模输入范围 根据实际的应用我们会选择一个运算放大器&#xff08;op amp&#xff09;&#xff0c;选型过程中工程师会考虑一些参数可例如&#xff1a;电源电压、增益带宽积、输入共模范围、转换速率和输入噪声电压等等。 在本篇文章中重点介绍了运放的输入共模范围的定…