7

我很好奇与引擎盖下有什么IEnumerable不同。IObservable我分别了解拉取和推送模式,但是 C# 在内存等方面如何通知订阅者(对于 IObservable)它应该接收内存中的下一位数据以进行处理?观察到的实例如何知道要推送给订阅者的数据发生了变化。

我的问题来自我正在从文件中读取行的测试。该文件总共约6Mb。

标准耗时:4.7s,行数:36587

接收时间:0.68s,行数: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();
    }
}
4

2 回答 2

5

我的预感是您看到的行为反映了操作系统缓存文件。我想如果你颠倒调用的顺序,你会看到类似的速度差异,只是交换了。

您可以通过执行一些热身运行或通过File.Copy在测试每个之前将输入文件复制到临时文件来改进此基准。这样文件就不会“热”,你会得到一个公平的比较。

于 2012-03-16T17:27:07.213 回答
1

我怀疑您正在看到 CLR 的某种内部优化。它可能会在两次调用之间将文件的内容缓存在内存中,以便ToObservable更快地提取内容......

编辑:哦,有疯狂昵称的好同事eeh ...@sixlettervariables 更快,他可能是对的:与其说是CLR,不如说是操作系统在优化。

于 2012-03-16T17:31:42.707 回答