이 블로그 포스트에서는 Qt QML 클러스터 애플리케이션이 어떻게 최적화 되었는지를 설명 할 것입니다.

Qt World Summit 2015에 실린 최초의 데모는 PC 환경에서 설계되었으며 시작 시간은 초기 디자인으로 해결되지 않았습니다. UI의 일부분이 비동기 적으로 로드되지만 시작 시퀀스가 전혀 고려되지 않도록 Loaders 를 사용하여 통합했습니다. 부팅을 위한 최적화를 시작하기 위해 먼저 Use Case 를 떠올렸습니다. 사용자가 가장 먼저 보는 화면은 무엇일까요? 우리는 먼저 사용자가 먼저 보는것은 클러스터의 프레임이라는 것을 확인했습니다. 그런 다음 나머지 객체를 화면에 로드하고 애니메이션을 적용합니다.

아래의 클러스터 이미지에서 빨간색 오버레이는 응용 프로그램이 시작될 때 사용자가 확인해야하는 부분을 표시합니다.

mask_layer_red

 

애플리케이션 코드를 살펴보면 대시 보드는 실제로 여러 개의 다른 마스크 이미지의 조합이고, 일부는 전체 화면입니다. 그래서 우리는 보이는 모든 부분을 하나의 전체 화면 이미지로 결합하여 UI 위에 다시 로드합니다.

DashboardFrameSport-mask

 

가능한 한 빨리 응용 프로그램을 시작하기 위해 응용 프로그램의 내부 디자인도 조정했습니다. 우리는 대시 보드 프레임에서 첫 번째로 로드 되는 항목을 자체 QML 파일로 분리했습니다. 클러스터 프레임이 로드되고 그려진 후에 우리는 그  밑단의 Loader 가 나머지 UI를 로드 할 수있게합니다.

frame_qml2

 

또한 Qt Creator의 QML 프로파일러를 사용하여 시간을 확인했습니다. 처음 데모에서는 데스크탑 용으로 설계된 원래의 Qt Quick Controls를 사용했습니다. 이때 게이지를 만들때 얼마간의 시간이 소비됐습니다. (Qt Quick Controls는 Qt 5.7의 임베디드 Use Case 를 위해 새롭게 디자인되었습니다!) 이 부분을 해결하기 위해 우리는 게이지를 이미지로 대체하고 애니메이션이 필요한 게이지의 컬러 부분을 프레그먼트 쉐이더(fragment shader) 로 만들었습니다. 

마지막 작업으로 플립 애니메이션을 게이지에 추가하고 시동 화면이 자연스러워 지도록 애니메이션을 페이드 인합니다.:

 

이러한 최적화가 끝나면 Qt 응용 프로그램의 대상 장치에서 300밀리 초 미만에 첫번째 프레임을 표시하게 되니다. (운영 체제 커널이 로드 된 시점 이후부터)

 

응용 프로그램 최적화 방법 : ‘Do’ 와 ‘Do not!”

마지막으로, 우리의 경험을 토대로 Qt Quick 어플리케이션을 최적화하기 위한 팁을 요약 해 놓았습니다.

 

해야 할 것(Do):

> 응용 프로그램이 처음부터 빨리 시작되도록 디자인하십시오. 사용자가 가장 먼저 보길 원하는 것이 무엇인지 생각하십시오.
> 병렬 로딩(Parallel Loading)을 허용하는 시작 애니메이션을 만듭니다.
> 체인 로딩(Chain Loading) 을 사용합니다. CPU 코어의 개수만큼 많은 로더를 실행하십시오 (예 : 2 개의 코어 : 동시에 실행되는 2 개의 로더).
> 첫 번째 로더는 비동기가 아니어야하며 그 후 나머지 로더를 트리거하십시오.
> 필요한 경우 로드되는 QML 플러그인을 작성하십시오.
> 필요한 경우에만 백엔드 서비스에 연결하십시오.
> QML 플러그인은 중요하지 않은 일반적인 서비스에서 시작하고 더 이상 필요하지 않을 때 종료합니다.
> png / jpg 이미지를 최적화하십시오.
> 버텍스(Vertices)의 양을 줄이고 보이지 않는 부분을 제거하여 3D 모델을 최적화하십시오.
> glTF를 사용하여 3D 모델 로딩을 최적화하십시오.
> Qt Quick Controls 2.0을 사용하십시오. 이것는 임베디드 용도로 설계되었으며 임베디드 용도의 경우 Quick Controls 1.0보다 생성 시간이 훨씬 짧습니다.
> Clip 및 불투명도의 사용을 제한하십시오.
> GPU Limit 을 측정하고 UI를 디자인 할 때 고려해야합니다.
> Qt Quick Compiler 를 사용하여 QML 파일을 미리 컴파일하십시오.
> 아키텍처에서 정적 링킹이 가능한지 여부를 조사하십시오.
> 명령적(Imperative) 신호 처리기 대신 선언적(Declarative) 바인딩을 사용하십시오.
> 속성(Property) 바인딩을 간단하게 설정합니다. 일반적으로 QML 코드는 간단하고 읽기 쉽도록 작성하십시요. 그러므로 더 높은 성능을 발휘합니다.
> 여러 플랫폼 및 폼 팩터를 대상으로 할 때는 로더 및 동적 구성 요소 인스턴스화 대신 파일 선택기를 사용하십시오. 맞춤형 버전을 로드 하지 말고 간단한 QML 코드를 “복제”하고 파일 선택기를 사용하십시요.

 

하지 말아야 할 것(Do not):

> QML 에 의존하세요. 모든 코드를 QML 로 작성할 필요는 없습니다.
> main.cpp 의 모든 것을 초기화하십시오.
> 모든 필수 인터페이스가 포함 된 싱글 톤(Singletons) 을 만듭니다.
> Listviews 에 대한 복잡한 대리자(delegates) 를 만듭니다.
> 임베디드를 위해 Qt Quick Controls 1.0을 사용하십시오.
> 가능한 클립(Clip)을 피해야합니다. (Use Case의 98 %가 가능해야 합니다.)
> 로더를 과용하는 일반적인 함정에 빠지십시오. Loader는 응용 프로그램 페이지와 같은 큰 항목을 로드하는 데 적합하지만 간단한 작업을 로드하는 데 너무 많은 오버 헤드가 발생합니다. 그것은 모든 것을 가속화하는 전지전능한 기술이 아닙니다. 여분의 QML 컨텍스트가 있는 추가 항목일 뿐입니다.
> 과도하게 코드를 재사용 하세요. 코드 빈번한 재사용은 바인딩 수와 복잡성을 줄이고 성능을 저하시킵니다.

 

다음 글에서는 부팅 시작 최적화 중 운영 체제에 대해 자세히 살펴볼 것입니다.

본 문서는 qt.io 의 “Fast-Booting Qt Devices, Part 2: Optimizing Qt Application” 을 번역한 블로그 입니다.