如何提高循环效率

时间:2020-03-02 08:04:46

标签: c# loops

我正在尝试将数据保存到csv文件中。当速率较小(节省2,000 / s)时,效果很好。但是当增加到20,000 / s时,它的工作速度就会变慢。

class Channel 
{
    List<double> RawData { get; set; }
    ...
}

-----------------------------------

var channels = new List<Channel>();
// after fetch the data
var sw = new StreamWriter(FileStream, Encoding.Default);
for (i = 0; channels.First().RawData.Count; i ++)
{
    string line = DateTime.Now.ToString() + ",";
    line += string.Join(',', channels.Select(c => c.RawData[i]));
    sw.WriteLine(line);
    sw.Flush();
}

当每个RawData的{​​{1}}的数量达到20,000时,该应用将运行缓慢。有什么解决方案可以加快channel的生成速度?

2 个答案:

答案 0 :(得分:4)

您可以采取一些措施来加快速度。

通常,I / O操作昂贵(最慢),因此请避免执行许多操作,而只写一次或几次。

多次执行此操作时,字符串修改也很慢。因此,您应该使用StringBuilder。

最后,在我看来,您使用的日期时间在许多情况下(但可能不是全部!)将是相同的值。如果是这种情况,则可以只调用一次,然后输出相同的值。

您也许还可以加快频道的Select语句(根据其他帖子)。

因此,您将获得如下代码:

StringBuilder sb = new StringBuilder();
string dtValue = DateTime.Now.ToString();

for (int i = 0; channels.First().RawData.Count; i++)
{
    sb.Append(dtValue).Append(",").Append(channels.First().RawData[i]).Append(Environment.NewLine);    
}

//Write just once.
using (var sw = new StreamWriter(FileStream, Encoding.Default))
{
    sw.Writeline(sb.ToString());
    sw.Close();
}

编辑:根据评论更新为使用channels.First()。RawData [i]。

答案 1 :(得分:1)

您可以使用Write(string)方法,并且不连接字符串。

也不应为每次迭代调用StreamWriter.Flush方法。

for (i = 0; channels.First().RawData.Count; i ++)未编译,因此不应该使用,因为string.Join(',', channels.Select(c => c.RawData[i]));将遍历所有项目。

下面的示例代码不进行串联,并且不读取内存中的所有数据。它将通道数据分别写入每个通道的流中。当然,这将花费一些时间,并且您拥有的数据越多,它将起作用的时间越长。

var channels = new List<Channel>();
// after fetch the data
using (var sw = new StreamWriter(FileStream, Encoding.Default)) // you have to check that both stream writer and `FileStream` instances are disposed properly 
{
foreach (var ch in channels)
{
sw.Write(string.Format("{0:ddMMyyyy hh:mm:ss},", DateTime.Now)); // it writes date time for every channel data 
foreach (var data in ch.RawData)
{
    sw.Write(string.Format("{0},", data.ToString(Culture.InvariantCulture)); // double.ToString() is culture specific so you can use Culture.InvariantCulture when converting double to string
}
sw.WriteLine(""); // last line break but note that all channel data are written in one line separated with commas
}
}

主要思想不是将所有通道RawData列表项连接到字符串。 肯定需要更多时间和内存才能将20000双精度转换为一个字符串。

它只是将RawData项目一一写入文件,并节省时间和内存(希望如此)