You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@flex.apache.org by mo...@comcast.net on 2013/04/17 19:04:31 UTC

how to dynamically add multiple LineSeries to a chart?

Hello, I'm looking for help for the *proper* way to dynamically set multiple LineSeries for a chart. I've provided the outline of my code below. 


I have a chart that can plot anywhere from 0 to some large number of LineSeries depending on the user's actions. I declare these LineSeries as an array (csArray) in an <fx:Declarations> block, which is later used in ActionScript function invalidateChart(). 


In using Flash Builder 4.6's memory profiler, I've noticed something interesting that makes me think something is broken with my code below. If I run the program and select a first plot with seven LineSeries. The chart renders fine. Then I select a second plot, which has a different set of seven LineSeries, which also renders fine. Now I look at the memory usage: 


Class=LineSeriesItem 
Package= mx.charts.series.items 
Cumulative Instances=2370 
Instances=2370 
Cumulative Memory=455050 (4.26%) 
Memory=455050 (11.68%) 


Next, I repeat the plotting of the above charts in the same order. That is, I re-select the option that plots the first chart that I looked at earlier (with 7 LineSeries). Then I select the options to plot the second chart that I looked at earlier (with a different set of 7 LineSeries compared to the first plot, but the same 7 LineSeries that I viewed for the second plot above). I would expect the memory usage to be unchanged from above. But what I see is a 3.9x increase in memory by LineSeriesItem: 



Class=LineSeriesItem 
Package= mx.charts.series.items 
Cumulative Instances=11577 
Instances=9207 
Cumulative Memory=2222784 (10.62) 
Memory=1767744 (28.14%) 


I don't understand why the memory increases from above... Is this normal behavior? 


If I repeat the plotting of the above two charts just like above (e.g. a third, or forth, or fifth, etc., time), the memory no longer increases for LineSeriesItems, regardless of how many times I repeat it. 


Please set me straight how to dynamically add LineSeries the proper way. Thanks for any help/advice. 


-----my code follows----- 



<fx:Declarations> 

<fx:Array id="csArray"> 
<mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> 
<mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> 
<mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> 
<mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> 
<mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> 
<mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> 
<mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> <mx:LineSeries /> 
<mx:LineSeries /> <mx:LineSeries /> 
</fx:Array> 
... 
</fx:Declarations> 


<fx:Script> 
<![CDATA[ 
... 
private var myData:Array; 
private var visArray:Array; 


public function invalidateChart():void { 

for (var ii:int=0;ii<myData.length;ii++) { 


var ls:LineSeries=csArray[ii]; 
ls.xField="x"; 
ls.yField="y"; 
ls.filterData=false; 


ls.setStyle("lineStroke",new SolidColorStroke(0x00FF00,10,1,true,"normal","square","round",3)); 
var cf:ClassFactory=new ClassFactory(com.myCompany.myrenderers.myLineRenderer); 
ls.setStyle("lineSegmentRenderer",cf); 
ls.setStyle("form","segment"); 
ls.dataProvider=myData[ii]; 
ls.y=-2; // shift plot up 
ls.x=1; // shift plot right 
} 


// only use those series for which visArray[i]=true 
var arr:Array=new Array(); 
for (var i:int=0;i < visArray.length;i++) { 
if(visArray[i]) 
arr.push(csArray[i]); 
} 
chart.series=arr; 


chart.invalidateDisplayList(); 
} 

... 
]]> 
</fx:Script> 


<myComponents:myLineChartComponent id="chart" ... /> 

Re: how to dynamically add multiple LineSeries to a chart?

Posted by Jonathan Campos <jo...@gmail.com>.
On Thu, Apr 18, 2013 at 5:08 PM, <mo...@comcast.net> wrote:

> Any hints that could get me thinking where else to look for the source of
> the leak?


I've worked with the charting a bit and haven't seen leaks in this section
of code. Obviously there is something holding a reference somewhere. I'd
recommend making a smaller testing application that just drawings lines to
a chart and seeing if you get the leak. Then building up from there to your
full application. It may be how your application stores data. It may be the
component. At this point it is impossible to tell.

J


-- 
Jonathan Campos

Re: how to dynamically add multiple LineSeries to a chart?

Posted by mo...@comcast.net.
Thanks Jonathan, 


Could you give me some possibilities that could cause the leak? It's showing up in the profiler as a LineSeriesItem class leak. 


I tried reseting the LineSeries before each new plot using: 

for each (var lineSeries:LineSeries in chart.series)
    lineSeries.dataProvider = null;  
				
// remove all lineseries
var tmp:Array = chart.series;
var len:int = chart.series.length;
for (var ss:int=len-1; ss >=0; ss--) {
    tmp.splice(ss,1);
}
chart.series=tmp;

but that had no effect on the leak. Not sure what else could be attached to LineSeriesItem that could still cause this leak. 

Any hints that could get me thinking where else to look for the source of the leak?  


----- Original Message ----- 
From: "Jonathan Campos" <jo...@gmail.com> 
To: "users" <us...@flex.apache.org> 
Sent: Thursday, April 18, 2013 12:18:02 PM 
Subject: Re: how to dynamically add multiple LineSeries to a chart? 

On Thu, Apr 18, 2013 at 12:30 PM, <mo...@comcast.net> wrote: 

> I implemented your architecture below (using s.dataProvider instead of 
> s.dataField) and adding some code before and after it as follows: 


Well technically you can set the data on the chart and have the lineseries 
just represent a specific property on the chart's data. But whichever way 
works for your application. 

The memory leak could be caused by many many reasons. Ultimately something 
isn't being released as expected. You'll have to dig further into your code 
if you are duplicating your data or some other issue that may be causing 
the leak. 

-- 
Jonathan Campos 

Re: how to dynamically add multiple LineSeries to a chart?

Posted by Jonathan Campos <jo...@gmail.com>.
On Thu, Apr 18, 2013 at 12:30 PM, <mo...@comcast.net> wrote:

> I implemented your architecture below (using s.dataProvider instead of
> s.dataField) and adding some code before and after it as follows:


Well technically you can set the data on the chart and have the lineseries
just represent a specific property on the chart's data. But whichever way
works for your application.

The memory leak could be caused by many many reasons. Ultimately something
isn't being released as expected. You'll have to dig further into your code
if you are duplicating your data or some other issue that may be causing
the leak.

-- 
Jonathan Campos

Re: how to dynamically add multiple LineSeries to a chart?

Posted by mo...@comcast.net.
Hi Jonathan, 

I implemented your architecture below (using s.dataProvider instead of s.dataField) and adding some code before and after it as follows:

// from: http://tjoadesign.nl/blog/?p=334
for each ( var lineSeries:LineSeries in chart.series )  
    lineSeries.dataFunction = null ; // note: this appears to null here by default anyway

-- start Jonathan's code---

var i:int = -1; 
var n:int = yourData.length; 
var genLineSeries:Array = []; 
while(++i<n) { 
var s:LineSeries = new LineSeries(); 
   //add properties as necessary to series 
   s.dataProvider = yourData[i].dataField; 
   genLineSeries.push(s); 
} 
chart.series = genLineSeries; 

-- end Jonathan's code---

chart.invalidateDisplayList();


Now there's a memory leak seen using Flash Builder profiler each time I toggle between two different plots. The memory occupied by LineSeries increases every time a plot (new, or old) is generated, forever.  

Is there something that needs to be reset or initialized somewhere? 


----- Original Message ----- 
From: "Jonathan Campos" <jo...@gmail.com> 
To: "users" <us...@flex.apache.org> 
Sent: Thursday, April 18, 2013 8:45:22 AM 
Subject: Re: how to dynamically add multiple LineSeries to a chart? 

On Wed, Apr 17, 2013 at 12:04 PM, <mo...@comcast.net> wrote: 

> Please set me straight how to dynamically add LineSeries the proper way. 
> Thanks for any help/advice. 


It's actually much easier than you are even doing it, pseudo code to follow: 

//loop your data describing the series that will be created 
var i:int = -1; 
var n:int = yourData.length; 
var genLineSeries:Array = []; 
while(++i<n) 
{ 
var s:LineSeries = new LineSeries(); 
//add properties as necessary to series 
//based on your data 
s.dataField = yourData[i].dataField; 
genLineSeries.push(s); 
} 
//assuming your chart 
lineChart.series = genLineSeries; 

//done 



-- 
Jonathan Campos 

Re: how to dynamically add multiple LineSeries to a chart?

Posted by mo...@comcast.net.
Thanks Jonathan, I'll give it a try. Just one question -- could you clarify if: 


s.dataField = yourData[i].dataField 


in your code below should really be: 


s.dataProvider = yourData[i].dataField 


as I don't see a dataField property available for a LineSeries. 

----- Original Message -----
From: "Jonathan Campos" <jo...@gmail.com> 
To: "users" <us...@flex.apache.org> 
Sent: Thursday, April 18, 2013 8:45:22 AM 
Subject: Re: how to dynamically add multiple LineSeries to a chart? 

On Wed, Apr 17, 2013 at 12:04 PM, <mo...@comcast.net> wrote: 

> Please set me straight how to dynamically add LineSeries the proper way. 
> Thanks for any help/advice. 


It's actually much easier than you are even doing it, pseudo code to follow: 

//loop your data describing the series that will be created 
var i:int = -1; 
var n:int = yourData.length; 
var genLineSeries:Array = []; 
while(++i<n) 
{ 
var s:LineSeries = new LineSeries(); 
//add properties as necessary to series 
//based on your data 
s.dataField = yourData[i].dataField; 
genLineSeries.push(s); 
} 
//assuming your chart 
lineChart.series = genLineSeries; 

//done 



-- 
Jonathan Campos 

Re: how to dynamically add multiple LineSeries to a chart?

Posted by Jonathan Campos <jo...@gmail.com>.
On Wed, Apr 17, 2013 at 12:04 PM, <mo...@comcast.net> wrote:

> Please set me straight how to dynamically add LineSeries the proper way.
> Thanks for any help/advice.


It's actually much easier than you are even doing it, pseudo code to follow:

//loop your data describing the series that will be created
var i:int = -1;
var n:int = yourData.length;
var genLineSeries:Array = [];
while(++i<n)
{
    var s:LineSeries = new LineSeries();
    //add properties as necessary to series
   //based on your data
   s.dataField = yourData[i].dataField;
   genLineSeries.push(s);
}
//assuming your chart
lineChart.series = genLineSeries;

//done



-- 
Jonathan Campos