简体   繁体   English

如何衡量Android应用数据大小并识别存储泄漏?

[英]How to measure Android app data size and identify storage leaks?

I made a small Android app and have been using it for a while now. 我制作了一个小型Android应用程序并且已经使用了一段时间了。 I noticed that, in the settings, on the "data" line of my app's characteristics (I am not interested in analysing the amount shown on the "application" line nor on the "cache" line), it shows about 20 MB, which seemed a lot to me. 我注意到,在设置中,我应用程序特征的“数据”行(我对分析“应用程序”行和“缓存”行上显示的数量不感兴趣),它显示大约20 MB,其中对我来说似乎很重要。 I am afraid the app has storage leaks (ie that it produces data that is never erased). 我担心应用程序存在泄漏(即它产生的数据永远不会被删除)。

I decided to investigate and measure what might take that much space. 我决定调查和衡量可能占用那么多空间的东西。 I use pretty much all the available storage options for this app: SQLite DB, internal files, external files, shared preferences (and cache files including Glide picture loading). 我几乎使用了这个应用程序的所有可用存储选项 :SQLite DB,内部文件,外部文件,共享首选项(以及包括Glide图片加载的缓存文件)。

So far, thanks to a question on SQLite DB , I found that my DB file takes about 500 kB. 到目前为止,由于有关SQLite DB的问题 ,我发现我的DB文件大约需要500 kB。 I found by scanning recursively the files and folders in the folder getFilesDir() that I use 10 kB of data in internal and app-private external files. 我通过递归扫描文件和文件夹getFilesDir()了我在内部和app私有外部文件中使用10 kB数据。 I have not analysed Shared Preferences size yet, but I store less than 20 key/value pairs. 我还没有分析共享首选项大小,但我存储少于20个键/值对。

Exploring the folder getCacheDirs() I also found that Glide uses about 3 MB of cache (close to what the Android settings app tells). 探索文件夹getCacheDirs()我还发现Glide使用大约3 MB的缓存(接近Android设置应用程序所说的)。

My question is, which leads did I miss to find where this 19.5 MB of data I cannot locate? 我的问题是,哪些导致我错过了找到这个19.5 MB的数据我找不到的位置? Did I forget some kind of storage that might take space? 我忘记了某种可能占用空间的存储空间吗? And, more generally, are there tools to analyse storage leaks (ie data produced by the app that might never be erased)? 而且,更一般地说,是否有工具来分析存储泄漏(即应用程序产生的数据可能永远不会被删除)?

Following @James suggestion, I started exploring the different folders, and after discussing the issue with a colleague and trying to explore many folders, I finally found that most of the data came from the cache of a former Webview I had. 按照@James的建议,我开始探索不同的文件夹,在与同事讨论问题并尝试探索许多文件夹后,我终于发现大部分数据来自我以前的Webview的缓存。 I am posting all my investigation, hopefully it will help. 我发布了所有的调查,希望它会有所帮助。

I executed the following code when the app starts, calling analyseStorage(this) from my main activity: 当应用程序启动时,我执行了以下代码,从我的主要活动中调用analyseStorage(this)

public void analyseStorage(Context context) {
  File appBaseFolder = context.getFilesDir().getParentFile();
  long totalSize = browseFiles(appBaseFolder);
  Log.d(STORAGE_TAG, "App uses " + totalSize + " total bytes");
}

private long browseFiles(File dir) {
  long dirSize = 0;
  for (File f: dir.listFiles()) {
    dirSize += f.length();
    Log.d(STORAGE_TAG, dir.getAbsolutePath() + "/" + f.getName() + " uses " + f.length() + " bytes");
    if (f.isDirectory()) {
      dirSize += browseFiles(f);
    }
  }
  Log.d(STORAGE_TAG, dir.getAbsolutePath() + " uses " + dirSize + " bytes");
  return dirSize;
}

What is important is to scan specifically context.getFilesDir().getParentFile() which matches the folder /data/data/my.app.package/ 重要的是要专门扫描context.getFilesDir().getParentFile() ,它匹配文件夹/data/data/my.app.package/

After executing that code, I had the following logs: 执行该代码后,我有以下日志:

D/storage﹕ /data/data/my.app.package/lib uses 0 bytes
D/storage﹕ /data/data/my.app.package/cache uses 3371773 bytes
D/storage﹕ /data/data/my.app.package/databases uses 483960 bytes
D/storage﹕ /data/data/my.app.package/shared_prefs uses 604 bytes
D/storage﹕ /data/data/my.app.package/app_webview uses 9139469 bytes
D/storage﹕ /data/data/my.app.package/files uses 7723 bytes
D/storage﹕ /data/data/my.app.package/app_ACRA-approved uses 0 bytes
D/storage﹕ /data/data/my.app.package/app_ACRA-unapproved uses 0 bytes
D/storage﹕ App uses 13003529 total bytes

What I could see is: 我能看到的是:

  • The cache, used only by Glide for picture loading, takes 3MB 仅由Glide用于图片加载的缓存需要3MB
  • The SQLite database takes 500kB SQLite数据库需要500kB
  • The shared preferences take 600B 共享首选项需要600B
  • The cache for all the Webviews I used to have still takes 9MB 我以前所有Webview的缓存仍然需要9MB
  • The rest of the files, under files and other folders, is mostly used by ACRA for bug tracking and take 10kB files和其他文件夹下的其余文件主要由ACRA用于跟踪错误并占用10kB

In the end, I finally discovered that most of my data went to Webview cache, actually not stored explicitly as cache. 最后,我终于发现我的大部分数据都转到了Webview缓存,实际上并没有明确存储为缓存。 I deleted these files and it actually reduced the size of my app by 20MB, even more than listed above. 我删除了这些文件,它实际上减少了我的应用程序的大小20MB,甚至超过上面列出的。 I now know what order of magnitude my app's data takes. 我现在知道我的应用程序数据的数量级。

There is no storage leaks. 没有存储泄漏。

You didn't count odex (dalvik) or oat (android runtime) file in. They are usually located at 你没有计算odex (dalvik)或oat (android运行时)文件。它们通常位于

/data/dalvik-cache/xxx.odex
/data/dalvik-cache/<target-architecture>/xxx.oat

These files are generated by system for optimization during installing time. 这些文件由系统生成,以便在安装期间进行优化。

Also you didn't count your APK file in which located at 你也没有计算你所在的APK文件

/data/app/xxx.yyy.zzz.apk

The directories or files are not accessible from adb shell if the device is not rooted. 如果设备未植根,则无法从adb shell访问目录或文件。

I think the storage usage show at settings include the following three parts 我认为设置中的存储使用情况包括以下三个部分

/data/data/xxx.yyy.zzz
/data/app/xxx.yyy.zzz.apk
odex or oat file

So the storage size you counted under /data/data/xxx.yyy.zzz is always less than the total size in settings. 因此,您在/data/data/xxx.yyy.zzz下计算的存储空间大小始终小于设置中的总大小。

You can use MAT TOOL for optimizing memory/size issues in your app.It displays which part in your app using more memory. 您可以使用MAT TOOL优化应用程序中的内存/大小问题。它会使用更多内存显示应用程序中的哪个部分。

Run you app in Android-studio and Go to Tools->Android->AndroidDeviceMonitor ,run your scenario and in device monitor click to download your app .hprof file by follow the image I attached below Android-studio中运行您的应用程序并转到工具 - > Android-> AndroidDeviceMonitor ,运行您的方案并在设备监视器中单击以下载您的应用程序.hprof文件 ,请按照下面附带的图像 下载.hprof文件

After that you need to convert Android-studio .hprof file to Eclipse Mat supported .hprof file by using hprof-conv.exe inside sdk->platform-tools and follow the cmd in your CMD promt 之后,您需要使用sdk-> platform-tools中的 hprof-conv.exe将Android-studio .hprof文件转换为Eclipse Mat支持的.hprof文件,并按照CMD promt中的cmd进行操作

F:\Android_Studio_SDK\platform-tools>hprof-conv "C:\Users\Bala\Desktop\your_AS_file.hprof" "C:\Users\Bala\Desktop\MAT_File_Name.hprof"

And in MAT Tool go to File -> OpenHeapDump to open your .hprof file,It will show your app memory utilize by package,class,object..etc; 并在MAT工具中转到文件 - > OpenHeapDump打开你的.hprof文件,它将显示你的应用程序内存利用package,class,object..etc;

Some referral link for learn about MAT Tool 有关推荐MAT工具的推荐链接
link 1 链接1
link 2 链接2

You can use a library like Leak Canary to automatically detect all memory leaks inside your app: https://corner.squareup.com/2015/05/leak-canary.html 您可以使用Leak Canary这样的库来自动检测应用程序内的所有内存泄漏: https//corner.squareup.com/2015/05/leak-canary.html

You can also go to the DDMS in Android Studio and get more information of the storage in your app without coding anything. 您还可以访问Android Studio中的DDMS,并在不编码任何内容的情况下获取应用程序中存储的更多信息。 However, most of the leaks would be detected by Leak Canary. 但是,泄漏金丝雀会检测到大部分泄漏。

Hope it helps! 希望能帮助到你!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM