我很好奇IEnumerable
和IObservable
到底有什么不同。我分别理解"拉"one_answers"推"模式,但就内存等而言,C#如何通知订阅者(对于IObservable)它应该接收内存中的下一位数据进行处理?观察到的实例如何知道要推送给订阅者的数据发生了变化。
我的问题来自于我正在进行的一项测试,该测试是从文件中逐行读取的。该文件的总容量约为6Mb。
标准耗时:4.7秒,线路:36587
Rx耗时:0.68秒,行数:36587
Rx如何能够在文件中的每一行上大规模改进正常迭代?
private static void ReadStandardFile()
{
var timer = Stopwatch.StartNew();
var linesProcessed = 0;
foreach (var l in ReadLines(new FileStream(_filePath, FileMode.Open)))
{
var s = l.Split(',');
linesProcessed++;
}
timer.Stop();
_log.DebugFormat("Standard Time Taken: {0}s, lines: {1}",
timer.Elapsed.ToString(), linesProcessed);
}
private static void ReadRxFile()
{
var timer = Stopwatch.StartNew();
var linesProcessed = 0;
var query = ReadLines(new FileStream(_filePath, FileMode.Open)).ToObservable();
using (query.Subscribe((line) =>
{
var s = line.Split(',');
linesProcessed++;
}));
timer.Stop();
_log.DebugFormat("Rx Time Taken: {0}s, lines: {1}",
timer.Elapsed.ToString(), linesProcessed);
}
private static IEnumerable<string> ReadLines(Stream stream)
{
using (StreamReader reader = new StreamReader(stream))
{
while (!reader.EndOfStream)
yield return reader.ReadLine();
}
}
我的直觉是,您看到的行为反映了操作系统缓存文件。我可以想象,如果你颠倒通话顺序,你会看到类似的速度差异,只是交换。
您可以通过执行一些预热运行或在测试每个测试之前使用File.Copy
将输入文件复制到临时文件来改进此基准测试。这样一来,文件就不会"热",而且你会得到一个公平的比较。
我怀疑您看到了CLR的某种内部优化。它可能会在两次调用之间将文件的内容缓存在内存中,这样ToObservable
就可以更快地提取内容。。。
编辑:哦,有个疯狂昵称eeh的好同事@六字母变量的速度更快,他可能是对的:与其说CLR优化,不如说是操作系统在优化。