Android 15 Support Memory Page 16KB 대응

David·2025년 9월 30일
0

대응을 하게 된 이유

저는 펫나우라는 앱을 운영하기도 하지만
동시에 Petnow SDK도 운영을 하고 있습니다.

그런데 저희 SDK를 이용하는 클라이언트에서 앱 업데이트 중 16KB page 메시지를 마주했습니다.
이에 대응하려다 보니 우리 SDK가 지원하지 않는 것 같다며 슬랙으로 문의를 주셨습니다.

우리측에서도 역시 앱을 운영하고 있다보니 위 정책을 확인했으나
11월까지 기간이 남았기에 다른 우선순위 작업을 진행하고 있었습니다만.. 🥲
아래처럼 보내주셔서 대응을 하기로 결심했습니다.

어떻게 대응했는지를 공유하기 앞서
해당 영상을 보고 개념 및 필요성에 대해
알아본 것을 먼저 정리했습니다.

🤔 왜 안드로이드는 Memory Page 16KB를 지원하는가

현대의 애플리케이션들은 예전에 비해 요구하는 기능도 복잡해지고
게임, 영상 등 고성능 고용량 애플리케이션이 증가하고 있습니다.
그러다보니 업데이트 이전에는 4KB page 로 TLB MMU 메모리 주소 변환을 요청하고

이는 TLB 의 Thrash 문제
(TLB 자주 무효화되고 사용해야 할 페이지가 dropping 및 filling 빈번하게 발생하여
페이지 테이블이 자주 교체되어 효율성 및 성능 저하)가
발생했습니다.

이에 안드로이드는 Memory Page 4KB -> 16KB(4배) 늘려
CPU가 애플리케이션 작업에 더욱 집중할 수 있도록 정책을 만들었습니다.


✅ 용어 정리

📌 메모리 페이지

  • 어떤 메모리가 어떤 애플리케이션에 속하는지 알 수 있음
  • 해당 애플리케이션이 메모리에서 무엇을 할 수 있는지 추적
  • 애플리케이션이 운영체제에 읽기/쓰기 및 실행 권한이 있는 페이지를 요청
  • 페이지 크기가 클 수록 요청해야 할 내용이 줄어듬

📌 TLB, MMU

우리가 안드로이드에서 사용하는 애플리케이션 사용 시
CPU는 아래와 같은 구조로 가상 주소를 물리 메모리 주소로 변환을 TLB와 MMU에 위임하여 다른 로직에 집중

TLB

  • 가상 주소 변환 캐시 hit / missing

MMU

  • 메모리 주소 변환 및 조회 관리

📌 ELF (Executable and Linakable Format)

우리가 만든 어플리케이션 파일 안에 c/c++ 코드,
✌🏻네이티브 라이브러리가 컴파일된✌🏻
"실행 가능한 파일"


👨🏻‍💻 16KB 대응

우리 프레임워크에서는 외부 라이브러리도 사용하기 때문에
외부 라이브러리 역시 16KB 대응이 되어야 합니다.

따라서 외부 라이브러리 업데이트를 먼저 진행하고
우리 프레임워크도 지원을 해주는 방향으로 진행합니다.

🚀 OpenCV 업데이트 진행

우선 OpenCV 측에서 이미 Issue가 올라와있고
이를 추적 해보면 업데이트 시 해결되는 것을 확인 했습니다.

업데이트 방법은
✅ curl 을 이용하여 opencv-4.12.0 버전을 다운 후 sha256 값 계산
✅ 계산된 값을 OpenCV.cmake 에 반영
✅ 캐시 지우고 해당 모듈 빌드
✅ libs.versions.toml에 openCV 버전 위와 같이 동일하게 변경

curl -L -o /Users/gimhyeong-geun/Downloads/opencv-4.12.0-android-sdk.zip \
  https://github.com/opencv/opencv/releases/download/4.12.0/opencv-4.12.0-android-sdk.zip
  
  • -L: 리다이렉트(302/301)를 자동으로 따라감. GitHub 릴리스 URL은 종종 리다이렉트라서 꼭 필요.
  • -o <파일경로>: 다운로드 결과를 지정한 경로/파일명으로 저장.
shasum -a 256 /Users/gimhyeong-geun/Downloads/opencv-4.12.0-android-sdk.zip

src>jni>cmake>OpenCV.cmake

FetchContent_Declare(
        OpenCV
        URL https://github.com/opencv/opencv/releases/download/4.12.0/opencv-4.12.0-android-sdk.zip
        URL_HASH SHA256=위에서 계산된 값
)

🚀 우리 모듈 업데이트 진행

  • 빌드 시 특정 버전 이상을 지원하면 16KB 지원이 자동으로 되는데 만약 호환성 등의 이유로 하위 버전으로 빌드를 해야 한다면 공식 문서에서 안내하는 옵션을 설정하면 된다.
  • 저는 심플하게 ndk 를 최신 버전으로 지원하게 변경했습니다.
plugins {
    ...
}

android {
    ndkVersion = "28.0.13004108" // 📌 here
    defaultConfig {
        ...
    }

  	...
}

dependencies {

    // OpenCV
    implementation(libs.opencv)
}

👀 16KB 확인 방법

구글 공식 문서를 보면 개발자가 확인할 수 있는 스크립트를 올렸는데
해당 스크립트를 돌리는 것으로 확인했습니다.


=== APK zip-alignment ===
12058624 lib/arm64-v8a/libc++_shared.so (OK)
13352960 lib/arm64-v8a/libopencv_java4.so (OK)
36831232 lib/arm64-v8a/libpetCameraNative.so (OK)
46776320 lib/arm64-v8a/libtensorflowlite_gpu_jni.so (OK)
49283072 lib/arm64-v8a/libtensorflowlite_jni.so (OK)
156663808 lib/x86_64/libc++_shared.so (OK)
157925376 lib/x86_64/libopencv_java4.so (OK)
213762048 lib/x86_64/libpetCameraNative.so (OK)
250855424 lib/x86_64/libtensorflowlite_gpu_jni.so (OK)
253509632 lib/x86_64/libtensorflowlite_jni.so (OK)
Verification succesful
=========================

=== ELF alignment ===
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/armeabi-v7a/libtensorflowlite_gpu_jni.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/armeabi-v7a/libopencv_java4.so: \e[31mUNALIGNED\e[0m (2**12)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/armeabi-v7a/libc++_shared.so: \e[31mUNALIGNED\e[0m (2**12)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/armeabi-v7a/libtensorflowlite_jni.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/armeabi-v7a/libpetCameraNative.so: \e[31mUNALIGNED\e[0m (2**12)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/x86/libtensorflowlite_gpu_jni.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/x86/libopencv_java4.so: \e[31mUNALIGNED\e[0m (2**12)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/x86/libc++_shared.so: \e[31mUNALIGNED\e[0m (2**12)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/x86/libtensorflowlite_jni.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/x86/libpetCameraNative.so: \e[31mUNALIGNED\e[0m (2**12)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/arm64-v8a/libtensorflowlite_gpu_jni.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/arm64-v8a/libopencv_java4.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/arm64-v8a/libc++_shared.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/arm64-v8a/libtensorflowlite_jni.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/arm64-v8a/libpetCameraNative.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/x86_64/libtensorflowlite_gpu_jni.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/x86_64/libopencv_java4.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/x86_64/libc++_shared.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/x86_64/libtensorflowlite_jni.so: \e[32mALIGNED\e[0m (2**14)
/var/folders/7h/4254qtds6dd0pylpsl15lx700000gn/T/testapp-release-unsigned_out_XXXXX.9xnhOU43/lib/x86_64/libpetCameraNative.so: \e[32mALIGNED\e[0m (2**14)
\e[31mFound 6 unaligned libs (only arm64-v8a/x86_64 libs need to be aligned).\e[0m
=====================

참고 사항

https://ko.wikipedia.org/wiki/%EB%A9%94%EB%AA%A8%EB%A6%AC_%EA%B4%80%EB%A6%AC_%EC%9E%A5%EC%B9%98

https://youtu.be/MnMGJhuChRI?si=CIFqsFUkTQigD68i

https://developer.android.com/guide/practices/page-sizes?hl=en

profile
공부하는 개발자

0개의 댓글