Span<T>之高性能字符串操作实测

简介:

   .net中的字符串操作性能问题由来已久,幸运的是微软推出了span<T>高性能指针操作封装工具类。这个类到底有多高的性能呢?网上传言反正很高,但是实际上在网上很难找到合适的测试实例,这让本人实在无力吐槽。经不住高性能这三个字的诱惑,本人还是了解了一番后做了几个简单样例来测试一番,下面列出几种字符串常见操作的测试代码及其运行结果。

一、String.Index 测试

复制代码
1             var t1 = StopWacherHelper.DoTimer(() =>
2             {
3                 for (int i = 0; i < count; i++)
4                 {
5                     str.IndexOf(subStr);
6                 }
7             });
8 
9             Console.WriteLine($"string.IndexOf {count} 次用时:{t1} 毫秒");
复制代码
复制代码
 1             var t2 = StopWacherHelper.DoTimer(() =>
 2             {
 3                 var strSpan = str.AsSpan();
 4 
 5                 var subStrSpan = subStr.AsSpan();
 6 
 7                 for (int i = 0; i < count; i++)
 8                 {
 9                     strSpan.IndexOf(subStrSpan);
10                 }
11             });
12 
13             Console.WriteLine($"Span<T>.IndexOf {count} 次用时:{t2} 毫秒");
复制代码

 

二、String.Substring 测试

复制代码
1             var t1 = StopWacherHelper.DoTimer(() =>
2             {
3                 for (int i = 0; i < count; i++)
4                 {
5                     str.Substring(0, str.IndexOf(subStr));
6                 }
7             });
8 
9             Console.WriteLine($"String.Substring {count} 次用时:{t1} 毫秒");
复制代码
复制代码
 1             var t2 = StopWacherHelper.DoTimer(() =>
 2             {
 3                 var strSpan = str.AsSpan();
 4 
 5                 var subStrSpan = subStr.AsSpan();
 6 
 7                 var index = strSpan.IndexOf(subStrSpan);
 8 
 9                 for (int i = 0; i < count; i++)
10                 {
11                     strSpan.Slice(0, strSpan.IndexOf(subStrSpan));
12                 }
13             });
复制代码

三、String.Split 测试

复制代码
1             var t1 = StopWacherHelper.DoTimer(() =>
2             {
3                 for (int i = 0; i < count; i++)
4                 {
5                     var arr = str.Split(new string[] { splitStr }, StringSplitOptions.None);
6                 }
7             });
8 
9             Console.WriteLine($"String.Split {count} 次用时:{t1} 毫秒");
复制代码
复制代码
 1             var t2 = StopWacherHelper.DoTimer(() =>
 2             {
 3                 var strSpan = str.AsSpan();
 4 
 5                 var splitSapn = splitStr.AsSpan();
 6 
 7                 int m = 0, n = 0;
 8 
 9                 for (int i = 0; i < count; i++)
10                 {
11                     List<string> arr = new List<string>();
12 
13                     while (true)
14                     {
15                         m = n;
16                         n = strSpan.IndexOf(splitSapn);
17                         if (n > -1)
18                         {
19                             arr.Add(strSpan.Slice(0, n).ToString());
20                             strSpan = strSpan.Slice(n + splitSapn.Length);
21                         }
22                         else
23                         {
24                             break;
25                         }
26                     }
27 
28                 }
29             });
30 
31             Console.WriteLine($"Span<T>.Split {count} 次用时:{t2} 毫秒");
复制代码

四、String.Replace 测试

复制代码
1             var t1 = StopWacherHelper.DoTimer(() =>
2             {
3                 for (int i = 0; i < count; i++)
4                 {
5                     str.Replace(splitStr, replaceStr);
6                 }
7             });
8 
9             Console.WriteLine($"String.Replace {count} 次用时:{t1} 毫秒");
复制代码
复制代码
 1             var t2 = StopWacherHelper.DoTimer(() =>
 2             {
 3                 var strSpan = str.AsSpan();
 4 
 5                 var splitSapn = splitStr.AsSpan();
 6 
 7                 int m = 0, n = 0;
 8 
 9                 for (int i = 0; i < count; i++)
10                 {
11                     List<string> arr = new List<string>();
12 
13                     while (true)
14                     {
15                         m = n;
16                         n = strSpan.IndexOf(splitSapn);
17                         if (n > -1)
18                         {
19                             arr.Add(strSpan.Slice(0, n).ToString());
20                             strSpan = strSpan.Slice(n + splitSapn.Length);
21                         }
22                         else
23                         {
24                             break;
25                         }
26                     }
27                     string.Join(replaceStr, arr);
28                 }
29             });
30 
31             Console.WriteLine($"Span<T>.Replace {count} 次用时:{t2} 毫秒");
复制代码

 

  怎么样,经过上面的测试,是不是觉的Span<T>确实是名不虚传?的确,在上面几个常见场景中,Span<T>的高性能确实不同凡响,差不多是10倍的性能优势!看到这里,小伙伴们是不是觉的字符串操作全改成Span<T>就行了?那下面的两个测试会让大家看清现实,在String.Contains中表现还不如原生的。

一、String.Contains 测试

复制代码
1             var t1 = StopWacherHelper.DoTimer(() =>
2             {
3                 for (int i = 0; i < count; i++)
4                 {
5                     str.Contains(subStr);
6                 }
7             });
8 
9             Console.WriteLine($"string.Contains {count} 次用时:{t1} 毫秒");
复制代码
复制代码
 1             var t2 = StopWacherHelper.DoTimer(() =>
 2             {
 3                 var strSpan = str.AsSpan();
 4 
 5                 var subStrSpan = subStr.AsSpan();
 6 
 7                 for (int i = 0; i < count; i++)
 8                 {
 9                     strSpan.Contains(subStrSpan, StringComparison.CurrentCulture);
10                 }
11             });
12 
13             Console.WriteLine($"Span<T>.Contains {count} 次用时:{t2} 毫秒");
复制代码

  仔细一看,不对啊,Span<T>的Contains里面有其它的大小写和语言相关的判断啊。好,那再换一个原生方法对比测试一下。

二、String.Compare 测试

复制代码
1             var t1 = StopWacherHelper.DoTimer(() =>
2             {
3                 for (int i = 0; i < count; i++)
4                 {
5                     string.Compare(str, subStr, true);
6                 }
7             });
8 
9             Console.WriteLine($"string.Compare {count} 次用时:{t1} 毫秒");
复制代码
复制代码
 1             var t2 = StopWacherHelper.DoTimer(() =>
 2             {
 3                 var strSpan = str.AsSpan();
 4 
 5                 var subStrSpan = subStr.AsSpan();
 6 
 7                 for (int i = 0; i < count; i++)
 8                 {
 9                     strSpan.Contains(subStrSpan, StringComparison.CurrentCultureIgnoreCase);
10                 }
11             });
12 
13             Console.WriteLine($"Span<T>.Contains {count} 次用时:{t2} 毫秒");
复制代码

  还是被反杀了,这说明Span<T>的这个Contains方法可能真的只能在某些地方才能用,不然性能反而会有所下降。

 

目录
相关文章
|
存储 算法 Java
操作系统之存储管理——FIFO算法和LRU算法
存储管理的主要功能之一是合理地分配空间。请求页式管理是一种常用的虚拟存储管理技术。 本实验的目的是通过请求页式管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换算法。
1080 0
操作系统之存储管理——FIFO算法和LRU算法
|
存储 自然语言处理 运维
服务发现比较:Consul vs Zookeeper vs Etcd vs Eureka
这里就平时经常用到的服务发现的产品进行特性的对比,总的来看,目前Consul 自身功能,和 spring cloud 对其集成的支持都相对较为完善,而且运维的复杂度较为简单,Eureka 设计上比较符合场景,但还需持续的完善。
5627 0
|
11月前
|
人工智能 JavaScript 前端开发
利用AI提升代码审查效率
本文探讨了如何利用AI技术提升代码审查效率,包括AI在静态代码分析、代码补全和模式识别等方面的作用,以及使用AI驱动工具、集成CI/CD流程、定制化规则等技巧,旨在帮助开发者优化代码审查流程,提高代码质量和开发效率。
|
Dubbo 关系型数据库 MySQL
nacos常见问题之配置环境变量
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
1402 6
|
传感器 监控 安全
智能家居系统:物联网技术的应用与挑战
在这篇文章中,我们将深入探讨智能家居系统背后的技术原理、实际应用以及面临的主要挑战。通过分析物联网技术如何实现家居自动化,并结合具体案例,本文旨在提供对智能家居发展现状和未来趋势的全面理解。
|
设计模式 测试技术 数据库连接
Entity Framework Core 中的依赖注入超厉害!DI 与 DbContext 完美结合,提升开发效率
【8月更文挑战第31天】依赖注入(DI)是一种软件设计模式,用于将对象的依赖关系与其创建过程解耦,从而提升代码的可测试性、可维护性和可扩展性。在Entity Framework Core中使用DI能够提高可测试性,便于替换DbContext实现以进行单元测试;增强可维护性,使代码模块化并清晰展示组件间的依赖关系;提升可扩展性,方便添加新服务和功能而不需修改现有代码。通过Microsoft.Extensions.DependencyInjection等依赖注入容器,可将DbContext注册并注入到需要使用的类中,简化数据库管理和测试流程。
324 0
|
Java Maven
IDEA Maven项目引入本地外部jar包
IDEA Maven项目引入本地外部jar包
|
监控 关系型数据库 MySQL
centos7搭建zabbix6.2 1
centos7搭建zabbix6.2
411 1
|
存储 Web App开发 安全
全平台最佳密码管理工具大全:支持 Windows、Linux、Mac、Android、iOS 以及企业应用
原文 当谈到网络安全的防护时,从各种网络威胁的角度来看,仅安装一个防病毒软件或运行一个安全的 Linux 操作系统,并不意味你就是足够安全的。
4560 0
|
弹性计算 运维 安全
全面分析和理解PBC
全面分析和理解PBC
7256 0
全面分析和理解PBC