在實做取得 app icon 的時候發現記憶體使用率會飆高而且常常降不下來, 想說可能是 birmap 吃掉記憶體,所以在使用完 bitmap 後就用 recycle 來讓 GC 可以做記憶體回收,但是發現呼叫 recycle 之後再次要取得 app icon 時常常會出現 exception 說使用到已經 recycle 的 bitmap,就在想會不會是系統已經做了 app icon 的 cache,所以每次取到的 app icon 有可能是跟之前一樣的 object,這篇的說法也印證了我的猜想,系統的確會內部自己做 cache
既然不能 recycle bitmap,但記憶體又這麼高,該怎麼辦?這時發現 Android 有提供一個 LruCache 物件來做 cache,很適合 bitmap 使用,試著用用看,結果...在這樣系統跟我都做了 cache 的情況下,記憶體使用率真的變低了
為什麼兩邊都做 cache 反而記憶體會下降,我認為 Android 系統內部的 cache 機制大概有問題 ,既然系統已經內部有做 app icon 的 cache 了,應用程式端就不需要再自己做 cache 才對,cache 的使用效能與記憶體管理系統自己要注意,而不是讓應用程式來煩惱,那還不如你系統就不要做 cache,這樣我記憶體使用率可以再降一點
為了這個問題還去查了一下 PackageManager 的原始碼,才發現 PackageManager 的實作提供者有兩個 ApplicationPackageManager 和 PackageManagerService 這些物件又互相 call 來 call 去對方的 method,看了有點頭昏
恩...繼上次 activity context create PackageManager memory leak 後又一個 Android 的坑
2017年9月30日 星期六
2017年9月27日 星期三
java blocking IO read 不支援 interrupt
一直以為 java 所有的 blocking operation 是可以用 thread.interrupt() method 中斷的,但是後來才發現 java 原本的 blocking IO library 是不支援 interrupt 的,例如去 read 一個 socket,然後用 thread.interrupt() 去中斷呼叫 read 的 thread,會發現 read 並沒有被中斷
新的 File library 像是 java.nio 才有支援 interrupt,而原本的 IO library 就要考慮其它的方式來中斷一個 blocking read,例如把 socket close,或是去 polling 是否 data available,若 data available 再呼叫 blocking read method
新的 File library 像是 java.nio 才有支援 interrupt,而原本的 IO library 就要考慮其它的方式來中斷一個 blocking read,例如把 socket close,或是去 polling 是否 data available,若 data available 再呼叫 blocking read method
2017年9月17日 星期日
查詢 kernel module CPU 使用率的好幫手 -- Kernrate
2017年9月11日 星期一
Activity context leak caused by getPackageManager
最近用 leakcanary 檢查有沒有 memory leak 的時候發現了 context leak,而 leak 的 memory 有 2MB 這麼多
context leak 是 android 最常發生的 memory leak 之一,吃掉的 memory 隨著你的 activity 大小而變,因為你的 activity context 無法釋放,隨著你的 activity 中持有的所有資源都會無法釋放
leakcanary 的強大功能就是會顯示出造成 memory leak 的來龍去脈,照著 leakcanary 的提示,是 UserManager 其中的一個 static variable reference 到我的 activity context,不過我沒有在 activity 中使用到 UserManager,怎麼會讓 context 被 UserManager 持有的
一番查證後,在我的 activity 中有去使用 PackageManager,而 PackageManager 內部使用到了 UserManager,而在 UserManager 第一次被使用到的時候會將自身存在一個 static variable 中,從而讓 context 被這個 static variable hold 住
android framework 用這樣的實作,難怪會有 memory leak,還讓你 leak 的不知不覺,只要用 activity context 呼叫 getPackageManager 就踩到坑裡
這個 memory leak 實際上是 android 5.0 的一個 bug,在 android 7.0 已經修正掉了,app 開發者要避開這個 memory leak 的話,需要用 application context 來呼叫 getPackageManage,而不是用 activity context
開發 android 時真的要小心,注意自己的 code 還不夠,還要注意不要掉到 android 挖好的洞裡
context leak 是 android 最常發生的 memory leak 之一,吃掉的 memory 隨著你的 activity 大小而變,因為你的 activity context 無法釋放,隨著你的 activity 中持有的所有資源都會無法釋放
leakcanary 的強大功能就是會顯示出造成 memory leak 的來龍去脈,照著 leakcanary 的提示,是 UserManager 其中的一個 static variable reference 到我的 activity context,不過我沒有在 activity 中使用到 UserManager,怎麼會讓 context 被 UserManager 持有的
一番查證後,在我的 activity 中有去使用 PackageManager,而 PackageManager 內部使用到了 UserManager,而在 UserManager 第一次被使用到的時候會將自身存在一個 static variable 中,從而讓 context 被這個 static variable hold 住
android framework 用這樣的實作,難怪會有 memory leak,還讓你 leak 的不知不覺,只要用 activity context 呼叫 getPackageManager 就踩到坑裡
這個 memory leak 實際上是 android 5.0 的一個 bug,在 android 7.0 已經修正掉了,app 開發者要避開這個 memory leak 的話,需要用 application context 來呼叫 getPackageManage,而不是用 activity context
開發 android 時真的要小心,注意自己的 code 還不夠,還要注意不要掉到 android 挖好的洞裡
2017年9月7日 星期四
2017年9月2日 星期六
找出給定範圍內的質數 -- Sieve of Eratosthenes
Sieve of Eratosthenes是一種找出給定範圍內的演算法,從該範圍內最小質數開始,逐步刪除該質數的乘積,圖形化表達如下
C 程式如下
C 程式如下
bool prime[20000000]; void eratosthenes() { for (int i=0; i < 20000000; i++) prime[i] = true; prime[0] = false; prime[1] = false; for (int i=2; i < 20000000; i++) if (prime[i]) for (int j=i*i; j < 20000000; j+=i) prime[j] = false; }用來實做質數表非常有用,在這邊也有提到更多細節與加速該演算法的方法
訂閱:
文章 (Atom)