c# - “指示托管堆垃圾收集的开始”到底是什么意思,它是坏的吗?
问题描述
究竟是做什么的
指示托管堆垃圾回收的开始
意思是,这很糟糕吗?
在运行 Visual Studio 调试器时,我正在查看进程内存,当我的一项操作发生时,进程内存图中有许多黄色符号,表示许多“指示托管堆垃圾收集的开始”发生了操作。代码在合理的时间内处理,所以这是一件坏事吗?
解决方案
“指示托管堆垃圾收集的开始”是什么意思?
CLR 有一个垃圾收集器。它跟踪正在使用的内存量,当它的启发式方法表明现在可能是尝试回收未使用内存的好时机时,它会收集垃圾内存并释放它。这样做会压缩堆。
不好吗?
根据您使用的 CLR 版本及其配置方式,有多种不同的垃圾回收策略。其中一些是“阻止世界”的收藏家;也就是说,当收集发生时,您的程序会暂停几毫秒。 如果您的程序需要实时或近乎实时地处理时间预算少于几毫秒的事件,那么在错误的时间收集可能会非常糟糕。
例如,假设您正在编写代码来分析以每秒数千米的速度移动的来袭导弹的飞行路径,并触发一些对策。如果由于在错误的时间进行垃圾收集而导致错误几毫秒,那么您的分析可能会偏离几米,并且您可能会错过目标。 不要用 C# 编写软件来运行导弹拦截系统。人可能会死。这真的很糟糕。
例如,假设您正在编写一个每秒刷新 60 次屏幕的游戏。这使您每次刷新不到 17 毫秒即可完成所有必要的游戏计算。如果这样做需要 14 毫秒,那么垃圾收集可能会导致您错过一帧。游戏玩家可能会被激怒。这真的很糟糕。
例如,假设您正在编写更新数据库的业务线软件,并且需要十秒钟来更新数据库。垃圾收集可能会中断它,然后可能需要十秒加三毫秒。这还不错。没关系。
从用户体验性能的角度分析您的应用程序,设置性能预算,并验证垃圾收集是否使您保持在预算范围内。如果您在垃圾收集方面没有预算,那么您需要使用特殊技术来控制执行收集的方式和时间,以确保它们在预算范围内发生。
特别是,如果您超出了收款的性能预算,那么您必须管理收款压力。“压力”是 GC 用来决定何时收集的启发式;它是最近分配了多少内存、分配的大小、内存存活了多少集合以及许多其他因素的组合。
当我们设计 Roslyn(当前这一代 C# 编译器技术)时,我们必须非常小心地管理收集压力,因为编译器会在编辑器中的击键之间进行许多小分配。在某些情况下,由于不需要的集合,我们没有足够快地进行分析以在键入期间产生 IntelliSense 行为。我们使用了多种技术来减少压力,以及收集器在收集期间移动内存所必须做的工作量。
这些都是先进的技术。如果您在预算范围内,请不要担心它们。但是,在您制定预算并衡量您是否在预算内之前,您不会知道自己是否在预算内!
推荐阅读
- java - gu 没有这样的文件或目录
- git - 如何在本地删除文件而不将这些删除提交到远程存储库,同时保持“干净”的工作树?
- sql - Hive:使用正则表达式作为单独的列拆分字符串
- php - 使用 Codeigniter zip 库压缩时出现阿拉伯语文件名问题
- swift - 通过 UIAlertAction 更改 UILabel 文本
- sql-server - SSAS 处理多维数据集无法复制属性键但运行原始 sql 显示没有重复
- python - 通过将动态参数列表传递给函数来创建 Pandas Dataframe 需要帮助
- asp.net-core - 从 ASP.net Core 2.2 迁移到 3.0(启用 CORS)后,Set-Cookie 不起作用
- sql-server - 创建具有多个外键引用单个字段的视图
- python-3.x - 如何在 Python OpenCV 中使用 cv2.waitKey(1)