【问题标题】:CorePlot ScatterPlot scrolling performance iPhone4CorePlot ScatterPlot 滚动性能 iPhone4
【发布时间】:2012-07-22 16:02:09
【问题描述】:

我正在使用核心情节来绘制图表。到目前为止,它似乎是一个很棒的框架,但是当我启用用户交互和执行滚动时,我遇到了一些性能问题。

起初我认为这是由于绘制的点数,所以我编写了一个简单的测试应用程序,点数很少。尽管情节尽可能简单,但滚动仍然很生涩。有了这个情节,我在 iPhone 4 上获得了大约 20-25 fps。

我是不是做错了什么,还是和核心情节一样快?

我的示例代码如下:

- (void)viewDidLoad
{
    [super viewDidLoad];

    graph = [(CPTXYGraph *)[CPTXYGraph alloc] initWithFrame:CGRectZero];

    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
    plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0) length: CPTDecimalFromDouble(5)];
    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0) length:CPTDecimalFromDouble(5)];
    plotSpace.allowsUserInteraction = YES;
    plotSpace.globalYRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-10) length:CPTDecimalFromDouble(100)];
    plotSpace.globalXRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInt(-10) length:CPTDecimalFromDouble(20)];

    // Axes
    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
    CPTXYAxis *x          = axisSet.xAxis;
    x.majorIntervalLength         = CPTDecimalFromInt(1);
    x.orthogonalCoordinateDecimal = CPTDecimalFromInt(0);
    x.axisConstraints = [CPTConstraints constraintWithLowerOffset:30];

    CPTXYAxis *y = axisSet.yAxis;
    y.majorIntervalLength         = CPTDecimalFromInt(1);
    y.minorTicksPerInterval       = 0;
    y.orthogonalCoordinateDecimal = CPTDecimalFromDouble(0);
    y.axisConstraints = [CPTConstraints constraintWithLowerOffset:30];

    // Create a plot that uses the data source method
    CPTScatterPlot *dataSourceLinePlot = [[CPTScatterPlot alloc] init];
    dataSourceLinePlot.identifier = @"1";

    CPTMutableLineStyle *lineStyle = [dataSourceLinePlot.dataLineStyle mutableCopy];
    lineStyle.lineWidth              = 3.f;
    lineStyle.lineColor              = [CPTColor redColor];
    dataSourceLinePlot.dataLineStyle = lineStyle;
    dataSourceLinePlot.dataSource = self;
    dataSourceLinePlot.delegate = self;
    [graph addPlot:dataSourceLinePlot];

    hostView.hostedGraph = graph;
}

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
    return 20;
}

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
    return [NSNumber numberWithInt:index];
}

【问题讨论】:

    标签: iphone ios uikit core-graphics core-plot


    【解决方案1】:

    最好在后台执行绘图。

    您可能正试图在主队列上绘制/处理这些图表,这很糟糕。正在发生的事情是您的所有渲染、处理和用户触摸事件都在主队列上进行备份,如下所示。所以你得到的是绘图、处理和触摸事件按照它们被接收的顺序发生(FIFO)。如果你把处理放在后台触摸事件将被处理而无需等待。 (请观看下面引用的视频)

    BAD (what you are probably doing)
    MainQueue: Process/Plot -> TouchEvent(scroll) -> Render -> Plot/Process -> Plot/Process -> TouchEvent(scroll) -> Update UI -> TouchEvent
    
    GOOD
    MainQueue: TouchEvent(scroll) -> TouchEvent(scroll) -> Update UI -> TouchEvent
    ProcessingQueue: Process/Plot -> Plot/Process -> Plot/Process 
    

    最好让 MainQueue 只处理渲染(UI 更新)和触摸事件,并将其他所有内容放在后台队列中。

    NSOperationQueue *q = [NSOperationQueue alloc] init];
    [q setName:@"Plotting Queue"];
    [q addOperationWithBlock:^{ plotGraph(); }];
    [q addOperationWithBlock:^{ 
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            updateTheUI();
         }];
    }];
    

    plotGraph 方法将是您上面的所有绘图代码。 updateTheUI 方法是你的 hostView.hostedGraph = graph;行加上任何代码以使 UI 重新呈现自身。

    观看名为 “在 iOS 上构建并发用户界面”的 WWDC 2012 视频

    【讨论】:

    • 第一次加载图形时最初调用绘图委托。它不会在每次后续重新加载或用户交互时调用。当滚动发生时,我相信 CorePlot 框架所做的唯一事情就是渲染。我并没有真正做任何后台任务,因为它都是与渲染相关的,所以我认为你的建议在这里适用,但如果我错了,请纠正我。
    • 您可能还需要将绘图移至背景。什么样的 viewController 持有这些地块? ScrollView、TableView 还是?
    • 另外,最好的办法是使用时间分析器来查看什么是尖峰。
    • 我会检查分析器以查看需要时间的内容,如果正在绘制,我看不出将其移至另一个线程会有什么帮助?它仍然需要同样长的时间。当我按照样本指示的方式使用 CorePlot 时,我更想知道这是否是一个已知的 CorePlot 问题。
    • 如果您观看上述视频可能会有所帮助。时间的长短很重要。队列确实很重要。如果您在主队列上进行绘图、绘图和处理事件,那么您将无法处理用户滚动。把它想象成一排在屠夫等待的人(拿一个号码)。你处理#1,然后是#2,然后是#3。因此,如果滚动事件是#3(用户滚动),那么在它前面的那些排队之前什么都不会发生,首先处理。滚动事件在队列中等待,直到它的编号被调用。在您的情况下,#1 和 #2 是大订单(4,000 人的牛排),您可能会永远等待。
    【解决方案2】:

    在我设置轴标记策略之前,我的散点图存在巨大的性能问题。将标签政策设置为 Automatic 或 None 消除了 5 秒的延迟。

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

    【讨论】:

    • 不幸的是,我需要轴标签。删除它们会带来轻微的性能提升,但不会太大。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多