使用 std::string_view 提升字符串处理性能
C++标准库提供了一个非常优秀的字符串处理类std::string,我们可以通过该类完成各种字符串操作。但是std::string有一个缺点,它的很多操作都是针对字符串实体,存在不必要的内存拷贝的代码,导致字符串的处理性能不尽如人意。
针对这种情况C++17标准引入了std::string_view这个类,该类不会直接作用在字符串实体上,而是记录字符串处理的位置,这样就可以保证用最小的代价对字符串进行处理。
在几个月前写过 std::string_view 的一些简洁介绍,在其中有提及:Here
做函数形参的时候,使用
std::string_view基本一定优于老式的const std::string&这种写法。
为了验证这个结论,下面的代码实现了一个断词器,然后针对 \(64MB\) 的数据做断词处理并且分别记录使用std::string和std::string_view作为基础类型时断词器运行的时间:
#include <iostream>
#include <chrono>
#include <string_view>
template<class T>
struct tokenizer {
using string_type = T;
using value_type = typename T::value_type;
tokenizer(const string_type & str,
std::enable_if_t<std::disjunction_v<
std::is_same<string_type, std::basic_string<value_type>>,
std::is_same<string_type, std::basic_string_view<value_type>>>> * = nullptr)
: data_(str), begin_(0), end_(0) {}
string_type operator()(const value_type sep) {
for ( ; end_ < data_.size(); ++end_ )
{
if (data_[end_] == sep)
{
auto res = data_.substr(begin_, end_ - begin_);
begin_ = ++end_;
return res;
}
}
if (end_ <= data_.size())
{
return data_.substr(begin_, end_);
}
return "";
}
bool more() const { return end_ < data_.size(); }
private:
const string_type data_;
size_t begin_, end_;
};
auto make_string_data(size_t count, char sep) {
std::string data;
for ( size_t i = 0; i < count; ++i )
{
data.push_back('a' + i % 26);
if (i + 1 != count)
data.push_back(sep);
}
return data;
}
int main() {
auto data = make_string_data(1024 * 1024 * 32, ' ');
{
tokenizer<std::string> tk(data);
auto start = std::chrono::high_resolution_clock::now();
while ( tk.more())
{
tk(' ');
}
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> diff = end - start;
std::cout << "elapsed time = " << diff.count() << std::endl;
}
{
tokenizer<std::string_view> tk(data);
auto start = std::chrono::high_resolution_clock::now();
while ( tk.more())
{
tk(' ');
}
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> diff = end - start;
std::cout << "elapsed time = " << diff.count() << std::endl;
}
return 0;
}
在上面的代码中tokenizer是一个断词器的类模板,接受std::string、std::wstring等std::basic_string模板实例化的类型,同时也能接受std::string_view、std::wstring_view等std::basic_string_view模板实例化的类型。这里采用了SFINAE的方法来约束tokenizer的模板实参必须为以上类型。如果编译环境是C++20标准,可以采用概念来约束模板实参类型。
这份代码tokenizer<std::string>运行结果是0.45秒,如果将tokenizer<std::string>替换为tokenizer<std::string_view>运行时间缩短为0.08秒,性能提升是非常明显的 。

使用 std::string_view 提升字符串处理性能的更多相关文章
- .NET Core中妙用unsafe减少gc提升字符串处理性能
一.前言 昨天在群里讨论怎么样效率的把一个字符串进行反转,一般的情况我们都知道,只要对String对象进行操作,那么就会生成新的String对象,比如"1"+"2&quo ...
- C# 利用StringBuilder提升字符串拼接性能
一个项目中有数据图表呈现,数据量稍大时显得很慢. 用Stopwatch分段监控了一下,发现耗时最多的函数是SaveToExcel 此函数中遍列所有数据行,通过Replace替换标签生成Excel行,然 ...
- dotnet 6 使用 string.Create 提升字符串创建和拼接性能
本文告诉大家,在 dotnet 6 或更高版本的 dotnet 里,如何使用 string.Create 提升字符串创建和拼接的性能,减少拼接字符串时,需要额外申请的内存,从而减少内存回收压力 本文也 ...
- jQuery 做好七件事帮你提升jQuery的性能
1. Append Outside of Loops 凡是触及到DOM都是有代价的.如果你向DOM当中附加大量的元素,你会想一次性将它们全部附加进来,而不是分多次进行.当在循环当中附加元素就会产生一个 ...
- java字符串格式化性能对比String.format/StringBuilder/+拼接
String.format由于每次都有生成一个Formatter对象,因此速度会比较慢,在大数据量需要格式化处理的时候,避免使用String.format进行格式化,相反使用StringUtils.l ...
- Jmeter 压力测试笔记(3)--脚本调试/签名/cookie/提升吞吐量/降低异常率/提升单机并发性能
import XXXsign.Openapi2sign;---导入jar包中的签名方法 String str1 = "12121"; ---需要被签名的字段:向开发了解需要哪些哪些 ...
- 提升VMware虚拟机性能招数
在VMware虚拟机(VMware Workstation或VMware Server)中我们可以同时运行多个Guest OS,当同时在同一Host OS中运行多台虚拟机时势必会严重影响到Host O ...
- psutil 是因为该包能提升 memory_profiler 的性能
python 性能分析入门指南 一点号数据玩家昨天 限时干货下载:添加微信公众号"数据玩家「fbigdata」" 回复[7]免费获取[完整数据分析资料!(包括SPSS.SAS.SQ ...
- 如何提升 CSS 选择器性能
CSS 选择器性能损耗来自? CSS选择器对性能的影响源于浏览器匹配选择器和文档元素时所消耗的时间,所以优化选择器的原则是应尽量避免使用消耗更多匹配时间的选择器.而在这之前我们需要了解CSS选择器匹配 ...
- 七个可以提升python程序性能的好习惯,你知道吗?
掌握一些技巧,可尽量提高Python程序性能,也可以避免不必要的资源浪费.今天就为大家带来七个可以提升python程序性能的好习惯,赶快来学习吧:. 1.使用局部变量 尽量使用局部变量代替全局变量:便 ...
随机推荐
- Access denied for user ‘root‘@‘localhost‘ (using password:YES)解决方法
修改jdbc.properties文件的密码
- 【UniApp】-uni-app-修改组件主题和样式
前言 好,经过上个章节的介绍完毕之后,了解了一下 uni-app-扩展组件 那么了解完了uni-app-扩展组件之后,这篇文章来给大家介绍一下 uni-app-修改组件主题和样式 首先不管三七二十一, ...
- [CF403E]Two Rooted Trees
Two Rooted Trees 题面翻译 题目描述 你有两棵有根树,每棵树都有 \(n\) 个结点.不妨将这两棵树上的点都用 \(1\) 到 \(n\) 之间的整数编号.每棵树的根结点都是 \(1\ ...
- [ABC261D] Flipping and Bonus
Problem Statement Takahashi will toss a coin $N$ times. He also has a counter, which initially shows ...
- 同样的SQL,怎么突然就慢了?
本篇文章素材来源于某银行系统的一次性能问题分析. 许久没写这种troubleshooting类型的技术文章了,因为曾在服务公司呆过多年,工作原因,这方面之前做的多,听的更多,导致已经达到在自己认知维度 ...
- 【笔记整理】忽略https证书校验
import requests url = "https://sam.huat.edu.cn:8443/selfservice/" # 默认不忽略ssl证书,如果有证书问题的网站会 ...
- 华企盾DSC邮件发送成功,但是不解密也没有任何提示(未添加白名单)
用Debugview监控整个过程,若日志中有信任邮箱未添加说明,白名单邮箱未添加或者添加错了(检查空格之类的或重新添加)
- Kernel Memory 入门系列:Semantic Kernel 插件
Kernel Memory 入门系列:Semantic Kernel 插件 Kernel Memory 本身提供了完整的RAG能力,这部分能力如果通过Semantic Kernel Memory的话, ...
- 【推荐】后现代风格文本编辑器-Helix
目录 Helix简介 Helix 安装 Linux平台 Ubuntu Fedora/RHEL Arch Linux extra NixOS Flatpak Snap AppImage macOS系统 ...
- k8s卷管理-2
目录 k8s卷管理-2 pv和pvc pv pv的定义 pvc pvc的定义 pv和pvc的绑定关系 手动指定pv与pvc绑定 pod使用pvc pod挂载pvc 访问模式的区别 k8s卷管理-2 之 ...