- 浏览: 257729 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
zoukaiwolai:
...
Java 16进制字符串与2进制字符串相互转换 -
sooxin:
j2ee的事务对连接有自己的管理机制,包括建立和关闭。没进j2 ...
c3p0 spring 包没进事务管理,连接池就不能释放 -
sooxin:
mina 采用一种NIO通信,底层的连接机制没有具体研究过,但 ...
转 Mina框架在项目中的使用 -
tywo45:
写得很好,希望博主把格式调一下!
Tomcat性能参数设置介绍 -
freecode:
采用了cp30,项目中出现很多未关闭的连接,一直在找原因.
c3p0 spring 包没进事务管理,连接池就不能释放
I finally found some spare time to organize the stuff presented at flexcamp and make it a blog post. I “argue” with the Flex profiler almost daily and we had an “intense” relationship the month right before the flexcamp. So I felt a talk about profiling and Garbage Collection (GC) was really fit. Right, it is impossible to decouple profiling from GC. If you want to improve the memory management of your application you have to know how the Flash Player (and Adobe Air) manage memory allocation and deallocation.
Let me start by saying there are many blog posts about issues related to GC and profiling, ranging from documentation, presentations, how-tos, etc. I list them at the bottom.
The present post can be considered useful to beginners and medium experienced people which use Flex almost daily and have the need to optimize memory consumption. After introducing the fundamental concepts I will list a set of lessons learned during the development of Posty and Focused. I will particularly focus on the use of renderers’ caches.
Virtual Machine (VM)
The flash player is based on a virtual machine (to be precise the machines are 2, one for actionscript2 and one for actionscript3). VMs dynamically allocate memory when you create new objects. For example the following line of code creates a new Object.
1 |
var o:Object = new Object() |
At startup the VM reserves some memory and when the code above is executed decides where the object goes in the application memory and how much space it takes. As you create objects the VM might use all the memory allocated at startup and, when needed, requests some more to the operative system. Unless you have a program which nonsensically just creates new objects, there will be some time during the execution when an object becomes “useless”, e.g. it is not needed anymore for the correct execution of the program. You’ll see that it is not easy to “understand” when an object is not needed. For now let’s assume we are able to detect it.
In the Flash VM achitecture you cannot explicitly say “delete it”. Memory usage is managed, that is the VM itself is responsible to check which objects are useless and delete them. Such a mechanism is called Garbage Collection.
Garbage Collection
So what can I do as a programmer? Well, you can ease the task of the garbage collector. Let’s see what we expect to happen with the help of a figure.
At startup the application reserves some memory to be used, say four blocks. When you create a new object the VM allocates it using the first slot. Let’s say that after a while o1
is not needed anymore and you set it to null. When you create a new object, o2
, you expect that it takes the place of o1
. Sometimes it happens, sometimes it does not. This depends on the garbage collection mechanism, which is a pretty complex procedure we are not describing here (a good article has been written by Grant Skinner).
At this point we already have a lesson learned: “setting an object to null does not necessarily free the memory it was occupying“.
This depends on the way GC has been implemented in flash. GC is triggered by allocation” and not deletion. This means that the GC cycle is run when you say new Object() and not when you set it to null.
Memory Consumption
If you have to do with AS3 and Flex you probably know that you can dynamically add UI elements to the graphical interface via a simple method called addChild()
. The opposite method is removeChild()
, which removes a display element from the UI. To be more precise, the element is deleted from the view (it is not displayed anymore) but this does not mean it has been garbage collected. Let me introduce you to a simple scenario to show you easy is to put too much trust in the removeChild()
method.
Many Flex applications load data from a server and display it dynamically, according to the values returned. Usually the view code is isolated in a component, often referred to as renderer, which is responsible of showing the data loaded from the server. We devise a very simple renderer that is made of two text fields, embedded in a VBox. Data shown are field1
and field2
, properties of the object provided as input.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" borderStyle="solid" width="200" > <mx:Script> <![CDATA[ [Bindable] private var _field1:String; [Bindable] private var _field2:String; override public function set data(value:Object):void { _field1 = value.field1; _field2 = value.field2; } ]]> </mx:Script> <mx:Text text="{_field1}" /> <mx:Text text="{_field2}" /> </mx:VBox> |
Let’s simulate data loading by means of a simple function, which returns an array of objects.
1 2 3 4 5 6 7 8 9 10 11 |
private function getData():Array { var a:Array = new Array(); for (var i:uint = 0; i< 200; i++) { var o:Object = new Object(); o.field1 = "field "+Math.random().toString(); o.field2 = "field "+Math.random().toString(); a.push(o); } return a; } |
To render data we use a simple function which creates a renderer, sets its data, and adds it to the VBox.
1 2 3 4 5 6 7 8 9 10 11 |
private function loadData():void { vbox.removeAllChildren(); var array:Array = getData(); for (var i:int = 0; i < array.length; i++) { var rend:MyRenderer = new MyRenderer(); rend.data = array[i]; box.addChild(rend); i++; } } |
Do you see the dangerous statement? Not yet? Let me show you. To simulate a repeated action I add a timer which calls the load function each N seconds.
1 2 3 4 5 |
private function init():void { var t:Timer = new Timer(2000); t.addEventListener(TimerEvent.TIMER, tick); t.start(); } |
Now try running the profiler. Do you see an ever growing graph like this?
Congrats! We have found a memory leak! A memory leak happens when the same action is repeated and memory consumption grows instead of being constant. Did you find the dangerous statement? It is when you create the renderer. Why? Because you assume that removeAllChildren()
removes renderers from the memory. Wrong! As said above that method only removes renderers from the display tree. In fact, as you can see in the profiler, renderers are still there, consuming memory.
UPDATE: Technically speaking this is not a memory leak, because there is nothing that prevents the garbage collector to clean up memory from renderers. A memory leak happens, in fact, when there is something that is supposed to use the renderer (e.g. a listener) even when you remove it from the display tree. In this example renderers are ‘free” and could be garbage collected. But they are not. So the result is the same of a memory leak, an ever growing memory consumption.
There are many techniques to solve this situation. We will show two: caching renderers and dynamic caching.
Caching
Let’s assume you know in advance how many renderers are needed. One way to solve the memory leak is to create a cache of renderers at startup.
1 2 3 4 5 6 7 |
private var cache:Array = new Array(); private function initRenderers():void { for (var i:int = 0; i < 200; i++) { renderers.push(new MyRenderer()); } } |
We can then modify our loadData method like this:
1 2 3 4 5 6 7 8 9 10 11 |
private function loadData():void { container.removeAllChildren(); var array:Array = getData(); for (var i:int = 0; i < array.length; i++) { var rend:MyRenderer = cache[i]; rend.data = array[i]; container.addChild(rend); i++; } } |
As you can see in the code we don’t create new renderers but we look for one in the cache. There are cases when you don’t know in advance which data are returned from the server and then you don’t know how many rendereres you need. In this case you need a dynamic cache.
Dynamic cache
Dynamic caching is based on an elastic mechanism. You have a place where you can look for a renderer: if there is one in the cache, that is returned, otherwise a new one is created temporarily. Better to see some code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public class MyRendererCache extends Object { private static var cache : ArrayCollection = new ArrayCollection(); public function MyRendererCache() { super(); for ( var x : Number = 0; x < 20; x ++ ) { cache.addItem( new MyRenderer() ); } } public static function getRenderer() : MyRenderer { var renderer : MyRenderer; if ( cache.length <= 0 ) { renderer = new MyRenderer(); } else { renderer = cache.removeItemAt( 0 ) as MyRenderer; } return renderer; } public static function setRenderer( renderer : MyRenderer ) : void { cache.addItem( renderer ); } } |
In the constructor you populate the cache with the minimu number of renderers, say 20 (lines 7-9). The cache has two static methods, getRenderer
and setRenderer
. The first is used to obtain a renderer, the second to give it back when done. If you look and lines 15-16 the cache returns a new renderer when the cache is empty. This way the number of renderers in memory can grow beyond the minimum number set in the constructor, but just temporarily, since the GC will delete them when not referenced anymore.
An important issue is related to the setRenderer
. When you don’t need a renderer anymore you have to return it back to the cache, otherwise we fall again in a memory leak as explained above. To achieve this we exploit the remove event of the renderer. The remove event is triggerer whenever a UI element is removed from the display list. For example when we call removeAllChildren()
such event is triggered for each renderer.
We can modify the renderer like this:
1 2 3 4 5 6 7 8 9 10 |
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" borderStyle="solid" width="200" remove="onRemove()" > private function onRemove():void { MyRendererCache.setRenderer(this); } .... </VBox> |
If you now run the profiler you will notice that memory grows until a given point and then keeps stable as in the figure below.
Congratulations! You have solved the memory leak!
Suggesting the GC
Besides favoring the job of GC Adobe has allowed programmers to suggest the intervention of the GC. The command is in the flash.system
package and it is System.gc()
. By documentation this “Forces the garbage collection process” but in my experience it is just a vague suggestion of intervention. It can solve some situation, so it is worth trying it at the beginning, when you need a quick way to save some memory.
发表评论
-
小学语文课堂教学三维目标的制定和落实-广安齐祥娥
2019-07-06 11:31 15教学目标是教学过程中重要的一部分,它是教学的出发点 也是教学 ... -
air打包是去掉air前缀
2017-02-05 12:13 768air打包是去掉air前缀当用air导报生成apk是会自动在a ... -
Adobe AIR 3新特性
2012-04-24 11:15 1240自从2008年发布了第一 ... -
四川血战麻将pc版下载
2012-01-17 16:59 111见附件! -
四川血战麻将 v0.3 整装待发!
2012-01-09 21:40 80app 搜索关键字:四川血战麻将app store 地址:ht ... -
四川血战麻将 app store 正式上线!
2012-01-05 17:15 76四川麻将, 又称血战麻将, 采用四川地区流行的麻将打法, 尤其 ... -
Flex 数据绑定易犯的错误:普遍的误用和错误
2011-07-12 21:21 1045http://www.cnblogs.com/kakaflex ... -
Flex框架选择的一点个人之见
2011-05-05 20:56 906时下,国人都热衷于开 ... -
flex缓存客户端
2011-05-05 20:53 774flex或者flash客户端的缓 ... -
flashbuiler4 格式化地址
2011-01-07 13:03 806http://flexformatter.googlecode ... -
分离MXML和AS
2010-04-26 09:40 1136package oreilly.cookbook { ... -
ACE框架在网络游戏服务器中的设计与应用
2010-04-19 21:26 2222陶 道,万旺根 (上海大 ... -
网络游戏同步
2010-04-19 21:24 1050同步在网络游戏中是非 ... -
关于完美的Flex应用框架的思考(Part 1 of 2)
2010-04-14 23:56 1115自Flex技术开始广泛应用以来,对于企业级Flex应用开发框架 ... -
Flash的socket在实际应用上需要注意的问题
2010-04-14 23:34 2210本文作者:奶瓶先生 转 ... -
转 RTMP协议理解
2010-04-14 16:18 6569一、基于TCP之上的高层协议;二、自定义新的包结构chunk; ... -
flex的Timer事件几点注意
2010-03-17 22:57 2109flex的Timer事件几点注意 1. 设定Timer的延 ... -
关于强引用和弱引用
2010-03-17 22:54 1613强引用:使用最普遍的引用。如果一个对象具有强引用,那就类似于必 ... -
关于MC的复制
2010-02-27 10:58 1745关于MC的复制一直都是 ... -
谜一样的TextField
2010-02-02 16:32 1198文章来之:http://hi.baidu.com/mr%5Fz ...
相关推荐
《垃圾收集手册》是关于自动内存管理的一本权威著作,主要探讨了计算机程序中的垃圾收集(Garbage Collection, GC)技术。垃圾收集是现代编程语言中一个至关重要的部分,它负责自动识别并释放不再使用的内存空间,...
The Garbage Collection Cookbook 垃圾回收算法手册
The Garbage Collection Handbook The Art of Automatic Memory Management 英文epub
"03 GarbageCollection.zip"这个压缩包文件,其标题暗示了我们将探讨的是垃圾收集(Garbage Collection, GC)这一核心概念,特别是在数据结构和算法的学习中,理解GC的工作原理对于优化程序性能至关重要。...
书名《The Garbage Collection Handbook The Art of Automatic Memory Management》揭示了本书的重点是垃圾回收(Garbage Collection)和自动内存管理(Automatic Memory Management)。垃圾回收是计算机科学中的一...
WP-Understanding Java Garbage Collection
4. **垃圾收集器类型**:Java虚拟机(JVM)提供了多种垃圾收集器,如Serial、Parallel、Parallel Old、CMS(Concurrent Mark Sweep)、G1(Garbage-First)和ZGC(Zing Garbage Collector)。每种收集器有其特定的...
垃圾回收算法的经典之作。 本书围绕着动态内存自动回收的话题,介绍了垃圾收集机制,详细分析了各种算法和相关技术。 本书共12章。第1章首先介绍计算机存储器管理的演化和自动内存回收的需求,并引入了本书所使用...
This paper presents a new garbage collection scheme for flash memory based storage systems that focuses on reducing garbage collection overhead, and improving the endurance of flash memory. The scheme...
垃圾收集(Garbage Collection, GC)是这一过程的核心,它负责识别并回收不再使用的内存空间。本篇文章将深入探讨几种常见的垃圾收集算法,以及它们在Java J2EE、C#、ASP.NET以及JVM中的应用。 1. **标记-清除...
在系统级编程中,垃圾收集(Garbage Collection, GC)是一项至关重要的任务,它自动管理程序的内存,释放不再使用的对象以防止内存泄漏。本文将深入探讨“slp-garbage collection”这一主题,它是系统级编程课程中的...
垃圾回收(Garbage Collection, GC)是自动动态内存管理的关键技术,它负责识别并回收不再使用的内存块,防止内存泄漏。GC的工作原理包括对象的可达性分析、标记-清除、复制、标记-压缩、分代收集等多种算法。这些...
12.6.5 “Garbage collecting the world” 12.6.6 网络对象 12.6.7 带权引用计数 12.6.8 世代引用计数 12.7 对actor进行垃圾收集 12.7.1 Halstead算法 12.7.2 标记算法 12.7.3 逻辑上集中式的收集器 12.8 引文注记
### Java垃圾回收经典手册知识点概览 #### 一、引言 《Plumbr Java垃圾回收手册》(2015年英文版)是一本详细介绍了Java虚拟机(JVM)中垃圾回收机制的经典指南。该手册由Nikita Salnikov-Tarnovski和Gleb Smirnov...
It automatically senses the garbage and informs local authority about the garbage overloading. It is IOT based project with utilizes arduino as its processing unit
在IT行业中,垃圾回收(Garbage Collection,简称GC)是一项重要的技术,特别是在使用像Java、Python、Ruby等高级编程语言时。垃圾回收是自动管理内存的一种机制,它负责监测和释放不再使用的内存空间,以防止内存...
书围绕着动态内存自动回收的话题,介绍了垃圾收集机制,详细分析了各种算法和相关技术。 本书共12章。第1章首先介绍计算机存储器管理的演化和自动内存回收的需求,并引入了本书所使用的术语和记法。...