Author |
Topic |
|
PeterJ
26 Posts |
Posted - 11 Aug 2010 : 14:12:12
|
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
|
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 |
|
|
quinncurtis
1586 Posts |
Posted - 11 Aug 2010 : 14:30:58
|
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%.
|
|
|
PeterJ
26 Posts |
Posted - 11 Aug 2010 : 14:38:02
|
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; } }
|
|
|
PeterJ
26 Posts |
Posted - 11 Aug 2010 : 14:39:33
|
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 |
|
|
PeterJ
26 Posts |
Posted - 11 Aug 2010 : 14:47:26
|
> 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. |
|
|
quinncurtis
1586 Posts |
Posted - 11 Aug 2010 : 15:09:34
|
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?
|
|
|
PeterJ
26 Posts |
Posted - 11 Aug 2010 : 15:14:02
|
We have the source, but we're trying to minimize our modifications to specialization. |
|
|
quinncurtis
1586 Posts |
Posted - 11 Aug 2010 : 15:23:45
|
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. |
|
|
PeterJ
26 Posts |
Posted - 11 Aug 2010 : 18:00:50
|
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? |
|
|
PeterJ
26 Posts |
Posted - 11 Aug 2010 : 18:01:51
|
I should add a thank you for you help today. It was invaluable. |
|
|
quinncurtis
1586 Posts |
Posted - 12 Aug 2010 : 08:32:11
|
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. |
|
|
PeterJ
26 Posts |
Posted - 12 Aug 2010 : 17:03:45
|
It looks like we made an error selecting the TimeCoordinates scale and need to look into your elapsed time scale. |
|
|
quinncurtis
1586 Posts |
Posted - 12 Aug 2010 : 18:43:22
|
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. |
|
|
PeterJ
26 Posts |
Posted - 16 Aug 2010 : 16:11:20
|
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. |
|
|
|
Topic |
|