Чем IEnumerable отличается от IObservable под капотом? - PullRequest
7 голосов
/ 16 марта 2012

Мне любопытно, как IEnumerable отличается от IObservable под капотом. Я понимаю шаблоны «выталкивания» и «выталкивания» соответственно, но как C #, с точки зрения памяти и т. Д., Уведомляет подписчиков (для IObservable), что он должен получить следующий бит данных в памяти для обработки? Как наблюдаемый экземпляр узнал, что он изменил данные для отправки подписчикам.

Мой вопрос возник из теста, который я выполнял в виде строк из файла. Файл был около 6 МБ в общей сложности.

Стандартное время: 4,7 с, строки: 36587

Время приема: 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();
    }
}

Ответы [ 2 ]

5 голосов
/ 16 марта 2012

Я подозреваю, что поведение, которое вы видите, отражает кеширование файла операционной системой.Я думаю, что если вы измените порядок вызовов, вы увидите похожую разницу в скоростях, просто поменяйте местами.

Вы можете улучшить этот тест, выполнив несколько прогонов прогона или скопировав входной файл ввременный файл, используя File.Copy перед тестированием каждого.Таким образом, файл не будет «горячим», и вы получите справедливое сравнение.

1 голос
/ 16 марта 2012

Я подозреваю, что вы видите какую-то внутреннюю оптимизацию CLR.Он, вероятно, кэширует содержимое файла в памяти между двумя вызовами, так что ToObservable может извлечь содержимое намного быстрее ...

Редактировать: О, хороший коллега с сумасшедшим псевдонимом eeh ... @Sixlettervariables был быстрее, и он, вероятно, прав: скорее оптимизируется ОС, чем CLR.

...