如果谓词为假,c# SkipWhile会泄漏内存
本文关键字:SkipWhile 泄漏 内存 谓词 如果 | 更新日期: 2023-09-27 18:14:37
// 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。在SkipWhile
谓词中返回true
不会导致这种情况,并且按照预期完成(执行期间耦合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;
}
}
SkipWhile
确实返回一个枚举数。但是,您使用string.Join
来连接所有内容,因此最终将整个文件加载到内存中。
如果你改变你的代码来独立处理每一行,你会看到你使用更少的内存:
foreach (var line in File.ReadLines(@"C:'logs'AzureSDK.log").SkipWhile(_ => false))
{
Console.WriteLine(line);
}
您的错误不在SkipWhile上,当您在其中传递true时会导致它跳过每一行-不返回您的连接结果。
字符串。Join导致内存不足异常,因为它试图分配一个长度为2.5gb的字符串