什么减慢Aggregate <ienumerable <char>,StringBuilder&gt;与我的扩展方法相比?

时间:2016-10-25 10:12:45

标签: c# string performance lambda aggregate

前段时间我有一个案例,即使用MyString.Skip(..).Take(..)代替MyString.Substring(..)很方便。但是SkipTake会返回IEnumerable<char>而不是新的string,所以我编写了自己的concat函数:

    public static string Concat(this IEnumerable<char> char_sequence) {
        var sb = new StringBuilder();
        foreach (var c in char_sequence)
        {
            sb.Append(c);
        }
        return sb.ToString();
    }

今天我不得不做同样的事情,但记得改为使用Aggregate

MyString.Skip(..).Take(..).Aggregate(new StringBuilder(), (current, next) => current.Append(next)).ToString()

因为代码已经存在,所以我进行了快速的性能测试。对于大型文本文件,Aggregate似乎要慢50%以上:

480KB .txt document, 1000 iterations (loading the document was not included in the test)

Function | Time (ms)
--------------------
Aggregate|    14,701
Concat   |     8,068

但为什么呢?根据{{​​3}},Aggregate使用此方法:

    public static TAccumulate Aggregate<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func) {
        if (source == null) throw Error.ArgumentNull("source");
        if (func == null) throw Error.ArgumentNull("func");
        TAccumulate result = seed;
        foreach (TSource element in source) result = func(result, element);
        return result;
    }

如果您将TSource替换为charTAccumulate替换为StringBuilder,则代码基本相同。这种速度差异来自哪里,有没有办法加快Aggregate



为了完整起见,在我写这个问题之前,我实际上做了两个以上的基准测试(虽然我因某种原因忘记了Substring,所以我不得不再次运行它)。请记住,我的问题不是关于使用什么,而是为什么Aggregate和自定义Concat之间存在差异。

Function                | Time (ms)         (Additional Notes)
-----------------------------------------------------------
Aggregate               |    14070
Parallel().Aggregate    |    14016        (uses only one thread)
new String()            |     7784
String.Concat           |    13342
Concat Extension        |     7997
Substring               |      329

0 个答案:

没有答案