Android App 최적화 카드 제거

6108 단어
읽기 편리하도록 안드로이드 앱 성능 최적화 시리즈를 디킨 오리지널로 옮겨달라는 요청이 들어왔다.금을 파는 새로 나온 '수집집' 기능은 시리즈 문집을 만드는 데 쓸 수 있다.
이 부분에서 우리는 앱에서 끊기는 현상에 대해 이야기하자.
1, 감지 카드
사용자가 카드에 대한 감지는 주로 인터페이스의 리셋에서 비롯된다.인터페이스의 성능은 주로 장치의 UI 렌더링 성능에 의존한다.만약에 우리의 UI 디자인이 너무 복잡하거나 실현이 잘 되지 않고 설비가 힘을 주지 않는다면 인터페이스가 끊긴 것처럼 사용자에게 끊기는 느낌을 줄 것이다.
1.1 16ms 지침
카드의 원인을 분석하기 전에 안드로이드의 유명한'16ms'원칙을 알아보자.
안드로이드 시스템은 16ms마다 VSYNC 신호를 보내서 우리의 인터페이스 (Activity) 를 다시 그립니다.왜 16ms일까. 안드로이드가 설정한 리셋률은 60FPS(Frame Per Second)이고 초당 60 프레임의 리셋률로 약 16ms에 한 번 리셋되기 때문이다.
이와 같다.
이것은 우리가 16ms 내에 다음 갱신 인터페이스의 관련 연산을 완성하여 인터페이스가 갱신될 수 있도록 해야 한다는 것을 의미한다.그러나 만약 우리가 16ms 내에 이번 연산을 완성하지 못한다면 어떻게 될까요?
예를 들어, 우리가 화면의 배경 그림을 업데이트하려면 24ms가 필요합니다.시스템이 첫 번째 16ms에 인터페이스를 새로 고쳤지만, 우리의 연산은 아직 끝나지 않아서 그림을 그릴 수 없습니다.시스템이 16ms 간격으로 VSYNC 정보를 다시 한 번 보낼 때 사용자는 업데이트된 그림을 볼 수 있습니다.즉 사용자가 32ms가 된 후에 이번 리셋을 보았다는 것이다. (주의, 24ms가 아니다.)이것이 바로 전설의 프레임 잃어버리기(dropped frame):droped frame
프레임 잃어버리는 것이 사용자에게 주는 느낌은 바로 끊기는 것이다. 게다가 연산이 너무 복잡하면 프레임 잃어버리는 것이 더 많아서 인터페이스가 항상 정체 상태에 있고 폭발할 정도로 끊긴다.
그러면 어떤 흔히 볼 수 있는 상황이 16ms를 초과하여 연산을 하고 프레임을 잃어버려서 사용자로 하여금 렉이 걸리게 할 수 있습니까?
2, 끊김 원인 분석 및 처리
일반적으로 다음과 같은 몇 가지 상황이 카드와 같은 성능 문제를 초래할 수 있다. 우리는 하나하나 살펴보자.
2.1 너무 복잡한 배치
앞서 설명한 바와 같이 인터페이스 성능은 UI 렌더링 성능에 따라 달라집니다.우리는 UI 렌더링의 전체 과정이 CPU와 GPU 두 부분이 협동하여 완성된 것으로 이해할 수 있다.
그 중에서 CPU는 UI 레이아웃 요소의 Measure, Layout, Draw 등과 관련된 연산 실행을 담당한다.GPU는 화면에 UI 요소를 그리는 그리기(rasterization)를 담당합니다.
만약 우리의 UI 레이아웃이 너무 깊거나 사용자 정의 컨트롤러의 onDraw에 복잡한 연산이 있다면 CPU와 관련된 연산은 16ms보다 커서 렉이 걸릴 수 있습니다.
이때 우리는 Hierarchy Viewer라는 도구를 빌려 레이아웃을 분석할 필요가 있다.Hierarchy Viewer는 UI 레벨을 그래픽화된 트리 구조로 표시할 수 있을 뿐만 아니라 각 노드에 세 개의 작은 원점을 주어 이 요소인 Measure, Layout, Draw의 소모 시간과 성능을 표시할 수 있다.
구체적으로 App 최적화의 Layout을 어떻게 배치하는지 참고하세요.
2.2 오버드로잉(Overdraw)
위에서 말한 CPU에 대한 GPU 그리기는 Overdraw가 존재하면 끊길 수도 있습니다.
Overdraw: 화면에 픽셀이 한 프레임에 다시 그려진 횟수를 설명하는 데 사용됩니다.통속적으로 말하자면 이상적인 상황에서 모든 스크린과 프레임에 있는 모든 화소점은 한 번만 그려져야 한다. 만약에 여러 번 그려지면 오버드라우가 과도하게 그려진다.
2.2.1 Overdraw 디버그
Android 시스템은 overdraw의 현상을 쉽게 볼 수 있도록 시각화된 방안을 제공합니다.'시스템 설정'->'개발자 옵션'->'GPU 과도한 그리기 디버깅'에서 디버깅을 시작합니다.
이 때 인터페이스에는 다섯 가지 색상 ID가 있을 수 있습니다.
  • 원색:오버드라우 없음
  • 블루: 1회 오버드라
  • 그린: 2회 오버드라
  • 핑크: 오버드라우 3회
  • 빨간색: 4회 및 4회 이상 오버드라우
  • 일반적으로 파란색은 받아들일 수 있고 성능이 우수하다.
    2.2.2 Overdraw의 분석 처리
    위에서 말한 바와 같이, 이른바 Overdraw는 하나의 화소점에 여러 번 그려진 것이다.흔히 볼 수 있는 것은 다음과 같다.
  • 다중 배경을 그렸습니다.
  • 보이지 않는 UI 요소를 그립니다.

  • 아니면 GithubApp이라는 App 코드를 예로 들어 디버깅하고 애플리케이션을 켜서 다음과 같은 모습을 보여줍니다.
    중간 리스트를 보실 수 있습니다. 이 오버드라우가 심각합니다.코드 검색 보기:
    fragment_trending_container.xml에서 ViewPager가 배경을 설정합니다.

    ViewPager의 fragment에는 배경이 설정되어 있습니다.
    
    
    
        ...
    

    전체 코드는Github의 원본 코드를 보십시오. 본고가 분석할 때commit는 b01b5793까지 있습니다.
    외부 ViewPager 배경을 삭제하고 보려면 다음과 같이 하십시오.
    중간 목록 구역은 더 이상 빨간색이 아니지만 파란색이라는 받아들일 수 있는 등급에 이르지 못했다는 것을 알 수 있다.이것은 우리의Activity가 기본적으로 theme에서 window에 순수한 색 배경을 설정하기 때문입니다.이 기본 배경을 사용하고 싶지 않기 때문에layout에 배경을 덧붙여서 다중 배경을 그립니다.
    물론 테마를 사용자 정의해서 theme의 window background를 레이아웃에 설정하지 않고 원하는 것으로 설정할 수도 있습니다.
    다음과 같은 방식으로 윈도우의 배경을 제거할 수 있습니다.
    테마 설정:
    @null

    또는 코드 설정, onCreate에서 다음을 수행합니다.
    getWindow().setBackgroundDrawable(null);

    지금 우리가 볼 수 있는 효과:
    이미 기본적으로 최적화 수준에 이르렀다.
    이상은 분석 방법과 사고방식을 제공하는 데 목적을 두고 있다.Overdraw의 주요 원인은 배경의 다중 그리기나 보이지 않는 View가 뒤에서 그리는 등이다. 그러나 이것만은 아니다.
    2.3 UI 스레드의 복잡한 연산
    위의 ANR 관련 분석에서 말했듯이 UI 스레드의 복잡한 연산은 UI가 응답하지 못하게 할 수 있다. 물론 더 많은 것은 UI 응답이 정체되고 끊기는 것이다.
    ANR이 생기는 것은 이미 끊기는 극치이다. 구체적인 분석은 ANR 최적화의 ANR에 대한 상세한 설명을 참조할 수 있다.
    연산 장애로 인한 카드에 대한 분석은 Traceview라는 도구를 사용할 수 있습니다.구체적인 Traceview의 소개와 실전 분석은 App 최적화가 당신의 App 시작 속도를 향상시키는 이론적 기반과 App 최적화가 당신의 App 시작 속도를 향상시키는 실례적인 도전을 참고할 수 있다.
    여기서 성능 분석 도구에서 언급한 StrictMode를 언급해야 합니다.
    2.3.1 StrictMode 사용
    StrictMode는 스레드나 VM을 기반으로 정책을 설정하는 데 사용되며, 정책 위반이 발견되면, 컨트롤러에서 경고를 출력하고, 트레이스 정보를 포함하여 응용 프로그램이 어디에 문제가 있는지 보여 줍니다.
    일반적으로 주 스레드의 디스크 읽기와 쓰기, 네트워크 접근 등 시간 소모 조작을 측정하는 데 쓰인다.
    Application 또는 Activity의 onCreate에서 StrictMode를 엽니다.
     public void onCreate() {
         if (BuildConfig.DEBUG) {
             //          
             StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                     .detectDiskReads()
                     .detectDiskWrites()
                     .detectNetwork()   // or .detectAll() for all detectable problems
                     .penaltyLog()
                     .build());
    
             //   VM     
             StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                     .detectLeakedSqlLiteObjects()
                     .detectLeakedClosableObjects()
                     .penaltyLog()
                     .penaltyDeath()
                     .build());
         }
         super.onCreate();
     }

    만약 당신의 라인에 문제가 생기면, 컨트롤러에 경고 출력이 있을 것입니다. 코드를 찾을 수 있습니다.상대적으로 간단하니, 여기서는 쓸데없는 말이 많지 않다.UI 스레드의 시간 소모 조작 방안을 해결하려면 ANR에서 언급한 스레드 모드를 참고하십시오.
    2.4 자주 사용하는 GC
    위에서 말한 것은 모두 처리상의 CPU, GPU와 관련된 것이다.실제 메모리 원인도 응용이 원활하지 않고 끊길 수 있다.
    이쯤 되면 그때 데스크톱에 맞췄던 3대 제품(CPU, 메모리, 모니터)이 생각난다.App 성능을 분석하는 것도 이 몇 가지인 것 같다.)
    왜 자주 GC가 끊긴다고 말합니까?간단히 말하면 GC 조작을 실행할 때 모든 라인의 모든 조작은 중단되고 GC 조작이 완성된 후에야 다른 조작이 계속 실행될 수 있기 때문에 프로그램이 GC를 빈번하게 하면 인터페이스가 끊길 수 있다.
    다음 내용은 Android Performance Patterns: Memory Churn and Performance.필요
    GC를 자주 사용하는 두 가지 이유가 있습니다.
  • 메모리 디더링(Memory Churn), 즉 대량의 대상이 만들어지고 짧은 시간 안에 방출된다.
  • 순식간에 대량의 대상이 발생하면 YoungGeneration의 메모리 구역을 심각하게 차지하고 밸브값에 도달하고 남은 공간이 부족할 때 GC를 촉발한다.매번 분배된 대상이 적은 메모리를 차지해야 하지만, 그들이 겹치면 Heap의 압력을 증가시켜 더 많은 GC를 촉발할 수 있다.

  • 이러한 GC 작업으로 인해 위에서 언급한 프레임 손실이 다음과 같이 발생할 수 있습니다.
    사용자로 하여금 렉이 걸리는 것을 느끼게 할 것이다.
    일반적으로 순식간에 대량의 대상이 생기는 것은 코드의 순환 중 new 대상이나 onDraw에서 대상을 만들기 때문이다.그러니까 이런 부분은 저희가 특히 주의해야 할 부분인데...
    메모리에 대한 분석에 관해서 우리는 후속적인 메모리 최적화에서 자세하게 이야기합시다.

    좋은 웹페이지 즐겨찾기