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

news2025/2/21 22:27:07

目录

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

问题引入

最近在一次解析大文件(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.coloradmin.cn/o/53091.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4-four: 我收到的赞

我收到的赞 重构点赞功能&#xff08;用上节的功能较为麻烦&#xff0c;需要将用户发布的帖子和评论所获得的赞加起来&#xff09; 以用户为key&#xff0c;记录点赞数量increment(key), decrement(key)。 开发个人主页 以用户为key&#xff0c;查询点赞数量 1.在Redis.Ut…

RabbitMQ------其他知识点(幂等性、优先级队列、惰性队列)(九)

RabbitMQ------其他知识点&#xff08;&#xff09;&#xff08;九&#xff09; 幂等性 用户对于统一操作发起的一次请求或者多次请求的结果是一致的&#xff0c;不会因为多次点击而产生副作用。同一次还款&#xff0c;通过多次点击不会生成多条还款记录&#xff0c;一个人的…

crm客户管理系统为企业带来的价值

简道云CRM场景套件对中小企业来说&#xff0c;crm客户管理系统最核心的作用&#xff0c;一是客户信息(联系信息和洽谈过程&#xff09;的存留&#xff0c;不会因为业务人员的离职造成流失&#xff0c;这点对老板很重要。二是可帮助业务人员&#xff08;客户获取、主管指导等&am…

Win32API操作文件

在Windows编程中CreateFile函数是用得非常多的&#xff0c;不仅可以打开文件&#xff0c;还可以打开管道、邮槽、通信资源、磁盘设备&#xff08;早期Windows)&#xff0c;控制台、目录。该函数返回一个句柄&#xff0c;该句柄可用于根据文件或设备以及指定的标志和属性访问文件…

SpringSecurity(二十)---OAuth2:实现资源服务器(上)资源服务器搭建以及直接调用授权服务器模式

一、 前言 本章将讨论如何使用Spring Security实现一个资源服务器&#xff0c;资源服务器是管理用户资源的组件。另外&#xff0c;学习本章有个前提&#xff0c;需要先把前面搭建授权服务器的相关文章先给阅读&#xff0c;否则可能后面出现的授权服务器相关代码不知道个所以然…

【Redis】缓存击穿的产生情况解决方案

1. 缓存击穿产生 也叫做 热点 Key 问题&#xff0c;高并发访问并且缓存重建业务较复杂的 key 突然失效了&#xff0c;无数的请求想要重建缓存&#xff0c;大量的访问会在瞬间给数据库带来巨大冲击。 2. 解决方案 2.1 方案一&#xff1a;互斥锁 查询缓存不存在时&#xff0c;…

【OpenFOAM】-olaFlow-算例1- baseWaveFlume

算例路径&#xff1a; olaFlow\tutorials\baseWaveFlume 算例描述&#xff1a; 一个基础的二维波浪水槽 算例快照&#xff1a; 图1 波浪模拟结果图2 算例网格文件结构&#xff1a; ├── 0.org │ ├── U │ ├── alpha.water │ ├── alpha.water.org │ └─…

关于Redis的远程连接 Connection: Disconnect on error 问题

bug描述&#xff1a; Connection: Disconnect on error: Connection error: Connection timed outConnection: 192.168.245.128 > connection failed 问题复现&#xff1a; redis版本&#xff1a; redis-6.2.6 Linux版本&#xff1a;CenterOS 7 在linux上已经完成了red…

第五章. 可视化数据分析分析图表—常用图表的绘制1—折线图,柱形图

第五章. 可视化数据分析分析图 5.3 常用图表的绘制1—折线图,柱形图 本节主要介绍常用图表的绘制&#xff0c;主要包括折线图&#xff0c;柱形图。 1.折线图&#xff08;matplotlib.pyplot.plot&#xff09; 折线图可以显示随时间而变化的连续数据&#xff0c;适用于显示在相…

Hadoop原理与技术——hdfs命令行基本操作

一、实验目的 熟悉hdfs命令行基本操作 二、实验环境 Windows 10 VMware Workstation Pro虚拟机 Hadoop环境 Jdk1.8 三、实验内容 1&#xff1a;hdfs常见命令&#xff1a; &#xff08;1&#xff09;查看帮助&#xff1a;hdfs dfs -help &#xff08;2&#xff09;查看当前目录…

OpenCV图像处理——目标追踪

总目录 图像处理总目录←点击这里 二十四、目标追踪 24.1、多目标&#xff08;手动检测&#xff09;追踪 24.1.1、原理 目标检测&#xff1a;运行之后按下s&#xff0c;通过鼠标对某个目标进行检测&#xff0c;然后点击空格或者回车 目标追踪&#xff1a;opencv的八种追踪…

【JavaEE】JavaScript(基础语法)1

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录前言一、JavaScript初识&#xff08;简单了解就行&#xff0c;没时间跳过&#xff09;二、【JS的代码相关】【注释】【输入输出】三、语法1. 变量2. 【基本数据类型】THINK前言 一个人最大的痛苦就是对自己无能的愤…

信贷风控NCL净损失率的指标实现与应用

在金融信贷业务的风险控制过程中&#xff0c;有一项财务指标发挥着比较重要的信息参考价值&#xff0c;可以有效衡量某个月份放款金额在形成呆账后的资金损失情况&#xff0c;其中呆账指的是信贷逾期180天以上&#xff0c;这个指标便是NCL&#xff08;Net Credit Loss&#xff…

大家都在用的福昕阅读器 foxit 你还不知道吗? 祛除水印PDF转换全功能解锁…

趣味拓展 什么字大家看了都说没用&#xff1f; (答案在文末) 引言 福昕阅读器是一款高级PDF编辑器&#xff0c;查看目录、去除水印、编辑文本、转换格式等都是可以用到的~ 小编第一次使用的时候是用来查看pdf文档目录的&#xff0c;当时未使用破解版&#xff0c;后来循序渐进…

基于PHP+MySQL中小学生科学实验展示网站的设计与实现

中小学生科学实验展示网站能够通过互联网得到广泛的、全面的宣传,让尽可能多的人积极的参加到科学实验行列中来,不仅为需要的人提供了服务,而且锻炼了自己,同时能够让中小学生对科学实验的兴趣有很大的提高 PHP中小学生科学实验展示网站是一个科普类型的网站,系统通过PHp&#…

[附源码]Python计算机毕业设计SSM客户信息管理(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

模拟电子技术(四)放大电路的频率响应

&#xff08;四&#xff09;放大电路的频率响应电路理论基础知识复习频率响应基本概念两个无源频率响应的单元电路波特图&#xff08;幅频、相频&#xff09;高、低同电路对比晶体管的高频等效模型单管放大电路的频率响应研究信号频率的变化对放大电路性能的影响也就是电路对输…

Linux零基础入门(二)Linux基础命令

Linux零基础入门&#xff08;二&#xff09;Linux基础命令前言Linux基础命令一 Linux的目录结构1 Linux路径的描述方式二 Linux命令入门1 Linux命令基础格式2 ls命令3 HOME目录和工作目录4 ls命令的参数ls 命令的 -a选项ls命令的 -l选项ls命令选项的组合使用ls选项和参数的组合…

基于人工势场法的二维平面内无人机的路径规划的matlab仿真,并通过对势场法改进避免了无人机陷入极值的问题

目录 1.算法描述 2.matlab算法仿真效果 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 人工势场法原理是&#xff1a;首先构建一个人工虚拟势场&#xff0c;该势场由两部分组成&#xff0c;一部分是目标点对移动机器人产生的引力场&#xff0c;方向由机器人指向目标点&#xf…

C语言——malloc开辟矩阵

目录 用动态内存开辟矩阵 矩阵初始化 用动态内存开辟矩阵 动态内存更多的知识在这篇博客&#xff0c;本文将介绍用malloc开辟矩阵。 malloc是C语言中用来动态开辟内存的&#xff0c;通过malloc函数可以向计算机申请一串连续的内存空间。 因为malloc开辟的内存在堆上&#…