iOS / Core-Animation: Performance tuning

前端 未结 5 1944
梦谈多话
梦谈多话 2021-02-04 05:17

I have my app running on my iPad. but it is performing very badly -- I am getting below 15fps. can anyone help me to optimise?

It is basically a wheel (derived from U

相关标签:
5条回答
  • 2021-02-04 05:49

    You should probably just re do this in OpenGL

    0 讨论(0)
  • 2021-02-04 05:51

    I know this question is old, but still up to date. CoreAnimation (CA) is just a wrapper around OpenGL - or meanwhile maybe around Metal. Layers are in fact textures drawn on rectangles and the animations are expressed using 3D transformations. As all of this is handled by the GPU, it should be ultra fast... but it isn't. The whole CA sub-system seems pretty complex and translating between AppKit/UIKit and the 3D world is harder than it seems (if you ever tried to write such a wrapper yourself, you know how hard it can be). To the programmer, CA offers a super simple to use interface but this simplicity comes with a price. All my attempts to optimize very slow CA were futile so far; you can speed it up a bit but at some point you have to reconsider your approach: Either CA is fast enough to does the job for you or you need to stop using CA and either implement all animation yourself using classic view drawing (if the CPU can cope with that) or implement the animations yourself using a 3D API (then the GPU will do it), in which case you can decide how the 3D world interacts with the rest of your app; the price is much more code to write or much more complex API to use, but the results will speak for themselves in the end.

    Still, I'd like to give some generic tips about speeding up CA:

    • Every time you "draw" to a layer or load content into a layer (a new image), the data of the texture backing this layer needs to be updated. Every 3D programmer knows: Updating textures is very expensive. Avoid that at all costs.
    • Don't use huge layers as if layers are too big to be handled directly by the GPU as a single texture, they are split into multiple textures and this alone makes performance worse.
    • Don't use too many layers as the amount of memory GPUs can spend on textures is often limited. If you need more memory than that limit, textures are swapped out (removed from GPU memory to make room for other textures, later on added back when they need to drawn). See first tip above, this kind of swapping is very expensive.
    • Don't redraw things that don't need redrawing, cache into images instead. E.g. drawing shadows and drawing gradients are both utlra expensive and usually rarely ever change. So instead of making CA draw them each time, draw them once to a layer or draw them to an image and load that image to a CALayer, then position the layer where you need it. Monitor when you need to update them (e.g. if the size of an object has changed), then re-draw them once and again cache the result. CA itself also tries to cache results, but you get better results if you control that caching yourself.
    • Careful with transparency. Drawing an opaque layer is always faster than drawing one that isn't. So avoid using transparency where not needed as the system will not scan all your content for transparency (or the lack of it). If a NSView contains no area where its parent shines through, make a custom subclass and override isOpaque to return YES. Same holds true for UIViews and layers where neither the parent, nor their siblings will ever shine through, but here it is enough to just set the opaque property to YES.

    If none of that really helps, you are pushing CA to its limits and you probably need to replace it with something else.

    0 讨论(0)
  • 2021-02-04 05:54

    Try it without your shadows and see if that improves performance. I imagine it will improve it greatly. Then I'd look into using CALayer's shadowpath for rendering shadows. That will greatly improve shadow rendering performance.

    Apple's Core Animation videos from last year's WWDC have a lot of great info on increasing performance in core animation.

    By the way, I'm animating something way more complex then this right now and it works beautifully even on an older iPhone 3G. The hardware/software is quite capable.

    0 讨论(0)
  • 2021-02-04 05:56

    I have no experience in developing iPad applications but I do have some in optimizing video games. So, I cannot give an exact answer but I want to give some tips in optimization.

    Do not guess. Profile it.

    It seems you are trying to make changes without profiling the code. Changing some suspicious code and crossing your fingers does not really work. You should profile your code by examining how long each task takes and how often they need to run. Try to break down your tasks and put profiling code to measure time and frequency. It's even better if you can measure how much memory are used for each task, or how many other system resources. Find your bottleneck based an evidence, not your feeling.

    For your specific problem, you think the program gets really slow when your resizing work kicks in. But, are you sure? It could be something else. We don't know for sure until we have actual profiling data.

    Minimize problematic area and measure real performance before making changes.

    After profiling, you have a candidate for your bottleneck. If you can still split the cause to several small tasks, do it and go to profile them until you cannot split it anymore. Then, try to measure their precise performance by running them repeatedly like a few thousand times. This is important because you need to know the performance (speed & space) before making any changes so that you can compare it to future changes.

    For your specific problem, if resizing is really the issue, try to examine how it performs. How long it takes to perform one resize call? How often you need to do resize work to complete your job?

    Improve it. How? It depends.

    Now, you have the problematic code block and its current performance. You now have to improve it. How? well, it really depends on what the problem is. you could search for better algorithms, you could do lazy fetching if you can delay calculations until you really need to perform, or you could do over-eager evaluation by caching some data if you are doing the same operation too frequently. The better you know the cause, the easier you can improve it.

    For your specific problem, it might be just the limit of OS ui function. Usually, resizing button is not just resizing button itself but it also invalidates a whole area or its parent widget so that every ui stuff can be rendered properly. Resizing button could be expensive and if that's the case, you could resolve the issue by simply using image-based approach instead of OS ui-based system. You could try to use OpenGL if image operations from OS API are not enough. But, again, we don't know until we actually try them out and profile these alternatives. Good luck! :)

    0 讨论(0)
  • 2021-02-04 05:58

    Are you using shadows on your layer for me it was a cause of performance issue, then you have 2 options AFAIK: - setting shadowPath that way, CA does not have to compute it everytime - removing shadows and using images to replace

    0 讨论(0)
提交回复
热议问题