简体   繁体   English

显示Flex对象引用

[英]Displaying Flex Object References

I have a bit of a memory leak issue in my Flex application, and the short version of my question is: is there any way (in AcitonScript 3) to find all live references to a given object? 我的Flex应用程序中存在一些内存泄漏问题,我的问题的简短版本是:有没有办法(在AcitonScript 3中)查找给定对象的所有实时引用?

What I have is a number of views with presentation models behind each of them (using Swiz). 我所拥有的是一些视图,每个视图背后都有演示模型(使用Swiz)。 The views of interest are children of a TabNavigator, so when I close the tab, the view is removed from the stage. 感兴趣的视图是TabNavigator的子视图,因此当我关闭选项卡时,视图将从舞台中删除。 When the view is removed from the stage, Swiz sets the model reference in the view to null, as it should. 从阶段中删除视图时,Swiz会将视图中的模型引用设置为null,就像它应该的那样。 I also removeAllChildren() from the view. 我也从视图中删除了AllChildren()。

However when profiling the application, when I do this and run a GC, neither the view nor the presentation model are freed (though both set their references to each other to null). 但是,在分析应用程序时,当我执行此操作并运行GC时,视图和表示模型都不会被释放(尽管两者都将它们的引用设置为null)。 One model object used by the view (not a presenter, though) IS freed, so it's not completely broken. 视图使用的一个模型对象(虽然不是演示者)已被释放,因此它并未完全被破坏。

I've only just started profiling today (firmly believing in not optimising too early), so I imagine there's some kind of reference floating around somewhere, but I can't see where, and what would be super helpful would be the ability to debug and see a list of objects that reference the target object. 我今天刚刚开始进行剖析(坚信不会过早地进行优化),所以我想有某种参考浮动在某处,但我看不到哪里,以及什么是超级有用的将是调试的能力并查看引用目标对象的对象列表。 Is this at all possible, and if not natively, is there some light-weight way to code this into future apps for debugging purposes? 这一切都是可能的,如果不是原生的话,是否有一些轻量级的方法将其编码到未来的应用程序中以进行调试?

Cheers. 干杯。

Assuming you are using Flex Builder, you could try the Profiler. 假设您使用的是Flex Builder,则可以尝试使用Profiler。 In my experience, it's not so good for profiling performance, but it's been of great help for finding memory leaks. 根据我的经验,它对于分析性能并不是那么好,但它对于发现内存泄漏有很大帮助。

It's not the most intuitive tool and it takes a while to get used to it (I mean, to the point where it actually becomes helpful). 它不是最直观的工具,需要一段时间才能适应它(我的意思是,它实际上变得有用)。 But, in my opinion, investing some time to at least learn the basics pays off. 但是,在我看来,投入一些时间来至少学习基础知识是值得的。 There's an enormous difference between just seeing how much memory the player is using globally (what System.totalMemory gives you, a very rough, imprecise and often misleading indicator) and actually track how many instances of each object have been created, how many are still alive and where were they allocated (so you can find the potential leak in the code and actually fix it instead of relying in black magic). 只看到玩家在全球范围内使用了多少内存(System.totalMemory给你的内容,一个非常粗略,不精确且经常误导的指标)并且实际跟踪每个对象创建了多少个实例,仍有多少仍然存在巨大差异活着,他们分配在哪里(所以你可以找到代码中的潜在泄漏并实际修复它而不是依赖于黑魔法)。

I don't know of any good tutorials for the FB profiler, but maybe this'll help to get you started. 我不知道有什么关于FB探测器的好教程,但也许这对你有所帮助。

First, launch the profiler. 首先,启动探查器。 Uncheck performance profiling and check everything else (Enable memory profiling, watch live memory data and generate object allocation stack traces). 取消选中性能分析并检查其他所有内容(启用内存分析,监视实时内存数据并生成对象分配堆栈跟踪)。

When the profiler starts, you'll see stats about the app objects, grouped by class. 当探查器启动时,您将看到按类分组的应用程序对象的统计信息。 At this point, you might want to tweak filters. 此时,您可能想要调整过滤器。 You'll see a lot of data and it's very easy to be overwhelmed. 你会看到很多数据,很容易被淹没。 For now, ignore everything native to flash and flex stuff, if possible, and concentrate on some object that you think it should be collected. 现在,如果可能的话,忽略flash和flex中的所有东西,并专注于你认为应该收集的一些对象。

The most important figures are "cumulative instances" and "instances". 最重要的数字是“累积实例”和“实例”。 The first is the total number of instances created so far; 第一个是到目前为止创建的实例总数; the second, the number of said instances that are still alive. 第二,所述实例的数量仍然存在。 So, a good starting point is get your app to the state where the view you suspect that leaks gets created. 因此,一个好的起点是让您的应用程序进入您怀疑泄漏被创建的视图所在的状态。 You should see 1 for "cumulative instances" and "instances". 您应该看到“累积实例”和“实例”1。

Now, do whatever you need to do to get to the point where this view should be cleaned up (navigate to other part of the app, etc) and run a GC (there's a button for that in the profiler UI). 现在,做任何你需要做的事情来达到应该清理这个视图的点(导航到应用程序的其他部分等)并运行GC(在探查器UI中有一个按钮)。 A crucial point is that you will be checking the app behaviour against your expectations -if that makes sense-. 关键的一点是,您将根据您的期望检查应用行为 - 如果这是有道理的。 Finding leaks automatically in a garbarge collected environment is close to impossible by definition; 根据定义,在收集环境中自动发现泄漏几乎是不可能的; otherwise, there would be no leaks. 否则,就不会有泄漏。 So, keep that in mind: you test against your expectations; 所以,记住这一点:你测试你的期望; you are the one who knows the life cycle of your objects and can say, "at this point this object should have been collected; if it's not, there's something wrong". 你是那个知道物体生命周期的人,可以说,“此时应该收集这个物体;如果不是,就会出现问题”。

Now, if the "instances" count for you view goes down to 0, there's no leak there. 现在,如果你的视图的“实例”计数下降到0,那里就没有泄漏。 If you think the app leaks, try to find other objects that might not have been disposed properly. 如果您认为应用程序泄漏,请尝试查找可能未正确处理的其他对象。 If the count remains at 1, it means your view is leaked. 如果计数保持为1,则表示您的视图已泄露。 Now, you'll have to find why and where. 现在,你必须找到原因和地点。

At this point, you should take a "memory snapshot" (the button next to the Force GC button). 此时,您应该拍摄“内存快照”(Force GC按钮旁边的按钮)。 Open the snapshot, find the object in the grid and double click on it. 打开快照,在网格中找到对象并双击它。 This will give you a list of all the objects that have a reference to this object. 这将为您提供所有引用此对象的对象的列表。 It's actually a tree, and probably each item will contain in turn a number of backreferences and so on. 它实际上是一棵树,可能每个项目都会包含许多反向引用等等。 These are the objects that are preventing your view from being collected. 这些是阻止收集视图的对象。 In the right panel, also, you will an allocation trace. 在右侧面板中,您还将获得分配跟踪。 This will show how the selected object was created (pretty much like a stack trace). 这将显示如何创建所选对象(非常类似于堆栈跟踪)。

You'll probably see a hugh number of objects there. 你可能会看到那里有很多物体。 But your best bet is to concentrate in those that have a longer life cycle than the object you're examining (your view). 但最好的办法是专注于那些生命周期比你正在检查的对象(你的观点)更长的人。 What I mean is, look for stage, a parent view, etc; 我的意思是,寻找舞台,父母观点等; objects on which your view depends on rather than objets that depend on your view, if that makes sense. 视图所依赖的对象,而不是依赖于视图的对象,如果这有意义的话。 If your view has a button and you added a listener to it, your button will have a ref to your view. 如果您的视图有一个按钮并且您添加了一个监听器,那么您的按钮将具有您的视图的参考。 In most cases, this is not a problem, since the button depends on the view and once the view is collect, so is the button. 在大多数情况下,这不是问题,因为按钮取决于视图,一旦收集视图,按钮也是如此。 So, the idea is that since there are a lot of objects, you should try to stay focused or you will get nowhere. 因此,我们的想法是,由于有很多物体,你应该保持专注,否则你将无处可去。 This method is rather heuristic, but in my experience, it works. 这种方法颇具启发性,但根据我的经验,它可行。

Once you find the source of a leak, go back to the source, change the code accordingly (maybe this requires not just changing code but refactoring a bit). 一旦找到泄漏源,请返回源代码,相应地更改代码(这可能不仅需要更改代码,还需要重构一下)。 Then repeat the process and check whether your change has caused the desired effect. 然后重复此过程并检查您的更改是否已产生预期效果。 It might take a while, depending on how big or complex is your app and how much you know about it. 这可能需要一段时间,具体取决于您的应用程序的大小或复杂程度以及您对它的了解程度。 But if you go step by step, finding and fixing one problem at the time, you'll eventually get rid of the leaks. 但如果你一步一步地找到并解决一个问题,你最终会摆脱泄漏。 Or at least the worst and more evident ones. 或者至少是最糟糕的,更明显的。 So, while a bit tedious, it pays off (and as a nice aside, you'll eventually understand what a waste of time is in most cases to use weak refs for every single event handler on the face of this earth, nulling out every single variable, etc, etc; it's an enlightening experience ;). 所以,虽然有点单调乏味,但它会得到回报(而且作为一个好的方面,你最终会明白在大多数情况下浪费时间来为地球上的每一个事件处理程序使用弱refs,将每个事件都归零单变量等等;这是一种启发性的体验;)。

Hope this helps. 希望这可以帮助。

Flash GC uses a mix of ref counting and mark and sweep, so it does detect circular references. Flash GC使用引用计数和标记和扫描的混合,因此它确实检测循环引用。 It seems rather you're having another reference in you object graph. 看来你在对象图中有另一个引用。 The most common reason is, that the objects you want disposed still are having event handlers registered on objects that are not disposed. 最常见的原因是,您想要处理的对象仍然具有在未处置的对象上注册的事件处理程序。 You could try to ensure that handlers are always registered with weak reference. 您可以尝试确保处理程序始终使用弱引用进行注册。 You could also override addEventListener and removeEventListener in all (base) classes, if possible, to look which listeners are registered and whether there are chances for some not to be removed. 如果可能,您还可以覆盖所有(基类)类中的addEventListener和removeEventListener,以查看哪些侦听器已注册,以及是否有可能无法删除某些侦听器。

Also, you can write destructors for your objects, that for ui components clear graphics and remove all children, and for all objects, removes references to all properties. 此外,您可以为对象编写析构函数,为ui组件清除图形并删除所有子对象,对于所有对象,删除对所有属性的引用。 That way, only your object is kept in RAM, which shouldn't require much memory (a small footprint of 20 B or so, plus 4 B per variable (8 for a Number)). 这样,只有你的对象被保存在RAM中,这不需要太多内存(20 B左右的小占用空间,每个变量加4 B(数字为8))。

greetz 格尔茨
back2dos back2dos

也是寻找内存泄漏的有用启发式方法: http//www.tikalk.com/flex/solving-memory-leaks-using-flash-builder-4-profiler

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM