Thursday, December 10, 2009

Flex Memory Management & Object Caching

The responsiveness and performance of a Flex application directly relates to what is being displayed on screen. The more that is happening, the slower the application will respond. In most cases, you won't run into this scenario. If you are dynamically adding LOTS of UIComponents, then this tip will help you create applications that perform very well under heavy load.

One of the most computationally expensive operations in the Flex component life cycle is the constructor and initialization routine. If you are adding and removing lots of complex components, this can become very taxing on the system, and reduce overall application performance. One way to reduce the impact that this has on your system is through object caching, (also known as object pooling).

Flex Bugs related to Memory Leak:

I have provided some of the flex bugs related to the memory leak here (especially in chart components, data binding, itemrenderers etc).

http://bugs.adobe.com/jira/browse/SDK-15710?actionOrder=desc

http://bugs.adobe.com/jira/browse/FLEXDMV-2027

http://bugs.adobe.com/jira/browse/FP-129

Creating WeakReference

Richard Lord over at Big Room Games has an interesting article on hacking AS3 to allow you to create weak-references to objects.

Using the WeakReference hack could be useful if you want to make sure that an object will not stay in 
memory if you forget to delete all references to it. However, keeping track of your objects and practicing 
good memory management is a much better solution and hacks like this one should be saved for special 
cases where tracking use of an object becomes difficult or impractical.

Reduce, Reuse and Recycle:
when using object caching, you create a cache of objects that the application can use. When the application is finished with these objects, you return the objects to the cache so that they can be reused again. This technique reduces the number of object instances created by the runtime, reduces the overall memory used when running the application, stabilizes the required resources to run the application (less spikes in both cpu and memory), and leads to better overall performance and scalability of the application when applied correctly.

I have created the custom class factory (implements IFactory interface) to implement object caching to generate itemrenderers.

public class CustomRendererFactory implements IFactory

{

Private var objectCache:Array = new Array();

Private var _generator:Class = null;

Public function CustomRendererFactory (generator:Class)

{

This._generator = generator;

}

//Get the object from the ObjectCache if available else create a ne instance.

Public function newInstance():*

{

Var instance:Object = null;

If(ObjectCache.length > 0)

{

Instance = ObjectCache.shift();

}

Else

{

Instance = new _generator();

}

Return instance;

}

//place the object passed as parameter to the objectCache.

Public function setObject(object:*)

{

objectCache.push(object);

}

}

This custom class factory can be used for itemRenderer property of the flex components. After using the renderers make sure that those objects are released by invoking the method setObject of this customRenderer class.

//Create a CustomRendererFactory object passing the class name of the object that we need.

Var renderer: CustomRendererFactory = new CustomRendererFactory(Canvas);

canvasObj:Canvas = Renderer.newInstance() as Canvas;

//

//release the object to cache when it is not in use anymore.

Renderer.setObject(canvasObj);

Renderer = null;

Conclusion:

Object caching and the weak reference can be combined to combat the memory leak issues present in the flex application.

Friday, December 4, 2009

HTML Meta Tags to the rescue

EXPIRES:


Example:

< META HTTP-EQUIV="EXPIRES" CONTENT="Mon, 22 Jul 2002 11:12:01 GMT" >

response.setDateHeader("Expires", 0);


The following example sets expiration for 15 seconds

long now = System.currentTimeMillis();

response.setDateHeader("Expires", now + 15000);


Description:

The date and time after which the document should be considered expired. An illegal EXPIRES date, e.g. "0", is interpreted as "now". Setting EXPIRES to 0 may thus be used to force a modification check at each visit.
Web robots may delete expired documents from a search engine, or schedule a revisit.



PRAGMA:


Example:

< META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE" >

response.setHeader("Pragma", "No-cache");


Description:

This directive indicates cached information should not be used and instead requests should be forwarded to the origin server. This directive has the same semantics as the CACHE-CONTROL:NO-CACHE directive and is provided for backwards compatibility with HTTP/1.0.
Clients SHOULD include both PRAGMA:NO-CACHE and CACHE-CONTROL:NO-CACHE when a no-cache request is sent to a server not known to be HTTP/1.1 compliant.



CACHE-CONTROL:


Example:

< META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE" >

response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");


Description:

The directive CACHE-CONTROL:NO-CACHE indicates cached information should not be used and instead requests should be forwarded to the origin server. This directive has the same semantics as the PRAGMA:NO-CACHE.
Clients SHOULD include both PRAGMA:NO-CACHE and CACHE-CONTROL:NO-CACHE when a no-cache request is sent to a server not known to be HTTP/1.1 compliant.



REFRESH:


Example:

< META HTTP-EQUIV="REFRESH"
CONTENT="15;URL=http://www.I18nGuy.com/index.html" >

It keeps on refreshing the page at frequent intervals


Description:

Specifies a delay in seconds before the browser automatically reloads the document. Optionally, specifies an alternative URL to load, making this command useful for redirecting browsers to other pages.




Further reference: Click here

Adobe Flex - Memory Leak


Flash Player Garbage Collection

Garbage collection is a process that reclaims memory no longer in use so that it can either be reused by the application or, in some cases, given back to the operating system. Garbage collection happens automatically at allocation, which is often confusing to new developers. This means that garbage collection does not occur when memory is no longer in use, but rather occurs when your application asks for more memory. At that point, the process responsible for garbage collection, called the Garbage Collector, attempts to reclaim available memory for reallocation.

The Garbage Collector follows a two-part procedure to determine which portions of memory are no longer in use. Understanding this procedure will give you the insight necessary to develop applications that use memory appropriately and to understand the information presented by the Flex profiler.

The first part of the garbage collection procedure is referred to as reference counting, and the second is referred to as mark and sweep. Both rely upon different methods of ensuring that the memory in question is no longer referenced by other objects in use.


Understanding leaks caused by event listeners

Objects that wish to be notified when an event occurs register themselves as listeners. They do this by calling the addEventListener() method on the object that broadcasts the event (called the broadcaster or dispatcher).

The following example shows a simple case:

var textInput:TextInput 
= new TextInput(); 
textInput.addEventListener
(‘change’, handleTextChanged);
In this case, the TextInput is expected to broadcast an event named change at some point in the future, and you want the handleTextChanged method to be called when this occurs. When you call addEventListener() on the TextInput instance, it responds by adding a reference to the object (the one that contains the handleTextChanged method) to a list of objects that need to be notified when this event occurs. When it is time to broadcast the change event, the TextInput instance loops through this list and notifies each object that registered as a listener.

The important thing is that each object that broadcasts an event maintains a reference to every object listening for the event to be broadcast. In terms of garbage collection this means that, in certain circumstances, if an object is listening for events, it may never be available for garbage collection.

Note: For more information on event dispatching, please refer to the IEventDispatcher interface in the Flex 3 livedocs.

Your main weapon to combat this problem is diligence. Much like any child that is added with addChild() can be removed with removeChild(), addEventListener() has a parallel function named removeEventListener() that stops listening for an event. When removeEventListener() is called, it also removes the reference to the listener kept by the broadcaster, potentially freeing up the listener for garbage collection.
In an ideal world, the number of addEventListener() and removeEventListener() calls in your application should be equal. However, there are times when you have less control over when objects are no longer needed and using removeEventListener() is simply not feasible. In these situations, we can use a concept called weak references.

Using weak references with listeners
When adding an event listener to a broadcaster, the developer can specify that the event listener should use weak references. This is accomplished by specifying extra parameters to the addEventListener() method.
var textInput:TextInput 
= new TextInput(); 
textInput.addEventListener
(‘change’, handleTextChanged
, false, 0, true);
Previously, we used the first two parameters of the addEventListener() method: the name of the event and the method to call when the event occurs. However, there are three other parameters that can be specified. In order, these parameters specify whether the event listener should use capture, its priority relative to other listeners for this event, and finally whether weak references should be used. The first two are beyond the scope of this topic, but the last one is critical to garbage collection.
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
Specifying a value of true (the default is false) for the fifth parameter of the addEventListener() method specifies that the reference established by this listener is to be considered weak. All the other references are considered strong references

As a more concrete example, if an object had a strong reference and three weak references to it, it could not be collected as garbage. However, if the strong reference was removed, the weak references would be ignored and the object could be collected.

In practice, this means that specifying the weak reference flag on addEventListener() calls is almost always a good practice. It prevents the case where listening to an event is the only reason that an object is not collected.

The other place that weak references are supported is in the Dictionary object. Simply pass true as the first parameter when you instantiate a new Dictionary to have it use weak references as its keys:

var dict:Dictionary = new Dictionary(true); dict[myObj] = myOtherObj;
 // the reference to myObj is weak, the reference to myOtherObj is strong
Richard Lord over at Big Room Games has an interesting article on hacking AS3 to allow you to create weak-references to objects. 
Using the WeakReference hack could be useful if you want to make sure that an object will not stay in memory if you forget to delete all references to it. However, keeping track of your objects and practicing good memory management is a much better solution and hacks like this one should be saved for special cases where tracking use of an object becomes difficult or impractical.
Further Reference: click here

Wednesday, January 7, 2009

RSS Reader - in Java

What is RSS?

The initials "RSS" are used to refer to the following formats:

  • Rich Site Summary (RSS 0.91)
  • RDF Site Summary (RSS 0.9 and 1.0)
  • Really Simple Syndication (RSS 2.0)

RSS is a format for delivering regularly changing web content. Many news-related sites, weblogs and other online publishers syndicate their content as an RSS Feed to whoever wants it.

Reference: http://en.wikipedia.org/wiki/RSS

The Rome API

You could define RSS very simply by saying that it is an XML format that allows you to share information in a condensed manner; for example by publishing only a title, a description, and a link to a more detailed article.

Now, strictly speaking RSS is not a single format, but a family of formats. Among the many flavors of RSS are RSS 0.91 (in Netscape and Userland "sub-flavors"), RSS 0.92, RSS 0.93, RSS 0.94, RSS 1.0, and RSS 2.0. More recently Atom 1.0 has also entered the mix, introducing many subtle and non-so-subtle compatibility issues.

Although you can very well write your own RSS script directly (after all, it's just XML!), doing so forces you to choose, and stick to, one particular format. The issue is even trickier if you have to read and process external RSS feeds, which can come in a variety of formats. This is where an API like Rome comes in handy. In addition to being fluent in the many flavors of RSS, as you will see, the Rome API is easy to use and intuitive to understand, which helps to make coding more productive and code more maintainable.

Rome is an open source Java API for reading and publishing RSS feeds in a relatively format-neutral way. Originally developed by Sun and now a Java.net project, Rome is designed to provide a level of abstraction to mask the subtle differences between the various formats. This lets you concentrate on publishing and/or processing content, rather than wrestling with the particularities of each format. Rome was designed from the onset to be easy to use, flexible, and to support all existing RSS flavors.


Download ROME API here

ROME API documentation

Reference: http://www.javaworld.com/javaworld/jw-11-2007/jw-11-rome.html


Source Code:



URL feedUrl = new URL("http://www.indianetzone.com/rss/sports.xml");
URLConnection uc = feedUrl.openConnection();



SyndFeedInput input = new SyndFeedInput();


Reader rdr = new XmlReader(uc);


SyndFeed feed = input.build(rdr);


//Iterate through object to get details
List list = feed.getEntries();

System.out.println("Feed image="+feed.getImage());
if (feed.getImage()!=null)
{
SyndImageImpl image = (SyndImageImpl)feed.getImage();
String imageInfo = "Image url:"+image.getUrl()+"\n";
}
pw.println("");

for (int i=0 ; i < entry =" (SyndEntry)list.get(i);">author : "+entry.getAuthor()+"
");
//pw.println("\npublished : "+entry.getPublishedDate()+"
");
//pw.println("\nupdated : "+entry.getUpdatedDate()+"
");
pw.println("\ndescription : "+entry.getDescription().getValue()+"
");

}
pw.println("
");

}