Quinn-Curtis Forums
Quinn-Curtis Forums
Home | Profile | Register | Active Topics | Members | Search | FAQ
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 Tools for Java
 QCRTGraph for Java
 Performance hotspots
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic  

PeterJ

26 Posts

Posted - 11 Aug 2010 :  14:12:12  Show Profile  Reply with Quote
We're hitting performance issues where a couple of Quinn Curtis methods are taking up ~80% of the cpu. Has anybody else hit this and found a workaround?


Setup
We're plotting ten variables on a chart with a 30 min span. Values are being updated around once a seconds.

We have a ChartView with a RTScrollFrame. Each variable is its own SimpleLinePlot.

Hot Spots
CPU usage increases as more and more data becomes loaded on the plots.

Two methods are dominating the cpu usage.

com.quinncurtis.chart2djava.SimpleDataSet.checkValidData
and
com.quinncurtis.chart2djava.PhysicalCoordinats.physToUserX

checkValidData is creating a GregorianCalendar object for each data point on each variable and is called several times in SimpleLinePlot's drawLinePlot. Is there anyway to disable this check as it appears to only apply when using non 24 hour days or non 7 day weeks.

Edited by - PeterJ on 11 Aug 2010 14:26:51

PeterJ

26 Posts

Posted - 11 Aug 2010 :  14:15:47  Show Profile  Reply with Quote
Here is a sketch of how we're setting up our plot.

ChartView plotView = new ChartView();

timeCoordinates = new TimeCoordinates( startTime,
nonTimeVaribleAxisMinValue,
endTime,
nonTimeVaribleAxisMaxValue);

ChartAttribute newPlotAttribute = new ChartAttribute (Color.White, plotLineThickness,ChartConstants.LS_SOLID);

TimeSimpleDataSet processVarsDataSet = new TimeSimpleDataSet(dataSetName, 0);
RTProcessVar newRTProcessVar = new RTProcessVar(processVarsDataSet, newPlotAttribute);

newRTProcessVar.setDatasetEnableUpdate(true);
newRTProcessVar.setAutoTruncateDataset(true);
newRTProcessVar.setAutoTruncateMaxCount(dataBufferSize);
newRTProcessVar.setMaximumValue(Double.MAX_VALUE);
newRTProcessVar.setMinimumValue(-Double.MAX_VALUE);

SimpleLinePlot lineplot = new SimpleLinePlot(timeCoordinates, processVarsDataSet, newPlotAttribute);

RTSimpleSingleValuePlot plotData = new RTSimpleSingleValuePlot(timeCoordinates,lineplot, newRTProcessVar);

rtScrollFrame = new RTScrollFrameEnhanced(plotView, var, timeCoordinates,
ChartConstants.RT_FIXEDEXTENT_MOVINGSTART_AUTOSCROLL);

rtScrollFrame.addProcessVar(newRTProcessVar);

plotView.addChartObject(plotData);



Edited by - PeterJ on 11 Aug 2010 14:23:06
Go to Top of Page

quinncurtis

1534 Posts

Posted - 11 Aug 2010 :  14:30:58  Show Profile  Reply with Quote
There is no way you are going to remove physToUser, since that handles the conversion from Time/Date units into user coordinates. As far as the checkValidData call, there is no flag to set to remove that check. One of the most common error programmers make in using the software is to enter garbage values outside of the valid range, so we can't really remove the checks. Do you have the source code? You could probably create your own optimized version of the library.

You don't say if you are updating the display once a second, or just the data once a second. You can certainly update the data once a second, but only update the display once every 5 seconds, cutting your CPU usage by 500%.
Go to Top of Page

PeterJ

26 Posts

Posted - 11 Aug 2010 :  14:38:02  Show Profile  Reply with Quote
We're trying that. We've overridden TimeSimpleDataset as follows.


public class TimeSimpleDataSetEnhanced extends TimeSimpleDataset {

public TimeSimpleDataSetEnhanced(String dataSetName, int dataBufferSize) {
super(dataSetName, dataBufferSize);
}

@Override
public boolean checkValidData(PhysicalCoordinates transform, int index)
{
System.out.println("calling");
return true;
}
}
Go to Top of Page

PeterJ

26 Posts

Posted - 11 Aug 2010 :  14:39:33  Show Profile  Reply with Quote
And we're trying to get a RTProcess var to use our overridden class.

Changes to the code sketched above:

TimeSimpleDataSetEnhanced processVarsDataSet = new TimeSimpleDataSetEnhanced(dataSetName, 0);
RTProcessVar newRTProcessVar = new RTProcessVar(processVarsDataSet, newPlotAttribute);
...
SimpleLinePlot lineplot = new SimpleLinePlot(timeCoordinates, processVarsDataSet, newPlotAttribute);

But no joy. It looks like the dataset is getting replaced with a TimeSimpleDataSet somewhere.

Edited by - PeterJ on 11 Aug 2010 14:40:31
Go to Top of Page

PeterJ

26 Posts

Posted - 11 Aug 2010 :  14:47:26  Show Profile  Reply with Quote
> You don't say if you are updating the display once a second, or just the data once a second. You can certainly update the data once a second, but only update the display once every 5 seconds, cutting your CPU usage by 500%.

We have to update the display once per second as we have a real time control application and the operator needs to see updates that frequently.
Go to Top of Page

quinncurtis

1534 Posts

Posted - 11 Aug 2010 :  15:09:34  Show Profile  Reply with Quote
checkValidData is not marked abstract, so you can't override it in a subclass and expect the override to be called in the library.

You did not say, do you have the source?




Go to Top of Page

PeterJ

26 Posts

Posted - 11 Aug 2010 :  15:14:02  Show Profile  Reply with Quote
We have the source, but we're trying to minimize our modifications to specialization.
Go to Top of Page

quinncurtis

1534 Posts

Posted - 11 Aug 2010 :  15:23:45  Show Profile  Reply with Quote
Changing the source code is the only solution I can suggest. Change the checkValidDataX routine in SimpleDataset

public boolean checkValidDataX(PhysicalCoordinates transform, int index)
{
boolean resultx, result;
double xvalue = getXDataValue(index);
if (transform.getXScale().getChartObjType() == ChartConstants.TIME_SCALE_OBJ)
{
resultx = true;
}
else
resultx = ChartSupport.bGoodValue(xvalue);
result = resultx;
return result;
}

Let us know what improvement you see. I would expect some improvement. Most of the time is taken up by the time/date to user coordinates conversion, not the range checking.
Go to Top of Page

PeterJ

26 Posts

Posted - 11 Aug 2010 :  18:00:50  Show Profile  Reply with Quote
We got the specialization approach to work by extending SimpleDataSet and overriding the checkValid method. That is a clean solution as we want to minimize our disturbance of your code so we can keep up with future versions.

Performance improvement was huge. As you suspected, the Gregorian parts were taking a lot of time and were topping out the list on our profiling tool.

There are a lot of place in your code were it looks like GregorianCalendar is being used when one could keep things as times in milliseconds. Are you getting a push from any other customers to optimize performance?
Go to Top of Page

PeterJ

26 Posts

Posted - 11 Aug 2010 :  18:01:51  Show Profile  Reply with Quote
I should add a thank you for you help today. It was invaluable.
Go to Top of Page

quinncurtis

1534 Posts

Posted - 12 Aug 2010 :  08:32:11  Show Profile  Reply with Quote
We store time data internally as milliseconds. Since our TimeCoordinates scale support discontinuous time, critical for financial applications, we have to use of GregorianCalendar objects for coordinate conversion and range checking. One can use our elapsed time scales, and the Cartesian scales for other continuous time applications. Have we found a significant market where developers are willing to pay a little extra for a specialized, continuous time/date scale that runs about as fast as our Cartesian and ElapsedTime scales? Can't say that we have.
Go to Top of Page

PeterJ

26 Posts

Posted - 12 Aug 2010 :  17:03:45  Show Profile  Reply with Quote
It looks like we made an error selecting the TimeCoordinates scale and need to look into your elapsed time scale.
Go to Top of Page

quinncurtis

1534 Posts

Posted - 12 Aug 2010 :  18:43:22  Show Profile  Reply with Quote
The determining factor should not be update speed though. If you want elapsed time displayed, i.e elapsed hh:mm:ss.mmm from the start event, without date information, then the ElapsedTimeCoordinates coordinate system is what you should be using. If you require an absolute date/time scale, then you should be using the TimeCoordinates.
Go to Top of Page

PeterJ

26 Posts

Posted - 16 Aug 2010 :  16:11:20  Show Profile  Reply with Quote
We did a few minor tweaks on the Time axis code in just reducing the number of GregorianCalendar instances created. It has resulted in a tremendous speed up and has not (hopefully!) changed your functionality. We'll feed the source code changes back to you for consideration through your @support.

Thanks again for the awesome support through your forum.
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
Quinn-Curtis Forums © 2000-2018 Quinn-Curtis, Inc. Go To Top Of Page
Powered By: Snitz Forums 2000 Version 3.4.07