LIFULL Creators Blog

LIFULL Creators Blogとは、株式会社LIFULLの社員が記事を共有するブログです。自分の役立つ経験や知識を広めることで世界をもっとFULLにしていきます。

AndroidStudio でのメモリ解析 便利だった機能の話

こんにちは。菊地です。

前回の記事(Android Studio でのメモリ解析の方法 - 株式会社ネクスト エンジニアBlog)で、AndroidStudioにおけるメモリ解析についてまとめましたが、今回はその補足のような記事になります。

AndroidStudio でメモリ関連の調査を行う際に便利だなと思った機能がありましたので、そちらのご紹介になります。

今回は AndroidStudio (Android DDMSかもしれませんが)にある

  • Graphics Acceleration の情報を確認するための Graphics States
  • ActivityManagerの状態を確認するための Activity Manager State

という2つの機能について記事にさせていただきます。

※ここからは、サンプルとして Navigation Drawer Activity を新規プロジェクトとして作成しています

Graphics State

どうやって使うの?

AndroidStudio > Android DDMS で左側のウィンドウに表示されているパッケージ名から調べたいパッケージ名を指定します。 パッケージを指定したあと Android DDMS > System Information > Graphics States で使えます

何がみれるの?

Graphics State という名前のとおり、現在のアプリにおける描画の状態が確認できます

  • どのような描画命令が行われたのか?
  • 描画時に使われたメモリ量(現在/最大)
  • 描画されたViewの数、メモリおよび描画フレーム数
Applications Graphics Acceleration Info:
Uptime: 610094 Realtime: 610094

** Graphics info for pid 2096 [jp.nextgroup.myapplication] **

Recent DisplayList operations

どのような描画命令が行われたかを一覧で見ることができます

Recent DisplayList operations
  DrawDisplayList
  DrawPatch
DrawRect
DrawRect
DrawRect
DrawPatch
DrawPatch
SetupShader
DrawRect
ResetShader
DrawDisplayList
  DrawDisplayList
    DrawDisplayList
      Save
      ClipRect
      DrawDisplayList
        DrawDisplayList
      RestoreToCount
      DrawRect
      Save
      DrawDisplayList
        DrawRect
        DrawDisplayList
          DrawPatch
          Save
          ClipRect
          Translate
          DrawText
          RestoreToCount
        DrawDisplayList
          Save
          ClipRect
          Translate
          DrawText
          RestoreToCount
        DrawDisplayList
          Save
          ClipRect
          Translate
          DrawText
          RestoreToCount
      RestoreToCount
      DrawPatch
  DrawDisplayList
  DrawPatch
DrawRect
DrawRect
DrawRect
DrawPatch
DrawPatch

Caches

描画命令における

  • 現在のメモリ使用量
  • 描画に使用された合計メモリ量

を確認することができます

Caches:
Current memory usage / total memory usage (bytes):
  TextureCache           167952 / 25165824
  LayerCache                  0 / 16777216
  RenderBufferCache           0 /  2097152
  GradientCache               0 /   524288
  PathCache                   0 / 10485760
  TextDropShadowCache         0 /  2097152
  PatchCache               1472 /   131072
  FontRenderer 0 A8      524288 /   524288
  FontRenderer 0 RGBA         0 /        0
  FontRenderer 0 total   524288 /   524288
Other:
  FboCache                    0 /       16
Total memory usage:
  693712 bytes, 0.66 MB

View Hierarchy

Viewの描画に関する

  • 描画されたViewの数
  • Viewの描画に使われているメモリ使用量
  • Viewの描画にかかったフレーム数

といった情報を見ることができます

Profile data in ms:

    jp.nextgroup.myapplication/jp.nextgroup.myapplication.MyActivity/android.view.ViewRootImpl@52876bc0
View hierarchy:

  jp.nextgroup.myapplication/jp.nextgroup.myapplication.MyActivity/android.view.ViewRootImpl@52876bc0
  24 views, 2.55 kB of display lists, 19 frames rendered


Total ViewRootImpl: 1
Total Views:        24
Total DisplayList:  2.55 kB

Activity Manager State

どうやって使うの?

AndroidStudio > Android DDMS で左側のウィンドウに表示されているパッケージ名から調べたいパッケージ名を指定します。 パッケージを指定したあと Android DDMS > System Information > Graphics States で使えます

何が見れるの?

現在のアプリにおける ActivityManagerの状態を見る事が出来ます

  • Activity の情報
  • Activity に Attach されている Fragment
  • Fragment の情報
  • Viewの階層構造

などなど

Fragmentの状態なども視覚的に確認することができ、Fragmentが破棄されているのかどうか?といったことも確認することができて、とても便利でした。

TASK jp.nextgroup.myapplication id=4
  ACTIVITY jp.nextgroup.myapplication/.MyActivity 52a1a528 pid=2096
    Local Activity 52852ee4 State:
      mResumed=true mStopped=false mFinished=false
      mLoadersStarted=true
      mChangingConfigurations=false
      mCurrentConfig={1.0 ?mcc?mnc en_US ldltr sw360dp w360dp h567dp 480dpi nrml port finger qwerty/v/v dpad/v s.5}
    Active Fragments in 52852f64:
      #0: NavigationDrawerFragment{5287b3b8 #0 id=0x7f080002}
        mFragmentId=#7f080002 mContainerId=#7f080000 mTag=null
        mState=5 mIndex=0 mWho=android:fragment:0 mBackStackNesting=0
        mAdded=true mRemoving=false mResumed=true mFromLayout=true mInLayout=true
        mHidden=false mDetached=false mMenuVisible=true mHasMenu=true
        mRetainInstance=false mRetaining=false mUserVisibleHint=true
        mFragmentManager=FragmentManager{52852f64 in MyActivity{52852ee4}}
        mActivity=jp.nextgroup.myapplication.MyActivity@52852ee4
        mView=android.widget.ListView{528798c8 VFED.VC. ........ 0,0-720,1557 #7f080002 app:id/navigation_drawer}
      #1: PlaceholderFragment{52862068 #1 id=0x7f080001}
        mFragmentId=#7f080001 mContainerId=#7f080001 mTag=null
        mState=5 mIndex=1 mWho=android:fragment:1 mBackStackNesting=0
        mAdded=true mRemoving=false mResumed=true mFromLayout=false mInLayout=false
        mHidden=false mDetached=false mMenuVisible=true mHasMenu=false
        mRetainInstance=false mRetaining=false mUserVisibleHint=true
        mFragmentManager=FragmentManager{52852f64 in MyActivity{52852ee4}}
        mActivity=jp.nextgroup.myapplication.MyActivity@52852ee4
        mArguments=Bundle[{section_number=1}]
        mContainer=android.widget.FrameLayout{5287ad2c V.E..... ........ 0,0-1080,1557 #7f080001 app:id/container}
        mView=android.widget.RelativeLayout{5285b990 V.E..... ........ 0,0-1080,1557}
    Added Fragments:
      #0: NavigationDrawerFragment{5287b3b8 #0 id=0x7f080002}
      #1: PlaceholderFragment{52862068 #1 id=0x7f080001}
    Fragments Created Menus:
      #0: NavigationDrawerFragment{5287b3b8 #0 id=0x7f080002}
    FragmentManager misc state:
      mActivity=jp.nextgroup.myapplication.MyActivity@52852ee4
      mContainer=android.app.Activity$1@52852fa0
      mCurState=5 mStateSaved=false mDestroyed=false
    ViewRoot:
      mAdded=true mRemoved=false
      mConsumeBatchedInputScheduled=false
      mPendingInputEventCount=0
      mProcessInputEventsScheduled=false
      mTraversalScheduled=false
      android.view.ViewRootImpl$NativePreImeInputStage: mQueueLength=0
      android.view.ViewRootImpl$ImeInputStage: mQueueLength=0
      android.view.ViewRootImpl$NativePostImeInputStage: mQueueLength=0
    Choreographer:
      mFrameScheduled=false
      mLastFrameTime=592749 (15996 ms ago)
    View Hierarchy:
      com.android.internal.policy.impl.PhoneWindow$DecorView{52853760 V.E..... R....... 0,0-1080,1776}
        com.android.internal.widget.ActionBarOverlayLayout{52853f34 V.ED.... ........ 0,0-1080,1776 #1020313 android:id/action_bar_overlay_layout}
          android.widget.FrameLayout{52855914 V.E..... ........ 0,219-1080,1776 #1020002 android:id/content}
            android.support.v4.widget.DrawerLayout{528758b8 VFE..... .F...... 0,0-1080,1557 #7f080000 app:id/drawer_layout}
              android.widget.FrameLayout{5287ad2c V.E..... ........ 0,0-1080,1557 #7f080001 app:id/container}
                android.widget.RelativeLayout{5285b990 V.E..... ........ 0,0-1080,1557}
                  android.widget.TextView{52875bc0 V.ED.... ......ID 48,48-48,105 #7f080003 app:id/section_label}
              android.widget.ListView{528798c8 VFED.VC. ........ 0,0-720,1557 #7f080002 app:id/navigation_drawer}
                android.widget.TextView{52852058 V.ED.... .....A.. 0,0-720,144 #1020014 android:id/text1}
                android.widget.TextView{52876384 V.ED.... ........ 0,143-720,287 #1020014 android:id/text1}
                android.widget.TextView{528794ac V.ED.... ........ 0,286-720,430 #1020014 android:id/text1}
          com.android.internal.widget.ActionBarContainer{52855b94 V.ED.... ........ 0,75-1080,219 #1020314 android:id/action_bar_container}
            com.android.internal.widget.ActionBarView{5285b218 V.E..... ........ 0,0-1080,144 #1020315 android:id/action_bar}
              android.widget.LinearLayout{5285b5b0 VFE...C. ........ 0,0-531,144}
                com.android.internal.widget.ActionBarView$HomeView{5285fb5c V.E..... ........ 0,0-145,144}
                  android.widget.ImageView{5285fdb4 V.ED.... ........ 0,48-48,96 #102025a android:id/up}
                  android.widget.ImageView{528614a4 V.ED.... ........ 37,24-133,120 #102002c android:id/home}
                android.widget.LinearLayout{52861ee4 V.E..... ........ 145,35-531,108}
                  android.widget.TextView{52862120 V.ED.... ........ 0,0-362,73 #1020265 android:id/action_bar_title}
                  android.widget.TextView{52862790 G.ED.... ......I. 0,0-0,0 #1020266 android:id/action_bar_subtitle}
              com.android.internal.view.menu.ActionMenuView{5284cd88 V.ED.... ........ 912,0-1080,144}
                com.android.internal.view.menu.ActionMenuPresenter$OverflowMenuButton{52848a78 VFED..C. ........ 0,0-168,144}
            com.android.internal.widget.ActionBarContextView{52862afc G.E..... ......ID 0,0-0,0 #1020316 android:id/action_context_bar}
          com.android.internal.widget.ActionBarContainer{528680e8 G.ED.... ......ID 0,0-0,0 #1020317 android:id/split_action_bar}
    Looper (main, tid 1) {5284fff0}
      (Total messages: 0, idling=false, quitting=false)

まとめ

Graphics Manager は描画命令を視覚的に確認できるほか、メモリ使用量のほか描画にかかったフレームなども見る事ができます。 そのため、 描画が遅い? と思ったときや、 なんか重くなった! 描画重い!? と嘆く前にこれを使い、実際にどういったことが行われて、どの程度の時間がかかっているのかを確認することで、少しでも操作を快適にできるかもしれません。

Activity Manager State もライフサイクルが複雑なFragmentについて、実際の状態を確認することができますし、実は裏でFragmentが生き残っていた!!なんてことも防げるようになると思います。

こういったツールも使いながら少しでもいいアプリを提供できるようにしていけたらと思います。