Drawit 메모리 최적화



안드로이드 메모리 모델은 Honeycomb(Android 3.0) 미만의 메모리 모델과 Honeycomb(Android 3.0) 이상의 메모리 모델로 나뉩니다. 저는 Oreo(Android 8.0)을 기준으로 앱을 개발했습니다.

프로세스는 메모리를 가질 수 있는 limit이 정해져 있습니다. 이와 같이 프로세스당 메모리를 애플리케이션 메모리라고 합니다. 이 메모리는 단말기마다 다릅니다. 화면이 커질수록 화면을 꽉채우기 위해 앱 메모리가 증가합니다. 현재 앱 메모리는 24MB, 32MB, 48MB, 64MB 등 다양하다고 합니다.

Drawit 앱은 비트맵 관련 이슈 2가지를 가지고 있습니다.

1. 총 그림을 그릴 수 있는 갯수

그림의 크기는 1280*720(Youtube, Instagram, Facebook용), 720*720(Instagram용), 504*304(Tumblr용), 504*404(Tumblr용)로 총 4가지 사이즈를 선택할 수 있습니다.

한 이미지의 크기는 얼마인가 계산해봅시다. 기준은 가장 큰 1280*720로 계산해보겠습니다.
한 픽셀은 R, G, B, alpha로 4개의 색을 가지고 있습니다. 하나의 색은 0~255까지 나타낼 수 있고 8bit로 생성할 수 있습니다. 즉  하나의 색은 1byte크기입니다. 한 픽셀은 4byte를 차지하고 한 그림당 1280*720*4byte=3686400 byte=3686.4KB=3.7MB를 차지합니다. 즉 제가 개발한 앱은 최대 3.7*9MB=33MB를 소모합니다.
이것은 앱 메모리를 초과하여 OOM을 발생시킵니다. 즉 단말기의 앱 메모리가 작으면 그릴 수 있는 그림 갯수가 줄어듭니다.

프로세스당 메모리 크기의 한계를 알고 싶다면 다음 API를 사용할 수 있습니다.

  • ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();


2. 사진을 업로드할 수 있는 크기

사용자는 어떤 크기의 사진을 업로드할 지 알 수 없습니다. 만약 고해상도의 이미지를 업로드하면 OOM이 발생합니다. 그래서 업로드 하기 전, 사진의 크기를 계산해서, 해상도를 줄인 후 업로드 합니다.

1) 비트맵을 객체에 넣기 전에, 크기를 구하고자 합니다.
  • Uri uri=getIntent().getData();
  • ContentResolver cr=getBaseContext().getContentResolver();
  • InputStream inputStream=cr.openInputStrea(uri);
  • BitmapFactory.Options options=new BitmapFactory.Options();


2) 비트맵을 디코딩할 때 크기만 불러옵니다.
  • options.inJustDecodeBounds=true;
  • BitmapFactory.decodeStream(inputStream,null,options);
  • options.inSampleSize=GetImage.calculateInSampleSize(options,this);


3) inSampleSize가 정해졌으므로 비트맵을 불러올 수 있습니다. 
  • options.inJustDecodeBounds=false;
  • InputStream inputStream=cr.openInputStrea(uri);
  • Bitmap bitmap=BitmapFactory.decodeStream(otherInputStream,null,options);


참고사이트





댓글

이 블로그의 인기 게시물

포트란?

안드로이드 스마트폰 연결