ChartsOrg / Charts

Beautiful charts for iOS/tvOS/OSX! The Apple side of the crossplatform MPAndroidChart.
Apache License 2.0
27.59k stars 6k forks source link

Core Graphics in Charts ? #2417

Open aravinth02 opened 7 years ago

aravinth02 commented 7 years ago

This is about why Core Graphics was chosen to draw the charts instead of using CAShapeLayer on a View ?

The reason why I am asking this since overriding drawRect stores the backing image before display the view to screen. And this backing store consumes expensive memory and CPU though.

Hope the same charts are drawable using CAShapeLayer on UIView and thus not required to override drawRect method

Thanks.

liuxuan30 commented 7 years ago

Can you enlighten me why using CAShapeLayer is better than Core Graphics, and it uses less memory and CPU? and don't have to call setNeedsDisplay?

karthisrini commented 7 years ago

Hi ,

@liuxuan30 I referred Apple's animation guide.

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/CoreAnimationBasics/CoreAnimationBasics.html#//apple_ref/doc/uid/TP40004514-CH2-SW12

Say we are rotating Pie chart on touch and rotate an pie section. It calls UIView "drawRect". On every time it re renders Pie section (on each frame since setNeedsDisplay called on animation). But in above article has below snippet

With view-based drawing, changes to the view itself often result in a call to the view’s drawRect: method to redraw content using the new parameters. But drawing in this way is expensive because it is done using the CPU on the main thread. Core Animation avoids this expense by whenever possible by manipulating the cached bitmap in hardware to achieve the same or similar effects.

So if have drawn the each pie section in layer and rotated all layers it would have avoided the need of CPU spike on on each frame load. Layer might have used Cached Bit Map and rotated around centre.

aelam commented 7 years ago

@liuxuan30 CAShapeLayer with UIBezierPath is drawn by GPU.

aelam commented 7 years ago

@liuxuan30 Currently, not just PieChart does so, BarChart, LineChart all work in this mechanism. it uses CADisplayLink to refresh, and draws 1%, 2% ... 50%... 100% then it looks it has animation. I think it's fine if it uses OpenGL(ES).

But if it uses CoreAnimation, it might be draw everything done, and commit animations to GPU with CoreAnimation, then CPU doesn't have much pressure

liuxuan30 commented 7 years ago

I agree with OpenGL to gain performance, and for pie chart rotation, it also makes sense.

but for CoreAnimation, I guess it depends, as it's not just about animation, it's also related to data update and refresh the view, I don't see CA will have benefit when updating the data and redraw chart?

And quote from the doc:

You would typically not use Core Animation to replace the content of a view 60 times a second, such as in a cartoon. Instead, you use Core Animation to move a view’s content around the screen, fade that content in or out, apply arbitrary graphics transformations to the view, or change the view’s other visual attributes.

However our animation now looks like a FPS 60 thing which is not ideal for CA?

liuxuan30 commented 7 years ago

And in more implementation details, how would you recommend using CAShaplayer to implement like lien chart or bar chart? If one bar means a sub layer, I guess it's more expensive? If we put everything in one layer, it seems the same as what we do now (a view has one layer by default)

jjatie commented 7 years ago

It doesn't have to be written as one layer, but can be flattened to a single (or handful of) layer before rendering. Again, not sure about performance, but much of Apple's documentation points to using CA instead of CG. It seems a reasonable hypothesis that a Metal backed CA would perform better than the current custom drawing on the CPU.