C#非常慢的StreamReader
本文关键字:StreamReader 非常 | 更新日期: 2023-09-27 18:29:33
我正在使用自己编写的一些非最佳代码…:-|
我有以下代码:
string fmtLine = "";
string[] splitedFmtLine;
int counterFMTlines = 0;
foreach (string fmtF in fmtFiles)
{
using (StreamReader sr = new StreamReader(fmtF))
{
while ((fmtLine = sr.ReadLine()) != null)
{
Console.WriteLine(counterFMTlines++);
foreach (L3Message message in rez)
{
splitedFmtLine = Regex.Split(fmtLine, "'t");
if (message.Time == splitedFmtLine[0])
{
message.ScramblingCode = splitedFmtLine[7];
}
}
}
}
}
当List为空并且只有一个文件(制表符分隔,280000行)时,我测试了这段代码,即使在那时,我也花了很长的时间(1分钟)来遍历文件中的所有280000行。这意味着执行跳过了foreach循环,其中是我的myObjs列表。
我不明白为什么花了这么长时间?
例如,我用不同的文本文件(源文件)填充myObjs列表(树层次结构),但比这个制表符分隔的文件大(制表符分隔:16MB,源文件:36MB),只花了几秒钟,而这只花了1分钟。
您正在向控制台写入280000次,这非常慢。拆下控制台输出。另外,使用字符串。Split('''t'),它比这个特定的regex调用快得多。
除了写入控制台的问题外,您还有一个O(m*n)运行时,其中n是文件中的行数,m是消息数。如果m或n很大,这就很糟糕。通过使用Dictionary
并消除内部循环,可以将其简化为O(n)运算。
您可以使用"时间"作为密钥将消息放入Dictionary
中。在循环中,您只需向字典查询特定时间的消息:
string fmtLine = "";
string[] splitedFmtLine;
int counterFMTlines = 0;
var messageTimes = new Dictionary<string, LinkedList<L3Message>>();
foreach (L3Message message in rez)
{
LinkedList<L3Message> list=null;
messageTimes.TryGetValue(message.Time, out list);
list = list ?? new LinkedList<L3Message>();
list.AddLast(message);
messageTimes[message.Time] = list;
}
foreach (string fmtF in fmtFiles)
{
using (StreamReader sr = new StreamReader(fmtF))
{
while ((fmtLine = sr.ReadLine()) != null)
{
//Console.WriteLine(counterFMTlines++);
splitedFmtLine = fmtLine.Split(''t');
LinkedList<L3Message> messageList = null;
messageTimes.TryGetValue(splitedFmtLine[0], out messageList);
if(messageList != null)
{
foreach (var message in messageList)
{
message.ScramblingCode = splitedFmtLine[7];
}
messageTimes.Remove(splitedFmtLine[0]); //see comments
}
if(messageTimes.Count==0) break; //see comments
}
}
if(messageTimes.Count==0) break; //see comments
}
这应该非常快。
编辑:我更改了示例,使其支持一次有多条消息的情况。
Edit2:我添加了一个优化,它基于消息时间和ScramblingCode总是相关的事实(请参阅注释)。