- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我们目前正在使用 ReactiveUI 来帮助构建一个相当大的基于 WPF 的 Windows 应用程序。一切都很顺利,直到我们发现我们的应用程序正在消耗大量内存……基本上我们所有的 View 、 View 模型和模型都没有被垃圾收集。
根据 Jet Brains dotMemory 等内存分析器的信息,ReactiveUI 似乎是罪魁祸首。特别是我们在 View 中配置的 ReactiveUI 绑定(bind),即使我们正在使用最佳实践并确保在停用 View 时处理所有绑定(bind)。
以下是我们正在创建的 View 之一的示例。任何关于我们可能哪里出错的想法都将不胜感激。
public partial class RunbookInputsView : IViewFor<RunbookInputsViewModel>
{
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
"ViewModel", typeof(RunbookInputsViewModel), typeof(RunbookInputsView));
public RunbookInputsView()
{
InitializeComponent();
this.WhenActivated(d =>
{
d(this.OneWayBind(ViewModel, vm => vm.AddInput, v => v.AddInput.Command));
d(this.OneWayBind(ViewModel, vm => vm.Inputs, v => v.Inputs.ItemsSource));
});
}
object IViewFor.ViewModel
{
get { return ViewModel; }
set { ViewModel = (RunbookInputsViewModel)value; }
}
public RunbookInputsViewModel ViewModel
{
get { return (RunbookInputsViewModel) GetValue(ViewModelProperty); }
set { SetValue(ViewModelProperty, value); }
}
}
最佳答案
从问题中很难判断泄漏是从哪里来的。让泄漏发生一段时间,然后使用 windbg
(Debugging Tools For Windows 的一部分)附加到进程(注意:您可能需要构建 x86
或 x64
才能正常工作。)
附加后,通过输入以下命令设置 .net 调试:
.symfix
sxe clr
sxd av
.loadby sos clr
然后您可以使用 !dumpheap -stat
获取每种类型的内存使用情况。这会产生以下格式的输出:(为了便于阅读,我截断了类名和列表。)
0:012> !dumpheap -stat
Statistics:
MT Count TotalSize Class Name
000007fefa55d2e8 1 24 System.[...]TransportSinkProvider
000007fefa55ce08 1 24 System.Run[...]rtSinkProvider
000007fee7c32df0 1 24 System.LocalDataStoreHolder
000007fee7c2ff78 1 24 System.Colle[...]
000007fee7c2ece0 1 24 System.Resources.FastResourceComparer
000007fee7c2ead0 1 24 System.Resources.ManifestBasedResourceGroveler
000007fee7c2ea70 1 24 System.[...]eManagerMediator
000007fee4cc1b70 4 1216 System.Xml.XmlDocument
如果您有内存泄漏,您将在这里看到泄漏的对象。 (应该有很多。)一旦您确定了泄漏的内容,您就可以执行 !dumpheap -type
来获取实际对象的列表。 (对于此示例,我将使用 System.Xml.XmlDocument
。类型名称区分大小写,并且必须完全限定。)
0:012> !dumpheap -type System.Xml.XmlDocument
Address MT Size
0000000002af9050 000007fee4cc1b70 304
0000000002afa628 000007fee4cc1b70 304
0000000002b0ea30 000007fee4cc1b70 304
00000000037e2780 000007fee4cc1b70 304
Statistics:
MT Count TotalSize Class Name
000007fee4cc1b70 4 1216 System.Xml.XmlDocument
您的列表可能会大得多,但概率表明泄漏类型的任何随机实例都会是您感兴趣的东西。如果我们对其中一个地址执行 !do
,我们将得到如下所示的输出:
0:012> !do 2af9050
Name: System.Xml.XmlDocument
MethodTable: 000007fee4cc1b70
EEClass: 000007fee4ae7f00
Size: 304(0x130) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll
Fields:
MT Field Offset Type VT Attr Value Name
000007fee4cc2b40 40004fc 8 System.Xml.XmlNode 0 instance 0000000000000000 parentNode
000007fee4cc2258 400050a 10 ...XmlImplementation 0 instance 0000000002af9180 implementation
000007fee4cc22f0 400050b 18 ....Xml.DomNameTable 0 instance 0000000002af92e0 domNameTable
[Entries removed for clarity]
000007fee4cc26f0 400052f 108 ...m.Xml.XmlResolver 0 instance 0000000000000000 resolver
000007fee7c18c48 4000530 126 System.Boolean 1 instance 0 bSetResolver
000007fee7c113e8 4000531 110 System.Object 0 instance 0000000002af9788 objLock
000007fee4cc11b0 4000532 118 ....Xml.XmlAttribute 0 instance 0000000000000000 namespaceXml
您可以对表中列出的任何对象使用 !do
以获取更多信息。 System.String
和 System.Boolean
等类型将吐出它们的实际值。如果从创建它的对象中不清楚,下一步可能是使用 !gcroot -nostacks
来查找对我们对象的引用。
0:012> !gcroot -nostacks 2af9050
HandleTable:
00000000006117d8 (pinned handle)
-> 0000000012a55748 System.Object[]
-> 0000000002af9050 System.Xml.XmlDocument
Found 1 unique roots (run '!GCRoot -all' to see all roots).
还有很多命令,这已经太长了。 !help
命令提供了一个很好的 list 。 (要使用它们中的任何一个,您需要在命令前加上 !
前缀。!help [command]
提供有关特定命令的详细信息。例如 !help dumpobj
:
0:012> !help dumpobj
-------------------------------------------------------------------------------
!DumpObj [-nofields] <object address>
This command allows you to examine the fields of an object, as well as learn
important properties of the object such as the EEClass, the MethodTable, and
the size.
You might find an object pointer by running !DumpStackObjects and choosing
from the resultant list. Here is a simple object:
0:000> !DumpObj a79d40
Name: Customer
MethodTable: 009038ec
EEClass: 03ee1b84
Size: 20(0x14) bytes
(C:\pub\unittest.exe)
Fields:
MT Field Offset Type VT Attr Value Name
009038ec 4000008 4 Customer 0 instance 00a79ce4 name
009038ec 4000009 8 Bank 0 instance 00a79d2c bank
Note that fields of type Customer and Bank are themselves objects, and you can
run !DumpObj on them too. You could look at the field directly in memory using
the offset given. "dd a79d40+8 l1" would allow you to look at the bank field
directly. Be careful about using this to set memory breakpoints, since objects
can move around in the garbage collected heap.
What else can you do with an object? You might run !GCRoot, to determine what
roots are keeping it alive. Or you can find all objects of that type with
"!DumpHeap -type Customer".
The column VT contains the value 1 if the field is a valuetype structure, and
0 if the field contains a pointer to another object. For valuetypes, you can
take the MethodTable pointer in the MT column, and the Value and pass them to
the command !DumpVC.
The abbreviation !do can be used for brevity.
The arguments in detail:
-nofields: do not print fields of the object, useful for objects like
String
关于c# - ReactiveUI 绑定(bind)似乎可以防止发生垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32126163/
我有一个 foo 类,它有一个 bar 方法,它接受可调用的东西(函数指针/仿函数)。这个可调用的东西应该作为绑定(bind)元素传递给另一个方法 doit 和第三个方法 bar_cb 方法。 #in
我正在尝试在我的 WPF 4.0 应用程序(使用 VS 2010 Pro RTM)中创建自定义 TabItem 模板/样式,但尽管一切似乎都正常工作,但我注意到跟踪窗口中存在绑定(bind)错误。 我
作为一名刚接触 Android 的开发人员,我想我可能误解了绑定(bind)服务。 我创建了一项服务来结束对服务器的访问。作为此服务的一部分,该服务正在监听多播地址,以识别本地网络上的设备何时出现和消
这个问题在这里已经有了答案: What is the use of the JavaScript 'bind' method? (23 个回答) 关闭 7 年前。 所以我一直在尝试了解一些 JS 上
我不明白这三种语法之间的区别: where a = f (b) do a <- f (b) do let a = f (b) 我确实明白了a <- f(b)与其他两个不同,在大多数情况下,我尝试了所有
我在将 Cocoa 项目从手动同步接口(interface)模型转换为绑定(bind)模型时遇到问题,这样我就不必担心接口(interface)粘合代码。 我关注了 CocoaDevCentral C
我正在尝试找出一种好的方法来对处理大数据集的代码进行并行化,然后将结果数据导入 RavenDb。 数据处理受 CPU 限制和数据库导入 IO 限制。 我正在寻找一种解决方案,以对 Environmen
我正在 foreach 循环中生成单选按钮。我试图将选中的属性绑定(bind)到父级中的基本可观察值。不幸的是,当单击单选按钮时,父级的属性似乎没有在单击处理程序中更新。 基于一些previous w
在我的 Windows Phone 应用程序中,我有两个 LongListSelectors并排在页面上。我想做到这一点,以便当用户滚动其中一个时,另一个滚动相同的量。 两个 LongListSele
我在网上看到这个问题准备面试: Given a non-preemptive kernel which type of process will get affected morein terms o
我有一个 foreach 绑定(bind),如下所示: Summary Permitting 原因是有两个选项卡始终存在,并且我根据是否添加了其他选项卡来添加其他选项
任何人都有绑定(bind)相同的情况DataContext到 TextBlock 中的 Text 属性(例如)。 我必须分配 DataContext以我的风格反射(reflect)基于 Datacon
给定以下代码: Login 和下面的javascript $(function () { $('#btnLogin').click(function () { co
我使用 boost::asio 创建了一个服务器。我在绑定(bind)到端点时遇到问题。所以,如果我在构造函数中初始化一个接受器: Server::Server(QWidget *parent) :
我正在将现有项目从 MySQL 转换为 Postgres。代码中有相当多的原始 SQL 文字使用 ? 作为占位符,例如 SELECT id FROM users WHERE
似乎在绑定(bind)某些数据时出错了,有人可以帮我解决我哪里出错了,尽管我无法弄清楚。 真的不需要在这里显示太多,这是 Binding,我已经通过移除背景并在其中放置颜色来测试背景,效果很好。 编辑
我正在尝试使用 wcf 构建一个 http 监听器(web 服务)。这个监听器是一个更大的桌面应用程序的一部分。此桌面应用程序还会调用 http 监听器。 当监听器接收到数据时,它应该被传递到桌面应用
嘿嘿。 我正在使用 Node.JS 和 child_process 来生成 bash 进程。我试图了解我是否正在执行 I/O 绑定(bind)、CPU 绑定(bind)或两者兼而有之。 我正在使用 p
尝试执行以下操作并出现“Got interpolation ({{}}) where expression was expected”错误。 {{item.name}} 谢谢!
我有一个导入的 Java 库,它是我解决方案中的“绑定(bind)库”项目。 我正在尝试从解决方案中的另一个项目绑定(bind)到第 3 方库中的服务。 第 3 方库文档 [在 java 中] 非常简
我是一名优秀的程序员,十分优秀!