- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我有一些代码可以在我自己的类 R C# DataFrame 类中处理数百万行数据。有许多 Parallel.ForEach 调用用于并行迭代数据行。此代码已使用 VS2013 和 .NET 4.5 运行了一年多,没有出现任何问题。
我有两台开发机器(A 和 B),最近将机器 A 升级到 VS2015。大约有一半时间我开始注意到我的代码出现奇怪的间歇性卡住。让它运行很长时间,事实证明代码最终确实完成了。只需 15-120 分钟,而不是 1-2 分钟。
由于某种原因,使用 VS2015 调试器尝试破解所有内容的尝试不断失败。所以我插入了一堆日志语句。事实证明,当在 Parallel.ForEach 循环期间存在 Gen2 集合时(比较每个 Parallel.ForEach 循环前后的集合计数),就会发生这种卡住。额外的 13-118 分钟都花在了 Parallel.ForEach 循环调用恰好与 Gen2 集合(如果有)重叠的情况下。如果在任何 Parallel.ForEach 循环期间没有 Gen2 集合(大约 50% 的时间我运行它),那么一切都会在 1-2 分钟内完成。
当我在机器 A 上的 VS2013 中运行相同的代码时,我得到了相同的卡住。当我在机器 B(从未升级过)上运行 VS2013 中的代码时,它运行良好。连夜跑了几十次,没有卡顿。
我注意到/尝试过的一些事情:
我根本没有更改默认的 GC 设置。根据 GCSettings,所有运行都在 LatencyMode Interactive 和 IsServerGC 为 false 的情况下发生。
我可以在每次调用 Parallel.ForEach 之前切换到 LowLatency,但我真的更愿意了解发生了什么。
有没有其他人在 VS2015 升级后看到 Parallel.ForEach 中出现奇怪的卡住?关于下一步的好的想法是什么?
更新 1:在上面的模糊解释中添加一些示例代码...
我希望这里有一些示例代码可以演示这个问题。这段代码在 B 机器上运行 10-12 秒,始终如一。它遇到了一些 Gen2 集合,但它们几乎没有花费任何时间。如果我取消注释这两个 GC 设置行,我可以强制它没有 Gen2 收集。它比 30-50 秒要慢一些。
现在在我的 A 机器上,代码花费的时间是随机的。似乎在 5 到 30 分钟之间。而且它似乎变得更糟,它遇到的 Gen2 集合越多。如果我取消注释这两个 GC 设置行,则机器 A 也需要 30-50 秒(与机器 B 相同)。
要在另一台机器上显示,可能需要对行数和数组大小进行一些调整。
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using System.Runtime;
public class MyDataRow
{
public int Id { get; set; }
public double Value { get; set; }
public double DerivedValuesSum { get; set; }
public double[] DerivedValues { get; set; }
}
class Program
{
static void Example()
{
const int numRows = 2000000;
const int tempArraySize = 250;
var r = new Random();
var dataFrame = new List<MyDataRow>(numRows);
for (int i = 0; i < numRows; i++) dataFrame.Add(new MyDataRow { Id = i, Value = r.NextDouble() });
Stopwatch stw = Stopwatch.StartNew();
int gcs0Initial = GC.CollectionCount(0);
int gcs1Initial = GC.CollectionCount(1);
int gcs2Initial = GC.CollectionCount(2);
//GCSettings.LatencyMode = GCLatencyMode.LowLatency;
Parallel.ForEach(dataFrame, dr =>
{
double[] tempArray = new double[tempArraySize];
for (int j = 0; j < tempArraySize; j++) tempArray[j] = Math.Pow(dr.Value, j);
dr.DerivedValuesSum = tempArray.Sum();
dr.DerivedValues = tempArray.ToArray();
});
int gcs0Final = GC.CollectionCount(0);
int gcs1Final = GC.CollectionCount(1);
int gcs2Final = GC.CollectionCount(2);
stw.Stop();
//GCSettings.LatencyMode = GCLatencyMode.Interactive;
Console.Out.WriteLine("ElapsedTime = {0} Seconds ({1} Minutes)", stw.Elapsed.TotalSeconds, stw.Elapsed.TotalMinutes);
Console.Out.WriteLine("Gcs0 = {0} = {1} - {2}", gcs0Final - gcs0Initial, gcs0Final, gcs0Initial);
Console.Out.WriteLine("Gcs1 = {0} = {1} - {2}", gcs1Final - gcs1Initial, gcs1Final, gcs1Initial);
Console.Out.WriteLine("Gcs2 = {0} = {1} - {2}", gcs2Final - gcs2Initial, gcs2Final, gcs2Initial);
Console.Out.WriteLine("Press Any Key To Exit...");
Console.In.ReadLine();
}
static void Main(string[] args)
{
Example();
}
}
更新 2:只是为了将评论中的内容移出以供 future 的读者使用...
此修补程序:https://support.microsoft.com/en-us/kb/3088957完全解决了这个问题。申请后我完全没有看到任何缓慢的问题。
事实证明与 Parallel.ForEach 没有任何关系我相信基于此:http://blogs.msdn.com/b/maoni/archive/2015/08/12/gen2-free-list-changes-in-clr-4-6-gc.aspx尽管出于某种原因,修补程序确实提到了 Parallel.ForEach。
最佳答案
这确实表现得太差了,后台 GC 在这里对你不利。我注意到的第一件事是 Parallel.ForEach() 使用了太多任务。线程池管理器将线程行为误解为“因 I/O 而陷入困境”并启动额外的线程。这使问题变得更糟。解决方法是:
var options = new ParallelOptions();
options.MaxDegreeOfParallelism = Environment.ProcessorCount;
Parallel.ForEach(dataFrame, options, dr => {
// etc..
}
这可以让您更好地了解 VS2015 中新诊断中心的程序出了什么问题。只需一个 单个 内核即可完成任何工作,这很容易从 CPU 使用情况中看出。偶尔出现尖峰,它们不会持续很长时间,与橙色 GC 标记一致。当您仔细查看 GC 标记时,您会发现它是一个 gen #1 集合。花费了非常的时间,在我的机器上大约需要 6 秒。
第 1 代收集当然不会花那么长时间,您在这里看到的是第 1 代收集在等待后台 GC 完成其工作。换句话说,实际上是后台 GC 花费了 6 秒。仅当 gen #0 和 gen #1 段中的空间足够大以在后台 GC 运行时不需要 gen #2 收集时,后台 GC 才有效。不是这个应用程序的工作方式,它以非常高的速度消耗内存。您看到的小峰值是多个任务被解除阻塞,能够再次分配数组。当第 1 代收集必须再次等待后台 GC 时,快速停止。
值得注意的是这段代码的分配模式对GC非常不友好。它将长生命周期数组 (dr.DerivedValues) 与短生命周期数组 (tempArray) 交织在一起。在压缩堆时给 GC 大量工作,每个分配的数组最终都会被移动。
.NET 4.6 GC 中的明显缺陷是后台收集似乎从未有效地压缩堆。 看起来它一遍又一遍地完成这项工作,就好像上一个集合根本没有压缩一样。很难说这是设计使然还是错误,我再也没有干净的 4.5 机器了。我当然倾向于错误。您应该在 connect.microsoft.com 上报告此问题,以便 Microsoft 进行检查。
解决方法很容易找到,您所要做的就是防止长生命周期和短生命周期对象尴尬地交织在一起。您可以通过预先分配它们来实现:
for (int i = 0; i < numRows; i++) dataFrame.Add(new MyDataRow {
Id = i, Value = r.NextDouble(),
DerivedValues = new double[tempArraySize] });
...
Parallel.ForEach(dataFrame, options, dr => {
var array = dr.DerivedValues;
for (int j = 0; j < array.Length; j++) array[j] = Math.Pow(dr.Value, j);
dr.DerivedValuesSum = array.Sum();
});
当然还有完全禁用后台 GC。
更新:在 this blog post 中确认了 GC 错误.即将修复。
更新:已在 .NET 4.6.1 中修复
关于c# - VS2015升级后的垃圾回收和Parallel.ForEach问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31747992/
我是 Mercurial 的新手,并且不知何故仍处于评估过程中,所以这四个概念对我来说有点困惑。有些被提到等同于 Git 的 Staging/Index 概念,有些甚至比 Git 的 Staging
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 6 个月前关闭。 Improve this ques
任何人都可以给我详细信息吗? 例如? #ID 是属性、特性、选择器还是 anchor ? 默认属性和默认属性是不同的东西吗? 这些都是标签还是元素? 我们将对此说些什么 这个 ..... 还有这些
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 8 年前。 Improve this qu
我有一个由 Javascript 填充的下拉列表。 在决定加载时显示的默认值时,我意识到以下属性显示的值完全相同: innerText innerHTML label text textContent
我可以知道每个 Exec 之间有什么区别吗? , ExecWait , ExecShell , nsExec::Exec , nsExec::ExecToLog, nsExec::ExecToStac
当您处于版本 1 和版本 2 之间时,您会如何维护您的软件? 从我的角度来看,“补丁”、“修补程序”、“维护版本”、“服务包”等术语都很模糊,根据与您交谈的对象不同,定义也不同。 您如何称呼版本之间的
我刚刚发现在 ES6 中有一个新的数学方法:Math.trunc . 我在 MDN article 中阅读了它的描述。 , 听起来像使用 |0 . 此外,>0 , &-1 , ^0也做类似的事情(感谢
我想知道我的 StackPanel 所有项目的高度。 有什么区别: Height - 获取或设置元素的建议高度。 ActualHeight - 获取该元素的渲染高度。 (只读) ExtentHeigh
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 9 年前。 Improve this
我对所有声称以某种方式阻止计算的内置 Mathematica 函数感到困惑:Unevaluated、Defer、Hold ,以及超过 6 个 Hold* 形式。 Mathematica 文档只是单独解
我什至不确定正确的术语,所以让我从我的目标开始:拥有一个简单的应用程序(“Data Doler”),它只会将大量数据从文件读取到内存中,然后提供服务将该数据切片到名为“Data Lapper”的单个多
我刚刚开始在我的项目中使用 Elasticsearch,我想像 sql 关键字一样搜索 '喜欢%' 做。 谁能解释一下 之间的区别通配符 , 前缀 , 查询字符串和 正则表达式 ? 哪个可以搜索最好性
由于我对任何主流浏览器(Firefox、Chrome、Opera)都不太满意,而且我尝试过的不太受欢迎的浏览器(近十几种)都没有,所以我决定 DIY 并制作一个网页我想要最好的浏览器。 主要目标是让它
我知道如何使用 Python 解析页面。我的问题是哪种方法是所有解析技术中最快的,其他方法的速度有多快? 我知道的解析技术有Xpath、DOM、BeautifulSoup,还有使用Python的fin
我试图从正在解析的命令行中找出哪个函数最适合将十进制、十六进制或八进制数转换为 int 最好——在不知道输入的情况下事先。 目标是使用一个函数来识别不同类型的输入并将其分配给它的整数 (int) 值,
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我们需要在我们的网站上显示酒吧、餐馆和剧院等各种场所的元信息(例如,地址、姓名)。 理想情况下,用户会输入地点名称以及邮政编码,我们会提供最接近的匹配项。 人们将哪些 API 用于类似的地理定位目的?
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我正在创建我的第一个 Web 应用程序,我真的很困惑应该使用什么技术。 我的应用程序需要看起来很严肃(像一个应用程序),它不需要很多色彩缤纷的图形界面。它只需要一个工具栏、一个标签栏、一个拆分面板(最
我是一名优秀的程序员,十分优秀!