最近,我一直在研究代码审查和优化重构。我发现,在许多代码场景中,使用是一种改变游戏规则的方法,可以显著提高代码性能。Span<T>
在这里,我将分享两个实际示例,展示如何利用它来优化代码并实现性能改进。Span<T>
什么?Span<T>
Span<T>是 C# 7.2 中引入的一种语法,它提供了一种高效且安全的方式来读取和写入内存。有了 ,我们可以直接操作数组、堆栈和堆等内存区域,避免不必要的内存分配和复制,从而提高代码性能和效率。Span<T>
您可以在何处使用 ?Span<T>
**数组操作:**可以直接访问数组元素,无需额外的内存副本,非常适合需要高效数组数据处理的场景。Span
**字符串操作:**实现高效的字符串处理,如拆分、搜索和替换,消除不必要的字符串分配和复制。Span
**内存池管理:**可与内存池配合使用,提高内存分配和释放效率,减轻 GC 压力。Span
**文件 I/O 操作:**最大限度地减少文件读写操作中的内存复制开销,从而提高读/写效率。Span
**网络编程:**在网络编程中,可以处理网络数据包,解析协议,提高网络数据处理效率。Span
**异步编程:**可以与异步编程集成,提供高效的数据处理方法。例如,它减少了处理大量数据时的内存复制开销。Span
使用 Span 的内存操作
// Create an array containing integer data
int[] array = new int[] { 1, 2, 3, 4, 5 };
// Use Span to manipulate the array
Span<int> span = array.AsSpan();
span[2] = 10; // Modify the third element's value to 10
// Output the modified array
foreach (var num in array)
{
Console.Write(num);
}
// Output result: 121045
这个简单的示例演示了如何使用和修改数组的元素值直接操作数组。让我们从我的开发经验中深入研究实际用例,以进一步说明 .我将包含优化前代码以进行性能比较,让您直接见证 .Span<T>Span<T>Span<T>
案例一:字符串拆分和数组类型转换
我需要从以下字符串中提取逗号分隔的数字,并将它们转换为整数数组。
const string StringForSplit = "666,747,200,468,471,395,942,589,87,353,456,536,772,599,552,338,553,925,532,383,668,96,61,125,621,917,774,146,54,885";
1. 预优化代码:
public int[] TestSplitString()
{
return StringForSplit.Split(',').Select(x => Convert.ToInt32(x)).ToArray();
}
2. 优化代码:Span<T>
public int[] TestSplitStringWithSpan()
{
var span = StringForSplit.AsSpan();
var separator = ",".AsSpan();
var sepLen = separator.Length;
var index = -1;
var result = new List<int>();
do
{
index = span.IndexOf(separator);
if (index == -1)
{
result.Add(int.Parse(span));
}
else
{
var value = span.Slice(0, index);
result.Add(int.Parse(value));
span = span.Slice(index + sepLen);
}
}
while (index != -1);
return result.ToArray();
}
3. 性能比较
上面的数据清楚地表明了显著的优化。内存使用量降低 64%,执行速度提升 30%。
案例二:从 HTML 代码中提取文本内容
我需要从以下 HTML 代码中提取 Country 信息。
const string HtmlCode = @"<html>
<head>
<meta charset=""utf-8"">
<title>Test Page</title>
</head>
<body>
<header>...</header>
<main>
<article>
<h3>Country list</h3>
<ul>
<li><span>Australia</span></li>
<li><span>Brazil</span></li>
<li><span>Canada</span></li>
<li><span>China</span></li>
<li><span>France</span></li>
<li><span>Germany</span></li>
<li><span>Japan</span></li>
<li><span>South Korea</span></li>
<li><span>United States</span></li>
<li><span>United Kingdom</span></li>
</ul>
</article>
</main>
<footer>...</footer>
</body>
</html>";
1. 预优化代码:
我想到的第一个想法是使用正则表达式。这就是前面的代码所做的。
public string[] TestFilterWithRegularExpression()
{
const string REGX_PTN = @"<li><span>(.*)<\/span><\/li>";
var matches = Regex.Matches(HtmlCode, REGX_PTN);
var result = new List<string>();
foreach (Match match in matches)
{
result.Add(match.Groups[1].Value);
}
return result.ToArray();
}
2. 优化代码:Span<T>
public string[] TestFilterWithSpan()
{
const string countryBegin = "<h3>Country list</h3>";
const string countryEnd = "</ul>";
const string startTag = "<li><span>";
const string endTag = "</span>";
var span = HtmlCode.AsSpan();
var countrySpan = countryBegin.AsSpan();
int index = span.IndexOf(countrySpan);
span = span.Slice(index + countrySpan.Length);
index = span.IndexOf(countryEnd.AsSpan());
span = span.Slice(0, index);
var startTagSpan = startTag.AsSpan();
var endTagSpan = endTag.AsSpan();
var startTagLen = startTagSpan.Length;
var endTagLen = endTagSpan.Length;
var result = new List<string>();
while (true)
{
index = span.IndexOf(startTagSpan);
var endIndex = span.IndexOf(endTagSpan);
if (index == -1 || endIndex ==-1) break;
var value = span.Slice(index + startTagLen, endIndex -index-startTagLen);
result.Add(value.ToString());
span = span.Slice(endIndex + endTagLen);
}
return result.ToArray();
}
3. 性能比较
这组数据对比简直就是“惊艳”!优化后的代码在执行速度和内存使用方面都实现了数倍甚至十倍的改进!Span<T>
在内存管理、优化和安全性方面提供出色的性能。如果您的目标是代码性能,请尝试一下。通过对这两种情况的并排比较,您无疑会被它的功能所吸引。
如果你喜欢我的文章,请给我一个赞!谢谢