【发布时间】:2025-12-10 14:50:01
【问题描述】:
我正在尝试从包含不同数字的单个字符串中解析不同的 ID(长),并且我需要最小化内存分配以提高性能。
下面是使用 Split 提取 ID 的代码,但我发现我可以使用 AsSpan 和 Splice 来做同样的事情,而无需分配内存。但不幸的是,即使在网上查找后,我对这个 Span 概念也不是很熟悉。谁能告诉我如何实现这一目标?
如下所示,输入字符串有 3 个不同的 ID,但我只需要其中 2 个并解析为 long 类型。
string[] machineIdPart;
string[] employeeIdPart;
long machineId;
long employeeId;
//Input String
var description = "machineId: 276744, engineId: 59440, employeeId: 4619825";
Console.Out.Write(description);
Console.Out.WriteLine();
var infoList = description.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var info in infoList)
{
if (info.TrimStart().StartsWith("machineId", StringComparison.OrdinalIgnoreCase))
{
machineIdPart = info.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
if (machineIdPart.Count() > 1)
{
long.TryParse(machineIdPart[1].Trim(), out machineId);
}
}
if (info.TrimStart().StartsWith("employeeId", StringComparison.OrdinalIgnoreCase))
{
employeeIdPart = info.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
if (employeeIdPart.Count() > 1)
{
long.TryParse(employeeIdPart[1].Trim(), out employeeId);
}
}
}
我想修改此代码以最小化内存分配,因为此方法将非常频繁地运行。
【问题讨论】:
-
您现在是否发现任何性能问题?
-
您会发现从
strings 解析longs 也不会太快。考虑以老式方式执行此操作,跳过寻找,的字符串,并使用x = x * 10 + c - '0'解析自己,避免所有字符串操作一次性完成。如果这仍然是一个性能问题,也可以从Span完成,但这是在另一个层面上(这意味着以更有效的方式提取description)。然而,根据马特——首先确定这是一个实际的瓶颈,即使你知道它会“非常频繁地”运行。优化错误的东西是浪费时间。 -
@Matt.G 我会说是的。上面的代码将插入到部分巨大的处理代码中。进行上述更改后,它增加了性能开销比较没有。这并不重要,但仍希望进一步改进以尽量减少影响。
-
@JeroenMostert 是的,请参阅我上面的评论。如果您不介意的话,您能否详细说明一下使用 Span 的“老式”方式??
-
通过跟踪您的位置(索引)而不是实际创建新字符串来编写一个简单的解析器。对于一个字符串,这个简单的重复调用
.IndexOf就可以了,尽管您也可以编写一个小状态机(switch (description[i]) { case ':': state = State.ParsingNumber; ++i; break; })。主要思想是保留字符串,而不是创建新字符串。在不分配任何内容的情况下解析这个字符串可以通过多种方式完成;您甚至不需要为此深入了解Span。 (不,我现在懒得写解析器了,抱歉。:-P)