前言
近日,偶然看见一段代码,在项目中,也是这般用法。然而,实则此般用法当下是欠佳的。且先瞧瞧这一段代码。
public string HandlerActionName2(string actionName)
{
if (actionName.EndsWith("Async", StringComparison.Ordinal))
{
actionName = actionName.Substring(0, actionName.Length - 5); //这里用Substring真的合适不?
}
return actionName;
}
在对 HandlerActionName2 进行调用时,倘若依旧会生成新的字符串,那么此处是否真的有必要产生新字符串呢?在.Net Core 2.1 中提供了 ReadOnlySpan ,将其运用于此能够减少新字符串的创建。
public ReadOnlySpan HandleActionName(ReadOnlySpan actionName)
{
if (actionName.EndsWith("Async", StringComparison.Ordinal))
{
//使用ReadOnlySpan的Slice进行切片,这个没有产生新的字符串
actionName = actionName.Slice(0, actionName.Length - 5);
}
return actionName;
}
性能基准测试
using System;
using BenchmarkDotNet.Attributes;
namespace CSharpBenchmarks.StringTest
{
[MemoryDiagnoser]
[DisassemblyDiagnoser(printSource: true)]
public class StringToReadOnlySpan
{
///
/// 分别执行1024次和202048次
///
[Params(1024, 2048)]
public int Times { get; set; }
///
///这里有两个字符串,用于测试
///
[Params("TestAsync", "Test")]
public string Names { get; set; }
[Benchmark]
public int ReadOnlySpanTest()
{
int count = 0;
for (int i = 0; i < Times; i++)
{
count += HandleActionName(Names).Length;
}
return count;
}
[Benchmark(Baseline = true)]
public int StringTest()
{
int count = 0;
for (int i = 0; i < Times; i++)
{
count += HandlerActionName2(Names).Length;
}
return count;
}
public ReadOnlySpan HandleActionName(ReadOnlySpan actionName)
{
if (actionName.EndsWith("Async", StringComparison.Ordinal))
{
//使用ReadOnlySpan的Slice进行切片,这个没有产生新的字符串
actionName = actionName.Slice(0, actionName.Length - 5);
}
return actionName;
}
public string HandlerActionName2(string actionName)
{
if (actionName.EndsWith("Async", StringComparison.Ordinal))
{
//这里用Substring真的合适不?
actionName = actionName.Substring(0, actionName.Length - 5);
}
return actionName;
}
}
}
笔记本执行结果:
台式机执行结果:
根据测试结果:
1. 如果字符串中没有Async结尾的话,使用String比ReadOnlySpan比快35%和100%之间,具体取决于硬件了.
2. 如果字符中是以Async结尾的话,ReadOnlySpan
个人能力有限,如果您发现有什么不对,请私信我
如果您觉得对您有用的话,可以点个赞或者加个关注,欢迎大家一起进行技术交流