【发布时间】:2015-09-30 08:33:00
【问题描述】:
我正在将文本文件 (.itf) 与位于文件夹中的一些逻辑合并。当我将它编译为 32 位(控制台应用程序,.Net 4.6)时,一切正常,除了如果文件夹中有大量数据,我会得到 outofmemory 异常。将其编译为 64 位可以解决该问题,但与 32 位进程相比,它的运行速度非常慢(慢了 15 倍以上)。
我用BufferedStream 和ReadAllLines 进行了尝试,但两者的性能都很差。分析器告诉我,这些方法在 99% 的时间里都在使用。不知道是不是问题...
代码如下:
private static void readData(Dictionary<string, Topic> topics)
{
foreach (string file in Directory.EnumerateFiles(Path, "*.itf"))
{
Topic currentTopic = null;
Table currentTable = null;
Object currentObject = null;
using (var fs = File.Open(file, FileMode.Open))
{
using (var bs = new BufferedStream(fs))
{
using (var sr = new StreamReader(bs, Encoding.Default))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (line.IndexOf("ETOP") > -1)
{
currentTopic = null;
}
else if (line.IndexOf("ETAB") > -1)
{
currentTable = null;
}
else if (line.IndexOf("ELIN") > -1)
{
currentObject = null;
}
else if (line.IndexOf("MTID") > -1)
{
MTID = line.Replace("MTID ", "");
}
else if (line.IndexOf("MODL") > -1)
{
MODL = line.Replace("MODL ", "");
}
else if (line.IndexOf("TOPI") > -1)
{
var name = line.Replace("TOPI ", "");
if (topics.ContainsKey(name))
{
currentTopic = topics[name];
}
else
{
var topic = new Topic(name);
currentTopic = topic;
topics.Add(name, topic);
}
}
else if (line.IndexOf("TABL") > -1)
{
var name = line.Replace("TABL ", "");
if (currentTopic.Tables.ContainsKey(name))
{
currentTable = currentTopic.Tables[name];
}
else
{
var table = new Table(name);
currentTable = table;
currentTopic.Tables.Add(name, table);
}
}
else if (line.IndexOf("OBJE") > -1)
{
if (currentTable.Name != "Metadata" || currentTable.Objects.Count == 0)
{
var shortLine = line.Replace("OBJE ", "");
var obje = new Object(shortLine.Substring(shortLine.IndexOf(" ")));
currentObject = obje;
currentTable.Objects.Add(obje);
}
}
else if (currentTopic != null && currentTable != null && currentObject != null)
{
currentObject.Data.Add(line);
}
}
}
}
}
}
}
【问题讨论】:
-
那么分析器所说的正在减慢速度的
ReadAllLines在哪里?此外,您的瓶颈可能是由于string.IndexOf。提示:投资创建一个合适的词法分析器/解析器。 -
我想知道字符串分配的数量(所有这些对
.Replace创建新字符串的调用)是否是罪魁祸首——真正的分析器可能会告诉我,但我想知道是否有一种机制将整个文件作为一个流并逐个字符读取而无需重新解析/操作该行将是这里更好的解决方案。 -
代码示例显示
BufferedStream版本。我也有一个ReadAllLines。在 32 位中,分析器确实说Replace和IndexOf方法会消耗大量时间。但是,我想知道为什么 64 位版本要慢得多。 -
我不确定为什么 64 位版本比 32 位版本慢。无论如何...每次您致电
line.IndexOf时,它都会从头开始读取该行。那非常耗时。我建议您实现自己的查找索引的方法。 -
@M.kazemAkhgary 我不确定你能比微软版本的 IndexOf 做得更好...