성능 최적화 고려 사항

5240 단어

1. 대상을 쉽게 조정하지 마라


대상의 조정도 자주 CPU 자원을 소모하는 곳이다.특히 CALayer: CALayer 내부에는 속성이 없습니다. 속성 방법을 호출할 때 내부는 실행할 때 ResolveInstanceMethod를 통해 대상에게 임시로 방법을 추가하고 대응하는 속성 값을 내부의 Dictionary에 저장합니다. 또한delegate를 알리고 애니메이션을 만드는 등 자원을 많이 소모합니다.UIView의 디스플레이와 관련된 속성(예를 들어 프레임/bounds/transform) 등은 사실상 모두 CALayer 속성이 비치기 때문에 UIView의 이러한 속성을 조정할 때 소모되는 자원은 일반적인 속성보다 훨씬 크다.이에 대해 응용 프로그램에서 불필요한 속성 수정을 최대한 줄여야 한다.
뷰 계층을 조정할 때 UIView, CALayer 간에 호출과 알림이 많이 발생하기 때문에 성능을 최적화할 때 뷰 계층을 조정하고 뷰를 추가하고 제거하는 것을 최대한 피해야 한다.

2. 대상을 자주 만들지 말고 조건이 있으면 재사용을 우선적으로 고려한다.


대상의 창설은 메모리를 분배하고 속성을 조정하며 심지어 파일을 읽는 작업까지 하여 CPU 자원을 비교적 소모한다.가급적 무게의 대상을 가벼운 대상으로 대체하면 성능을 최적화할 수 있다.예를 들어 CALayer가 UIView보다 훨씬 가볍기 때문에 터치 이벤트에 응답하는 컨트롤러가 필요하지 않고 CALayer로 표시하는 것이 더욱 적합하다.객체가 UI 작업과 관련이 없는 경우 가능한 백엔드 스레드로 만들려고 하지만 안타깝게도 CALayer가 포함된 컨트롤은 마스터 스레드에서만 만들고 조작할 수 있습니다.만약 대상이 복용할 수 있고, 복용의 대가가 방출, 새 대상을 만드는 것보다 적다면, 이러한 대상은 가능한 한 캐시 탱크에 복용해야 한다.

3. Storyboard와 Xib을 사용하지 마십시오.


Storyboard/Xib를 통해 보기 대상을 만들 때 그 자원 소모는 코드를 직접 통해 대상을 만드는 것보다 매우 크고 매우 많다. 성능이 민감한 인터페이스에서 Storyboard/Xib는 좋은 기술 선택이 아니다.

4. 게으름에 적응할 수 있다면


대상의 창설 시간을 최대한 늦추고 대상의 창설을 여러 작업으로 분산시킨다.비록 이것은 실현하기가 비교적 번거롭고 가져오는 장점이 많지 않지만, 할 능력이 있다면 가능한 한 시도해 보아야 한다.

5. 백그라운드 스레드에서 중량급 대상을 폐기


대상의 폐기는 자원을 많이 소모하지는 않지만 누적하는 것도 무시할 수 없다.일반적으로 용기류가 대량의 대상을 가지고 있을 때 소각할 때의 자원 소모는 매우 뚜렷하다.마찬가지로 만약 대상이 백엔드 라인에 놓아서 방출할 수 있다면 백엔드 라인으로 옮겨라.여기에 작은 Tip이 있습니다. 대상을 Block에 포획한 다음 백엔드 대기열에 던져서 컴파일러 경고를 피하기 위해 메시지를 보내면 백엔드 라인에서 대상을 삭제할 수 있습니다.
NSArray *tmp = self.array;
self.array = nil;
dispatch_async(queue, ^{
    [tmp class];
});

6. 이미지 관리


UIImage Apple 공식 문서는 UIImage 객체를 생성하는 두 가지 방법을 제공합니다.
  • imageNamed, 그 매개 변수는 그림의 이름이다.
  • imageWithContentsOffile, 그 매개 변수도 그림 파일의 경로입니다.
  • imageNamed: 이 방법은 시스템 캐시에서 그림 대상을 지정한 이름으로 찾아서 되돌려줍니다.캐시에서 해당하는 그림을 찾지 못하면, 이 방법은 지정한 문서에서 불러와서 캐시하고 대상을 되돌려줍니다.따라서 이미지Named의 장점은 그림을 불러올 때 캐시하는 것입니다.그래서 그림이 자주 사용될 때 이미지Named 방법을 사용하는 것이 좋습니다.예를 들어 TableView의 TableView Cell에 같은 아이콘을 불러와야 합니다. 이미지 Named로 그림을 불러오는 효율이 매우 높습니다.시스템은 그 아이콘을 메모리에 저장하고, Table View Cell에서 그 그림을 사용할 때마다 그림 바늘을 같은 메모리로 가리킨다.그렇기 때문에 이미지 Named를 사용하면 그림을 캐시하고 그림의 데이터를 메모리에 넣는다. iOS의 메모리는 매우 귀하고 메모리 소모가 너무 크면 메모리를 강제로 방출한다. 즉memory warnings를 만나게 된다.iOS 시스템에서 이미지의 메모리를 방출하는 것은 비교적 번거로운 일로 메모리 유출을 초래할 수 있다.예를 들어, UIView 객체의 animationImages가 UIImage 객체의 동적 배열인 NSMutable Array인 경우 프레임별 애니메이션을 수행합니다.이미지를 동적 배열 NSMutable Array에 imageNamed 방식으로 로드하면 메모리 유출이 발생할 수 있습니다.원인은 매우 명백하다.imageWithContentsOffile: 이미지만 로드되고 이미지 데이터는 캐시되지 않습니다.따라서 비교적 큰 그림과 사용 상황이 적을 때 이 방법으로 메모리 소모를 줄일 수 있다.

    7. 레이아웃 계산


    보기 레이아웃의 계산은 앱에서 가장 흔히 볼 수 있는 CPU 자원을 소모하는 곳이다.만약 백엔드 라인에서 보기 레이아웃을 미리 계산하고 보기 레이아웃을 캐시할 수 있다면 이곳은 기본적으로 성능 문제가 발생하지 않을 것이다.
    뷰 레이아웃은 어떤 기술을 사용하든 UIView에 적용됩니다.frame/bounds/center 등 속성 조정에 있어위에서 말한 바와 같이 이러한 속성에 대한 조정은 자원을 매우 소모하기 때문에 가능한 한 레이아웃을 미리 계산하고 필요할 때 대응하는 속성을 한꺼번에 조정하며 여러 번, 빈번하게 이런 속성을 계산하고 조정하지 않는다.

    8. Autolayout 사용 정보


    만약 한 인터페이스에 대량의 텍스트가 포함된다면, 텍스트의 넓이 계산은 많은 자원을 차지할 뿐만 아니라, 피할 수 없을 것이다.텍스트 표시에 특별한 요구가 없다면, UILAbel 내부의 실현 방식을 참고하십시오. [NSAttributed String bounding RectWith Size: options:context:] 로 텍스트의 폭을 계산하고, - [NSAttributed String draw With Rect: options:context:] 로 텍스트를 그릴 수 있습니다.비록 이 두 가지 방법은 성능이 좋지만, 여전히 메인 라인이 막히지 않도록 백엔드 라인에 놓아야 한다.
    만약 당신이 CoreText로 텍스트를 그린다면, CoreText 레이아웃 대상이 되어 스스로 계산할 수 있고, CoreText 대상은 나중에 그림을 그릴 때 사용할 수 있도록 보존할 수 있습니다.

    9. 텍스트 렌더링


    화면에 보이는 모든 텍스트 내용 컨트롤, UIWebView를 포함하여, 밑바닥은 CoreText를 통해 조판되고, 비트맵으로 그려져 있습니다.일반적인 텍스트 컨트롤(UIlabel, UITExtView 등)은 레이아웃과 그리기가 주 스레드에서 이루어지기 때문에 대량의 텍스트를 표시할 때 CPU의 압력이 매우 크다.이 해결 방안은 사용자 정의 텍스트 컨트롤로 TextKit나 맨 밑에 있는CoreText로 텍스트를 비동기적으로 그리는 것입니다.비록 이것은 실현하기 매우 번거롭지만 그 장점도 매우 크다. 코어텍스 대상이 만들어진 후에 텍스트의 넓고 높은 정보를 직접 얻을 수 있어 여러 번의 계산을 피할 수 있다(UIlabel 대시간 계산, UIlabel 그리기 시 내부 재계산).CoreText 객체는 나중에 여러 번 렌더링할 수 있도록 메모리를 적게 사용합니다.
    전형적인 것은 TableView의cell이 label에 값을 매겨야 한다는 것이다. 만약에 label의 텍스트가attributed String을 사용한다면tableView가 미끄러지는 과정에서 우리는 서버에서 NSString의 문자를 받았는데 NSString에서 NSAttributed String으로 전환하는 것은 시간이 많이 걸리는 작업이다.우리는 이 조작을 앞당겨야 한다. 예를 들어 비동기적인 루틴이 해석된 후에 NSAttributed String으로 전환해야 한다.이렇게 하면 메인 라인을 막지 않을 뿐만 아니라, 미끄러질 때도 별도의 렌더링이 필요하지 않다.

    10. 그림의 디코딩


    UIImage나 CGImageSource의 몇 가지 방법으로 그림을 만들 때, 그림 데이터는 바로 디코딩되지 않습니다.그림을 UIImageView 또는 CALayer에 설정합니다.콘텐츠에서 가고 CALayer가 GPU에 제출되기 전에 CGImage의 데이터가 디코딩됩니다.이 단계는 주선에서 발생했을 뿐만 아니라 피할 수 없다.이 메커니즘을 돌리려면, 흔히 볼 수 있는 방법은 백엔드 라인에서 먼저 그림을 CG Bitmap Context에 그린 다음 Bitmap에서 직접 그림을 만드는 것입니다.현재 흔히 볼 수 있는 인터넷 사진 라이브러리는 모두 이 기능을 자체로 가지고 있다.

    11. 이미지 그리기


    그림의 그리기는 보통 CG로 시작하는 방법으로 그림을 캔버스에 그려서 캔버스에서 그림을 만들고 이런 과정을 보여주는 것을 말한다.여기서 가장 흔히 볼 수 있는 곳은 [UIView draw Rect:] 안입니다.CoreGraphic 방법은 일반적으로 모두 라인이 안전하기 때문에 그림의 그리기는 백엔드 라인에 쉽게 놓을 수 있다.간단하게 비동기적으로 그리는 과정은 대체로 다음과 같다(실제 상황은 이보다 훨씬 복잡하지만 원리는 기본적으로 일치한다)
    - (void)display {
        dispatch_async(backgroundQueue, ^{
            CGContextRef ctx = CGBitmapContextCreate(...);
            // draw in context...
            CGImageRef img = CGBitmapContextCreateImage(ctx);
            CFRelease(ctx);
            dispatch_async(mainQueue, ^{
                layer.contents = img;
            });
        });
    }
    

    좋은 웹페이지 즐겨찾기