// C:\logs\AzureSDK.log is ~2.5GB file
IEnumerable<string> lines = File.ReadLines(@"C:\logs\AzureSDK.log").SkipWhile(line => false);
Console.WriteLine(string.Join("\n", lines));
return;
这显然不返回迭代器并在内部分配内存,直到我得到OOM 。在true
谓词中返回SkipWhile
不会导致这种情况并按预期完成(在执行期间偶然MB
内存使用量)
根据文档,方法签名和常识,SkipWhile
必须返回迭代器,而不是将所有数据加载到内存中。
机器信息
Microsoft Windows [Version 10.0.14393]
Target 4.5.2, AnyCPU, Release
VS 2015 Update 3
NET 4.6.01586
思考?我必须做一些愚蠢的事情,但不确定是什么
UPD:愚蠢的事情是字符串。我忘记了,这是附加到单个StringBuilder将所有行加载到内存中。
我还检查过SkipWhile来源,这显然非常好:
public static IEnumerable<TSource> SkipWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
return SkipWhileIterator<TSource>(source, predicate);
}
static IEnumerable<TSource> SkipWhileIterator<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate) {
bool yielding = false;
foreach (TSource element in source) {
if (!yielding && !predicate(element)) yielding = true;
if (yielding) yield return element;
}
}
答案 0 :(得分:5)
SkipWhile
会返回一个枚举器。但是然后你使用string.Join
来连接所有内容,因此最终将整个文件加载到内存中。
如果您更改代码以独立处理每一行,您会发现使用的内存要少得多:
foreach (var line in File.ReadLines(@"C:\logs\AzureSDK.log").SkipWhile(_ => false))
{
Console.WriteLine(line);
}
答案 1 :(得分:3)
您的错误不在SkipWhile上,当您传递true时会导致它跳过每一行 - 没有为您的联接返回任何结果。
string.Join导致内存不足异常,因为它试图分配长度为2.5gb的字符串。