Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CorePlot multiple scatterplots huge memory consumption

I'm experiencing some problems with CorePlot. I try to plot multiple scatterPlots into one graph. Which works as expected but when I start scrolling or zooming the graph the whole app increases it's memory usage up to 900MB an crashes. I think I have to do some object releasing but I don't know how. Basically I plot each line with a different plot identifier and put the according data into the datasource.

Here is what I got: (In this example code I just reduced the axe ranges with static values for testing purposes.)

- (void)setupGraph {
// Create graph from theme
self.graph = [[CPTXYGraph alloc] initWithFrame:self.scatterPlotView.bounds];
self.graph.plotAreaFrame.masksToBorder = NO;
self.scatterPlotView.hostedGraph = self.graph;

CPTTheme *theme = [CPTTheme themeNamed:kCPTPlainBlackTheme];
[self.graph applyTheme:theme];

self.graph.paddingLeft   = 0.0;
self.graph.paddingTop    = 0.0;
self.graph.paddingRight  = 0.0;
self.graph.paddingBottom = 0.0;


// Setup plot space
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace;

plotSpace.allowsUserInteraction = YES;

plotSpace.delegate = self;

plotSpace.globalXRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0) length:CPTDecimalFromDouble(30)];
plotSpace.globalYRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0) length:CPTDecimalFromDouble(15)];

plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0) length:CPTDecimalFromDouble(10)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0) length:CPTDecimalFromDouble(15)];

CPTXYAxisSet *axisSet = (CPTXYAxisSet *)self.graph.axisSet;
CPTXYAxis *x = axisSet.xAxis;
CPTXYAxis *y = axisSet.yAxis;
x.labelingPolicy = CPTAxisLabelingPolicyNone;
y.labelingPolicy = CPTAxisLabelingPolicyNone;
}

This method loads my data and draws the scatterplots

- (void)loadSignals {


//Data loading logic goes here nothing special just one array for each plot

for (Signal *sig in [signals allValues]) {
    [self constructScatterPlot:sig.name];
}
}];

This is where the drawing happens:

- (void)constructScatterPlot:(NSString *)identifier {    
    CPTScatterPlot *dataSourceLinePlot = [[CPTScatterPlot alloc] init];

   CPTMutableLineStyle *lineStyle = [dataSourceLinePlot.dataLineStyle mutableCopy];

    CPTScatterPlot *boundLinePlot = [[CPTScatterPlot alloc] init];
    boundLinePlot.identifier = identifier;

    lineStyle            = [boundLinePlot.dataLineStyle mutableCopy];
    lineStyle.miterLimit = 1.0;
    lineStyle.lineWidth  = 1.0;
    lineStyle.lineColor  = [CPTColor redColor];
    boundLinePlot.dataLineStyle = lineStyle;

    boundLinePlot.dataSource     = self;
    boundLinePlot.cachePrecision = CPTPlotCachePrecisionDouble;
    boundLinePlot.interpolation  = CPTScatterPlotInterpolationStepped;
    [self.graph addPlot:boundLinePlot];
}

...and this is where the datasource gets it's values:

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
NSString *plotIdent = (NSString *) plot.identifier;

     if (![plotIdent isEqualToString:self.currentIdent]) {
        self.countPlot++;
        self.currentIdent = plotIdent;
    }

Signal *newSig = [self.signals objectForKey:plotIdent];
    Value * newValue = [newSig valueAtTime:index];
NSNumber *number = [NSNumber numberWithInteger:[newValue.value integerValue]];

    if ( fieldEnum == CPTScatterPlotFieldY ) {

        return number;
    }
    if ( fieldEnum == CPTScatterPlotFieldX ) {
        return [NSNumber numberWithInteger:index];
    }
    return nil;
}

So first of all I'd like to know if this is the correct way of drawing multiple plots (up to 40 in my case) into one graph? If so, what could I do to optimize my plot performance?

The output should look like this: Expected (scrollable) output

like image 734
dibi Avatar asked Apr 30 '26 07:04

dibi


2 Answers

I found this use

"try setting collapsesLayers to YES on the hosting view"

Application get stuck when drawing nearly 40 Scatter Plots using Core Plot in IPad

like image 82
CppChase Avatar answered May 02 '26 20:05

CppChase


Each plot is a CALayer that covers the entire plot area of the graph, so with 40 of them you may be using up most of the available video memory. If they all use the same line style, you can plot all of the lines on the same plot and save some memory that way. Insert an extra data point between the line segments and return nil or @(NAN) from the datasource to break the line.

like image 22
Eric Skroch Avatar answered May 02 '26 21:05

Eric Skroch