Realm compare with GreenDao
Android Studio配置
Realm環(huán)境配置
- 在項目的 build.gradle 文件中添加如下 class path 依賴浑彰。
- classpath "io.realm:realm-gradle-plugin:3.1.1"
- 在 app 的 build.gradle 文件中應(yīng)用 realm-android 插件兜挨。
- apply plugin: 'realm-android'
GreenDao環(huán)境配置
-
在項目的 build.gradle 文件中進行以下配置
- 在repositories添加 mavenCentral()
- 在dependencies添加 classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
-
在 app 的 build.gradle 文件中應(yīng)用 org.greenrobot.greendao 插件侍芝。
- apply plugin: 'org.greenrobot.greendao'
-
在 app 的 build.gradle 文件中添加兩個依懶
- compile 'org.greenrobot:greendao:3.2.2'
- compile 'org.greenrobot:greendao-generator:3.2.2'
自此Reaml和GreenDao配置完成,兩個的配置都是挺簡單躏尉。
數(shù)據(jù)庫類型的區(qū)別
Realm 是一個 MVCC 數(shù)據(jù)庫 , MVCC 在設(shè)計上采用了和 Git 一樣的源文件管理算法。你可以把 Realm 的內(nèi)部想象成一個 Git后众,它也有分支和原子化的提交操作胀糜。這意味著你可能工作在許多分支上(數(shù)據(jù)庫的版本),但是你卻沒有一個完整的數(shù)據(jù)拷貝蒂誉。Realm 和真正的 MVCC 數(shù)據(jù)庫還是有些不同的教藻。一個像 Git 的真正的 MVCC 數(shù)據(jù)庫,你可以有成為版本樹上 HEAD 的多個候選者右锨。而 Realm 在某個時刻只有一個寫操作括堤,而且總是操作最新的版本 - 它不可以在老的版本上工作。
GreenDao是一個ORM數(shù)據(jù)庫,對象-關(guān)系映射(OBJECT/RELATIONALMAPPING陡蝇,簡稱ORM)痊臭,用來把對象模型表示的對象映射到基于S Q L 的關(guān)系模型數(shù)據(jù)庫結(jié)構(gòu)中去。這樣登夫,我們在具體的操作實體對象的時候广匙,就不需要再去和復(fù)雜的 SQ L 語句打交道,只需簡單的操作實體對象的屬性和方法[2] 恼策。O R M 技術(shù)是在對象和關(guān)系之間提供了一條橋梁鸦致,前臺的對象型數(shù)據(jù)和數(shù)據(jù)庫中的關(guān)系型的數(shù)據(jù)通過這個橋梁來相互轉(zhuǎn)化[1]
Realm與GreenDao性能對比
對比前的準(zhǔn)備
public class SystemInfotil {
/**
* 獲取當(dāng)前cpu信息
* @param context
* @return
*/
public static SystemInfo getProcessCpuRate(Context context) {
float totalCpuTime1 = getTotalCpuTime();
float processCpuTime1 = getAppCpuTime();
return new SystemInfo(totalCpuTime1, processCpuTime1, displayBriefMemory(context));
}
/**
* 獲取cpu使用率
* @param startCpuInfo 開始時的信息
* @param endCpuInfo 結(jié)束時的信息
*/
public static float caculateRate(SystemInfo startCpuInfo, SystemInfo endCpuInfo) {
return 100 * (endCpuInfo.processCpuTime - startCpuInfo.processCpuTime)
/ (endCpuInfo.totalCpuTime - startCpuInfo.totalCpuTime);
}
/**
* 獲取cpu和內(nèi)存使用
* @param startCpuInfo 開始時的信息
* @param endCpuInfo 結(jié)束時的信息
*/
public static String getRateString(SystemInfo startCpuInfo, SystemInfo endCpuInfo) {
float cpuRate = caculateRate(startCpuInfo, endCpuInfo);
return "; CPU:" + cpuRate + "; 內(nèi)存:" + (endCpuInfo.availibleMem - startCpuInfo.availibleMem);
}
/**
* 其中,以CPU開頭的兩行表示的信息就是涣楷,當(dāng)前該CPI的一個總的使用情況分唾,后面各個數(shù)值的單位為jiffies,可以簡單理解為Linux中操作系統(tǒng)進程調(diào)度的最小時間片狮斗。具體含義如下(以CPU0為例):
* user(181596)從系統(tǒng)啟動開始累計到當(dāng)前時刻绽乔,處于用戶態(tài)的運行時間,不包含 nice值為負進程碳褒。折砸;
* nice(85733)從系統(tǒng)啟動開始累計到當(dāng)前時刻看疗,nice值為負的進程所占用的CPU時間;
* system (197165)從系統(tǒng)啟動開始累計到當(dāng)前時刻睦授,處于核心態(tài)的運行時間两芳;
* idle (1328127)從系統(tǒng)啟動開始累計到當(dāng)前時刻,除IO等待時間以外的其它等待時間去枷;
* iowait(11679)從系統(tǒng)啟動開始累計到當(dāng)前時刻怖辆,IO等待時間;
* softirq (5138)從系統(tǒng)啟動開始累計到當(dāng)前時刻删顶,軟中斷時間竖螃。
* irq (5)從系統(tǒng)啟動開始累計到當(dāng)前時刻,硬中斷時間翼闹;
* @return
*/
public static long getTotalCpuTime() {
String[] cpuInfos = null;
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream("/proc/stat")), 1000);
String load = reader.readLine();
reader.close();
cpuInfos = load.split(" ");
} catch (IOException ex) {
ex.printStackTrace();
}
long totalCpu = Long.parseLong(cpuInfos[2])
+ Long.parseLong(cpuInfos[3]) + Long.parseLong(cpuInfos[4])
+ Long.parseLong(cpuInfos[6]) + Long.parseLong(cpuInfos[5])
+ Long.parseLong(cpuInfos[7]) + Long.parseLong(cpuInfos[8]);
return totalCpu;
}
/**
* 獲取應(yīng)用占用的CPU時間
*/
public static long getAppCpuTime() {
String[] cpuInfos = null;
try {
int pid = android.os.Process.myPid();
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream("/proc/" + pid + "/stat")), 1000);
String load = reader.readLine();
reader.close();
cpuInfos = load.split(" ");
} catch (IOException ex) {
ex.printStackTrace();
}
long appCpuTime = Long.parseLong(cpuInfos[13])
+ Long.parseLong(cpuInfos[14]) + Long.parseLong(cpuInfos[15])
+ Long.parseLong(cpuInfos[16]);
return appCpuTime;
}
/**
* 獲取當(dāng)前內(nèi)存的使用量
*/
public static float displayBriefMemory(Context context) {
final ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(info);
return info.totalMem / 1024 / 1024;
}
public static class SystemInfo {
float totalCpuTime;
float processCpuTime;
float availibleMem;
SystemInfo(float totalCpuTime, float processCpuTime, float availibleMem) {
this.totalCpuTime = totalCpuTime;
this.processCpuTime = processCpuTime;
this.availibleMem = availibleMem;
}
}
}
10次的插入平均資源消耗
GreenDao插入數(shù)據(jù)代碼實現(xiàn)和插入結(jié)果統(tǒng)計
long startIndex = System.currentTimeMillis();
for (int index = 0; index < insertCount; index ++) {
user = new User(index + startIndex, GreenDaoActivity.NAME + ((int)(Math.random() * GreenDaoActivity.RANDOM_SIZE)) + "" + (startIndex + index));
userDao.insertOrReplace(user);
}
插入數(shù)量 |
CPU峰值 |
內(nèi)存消耗 |
CPU時間 |
10條 |
17.37% |
0 |
30 |
20條 |
16.17% |
0 |
57 |
100條 |
13.16% |
0 |
270 |
1000條 |
11.46% |
0 |
2663 |
Realm插入數(shù)據(jù)代碼實現(xiàn)和插入結(jié)果統(tǒng)計
for (int index = 0; index < insertCount; index ++) {
final int finalIndex = index;
Realm.getDefaultInstance().executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
Contact contact = realm.createObject(Contact.class);
contact.setName(GreenDaoActivity.NAME + ((int)(Math.random() * GreenDaoActivity.RANDOM_SIZE)) + "" + (startTime + finalIndex));
contact.setSex(startTime + finalIndex);
}
});
}
插入數(shù)量 |
CPU峰值 |
內(nèi)存消耗 |
CPU時間 |
10條 |
15.95% |
0 |
38 |
20條 |
16.46% |
0 |
65 |
100條 |
13.26% |
0 |
277 |
1000條 |
13.53% |
0 |
2735 |
從上圖得出的結(jié)論
- Realm與GreenDao消耗CPU斑鼻,內(nèi)存和時間都差不多
10次的查詢的平均資源消耗
GreenDao查詢數(shù)據(jù)代碼實現(xiàn)和查詢結(jié)果統(tǒng)計
for (int index = 0; index < selectTime; index ++) {
String startWidth = NAME + + ((int)(Math.random() * RANDOM_SIZE));
list = (ArrayList) getUserDao().queryBuilder().where(UserDao.Properties.Name.like("%" + startWidth + "%")).list();
if (list != null && list.size() >= 0) {
localList.addAll(list);
}
}
查詢數(shù)量 |
CPU峰值 |
內(nèi)存消耗 |
CPU時間 |
10條 |
31.67% |
0 |
172 |
20條 |
30.34% |
0 |
328 |
100條 |
27.35% |
0 |
1619 |
1000條 |
25.71% |
0 |
16121 |
Realm查詢數(shù)據(jù)代碼實現(xiàn)和查詢結(jié)果統(tǒng)計
for (int index = 0; index < selectTime; index ++) {
Realm.getDefaultInstance().executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
RealmResults realms = realm.where(Contact.class).beginsWith("name", GreenDaoActivity.NAME + ((int)(Math.random() * GreenDaoActivity.RANDOM_SIZE))).findAll();
if (realms == null) {
return;
}
counts[0] += realms.size();
}
});
}
查詢數(shù)量 |
CPU峰值 |
內(nèi)存消耗 |
CPU時間 |
10條 |
21.35% |
0 |
75 |
20條 |
20.46% |
0 |
145 |
100條 |
20.35% |
0 |
723 |
1000條 |
19.95% |
0 |
7028 |
從上圖得出的結(jié)論
- Realm在CPU和耗時上都要比GreenDao性能要好
10次的刪除平均資源消耗
GreenDao刪除數(shù)據(jù)代碼實現(xiàn)和刪除結(jié)果統(tǒng)計
for (int index = 0; index < deleteTimes; index ++) {
getUserDao().delete(userIds.get(index));
userIds.remove(index);
}
刪除數(shù)量 |
CPU峰值 |
內(nèi)存消耗 |
CPU時間 |
10條 |
15.99% |
0 |
41 |
20條 |
16.68% |
0 |
76 |
100條 |
15.17% |
0 |
371 |
1000條 |
15% |
0 |
2771 |
Realm刪除數(shù)據(jù)代碼實現(xiàn)和刪除結(jié)果統(tǒng)計
for (int index = 0; index < deleteCount; index ++) {
Realm.getDefaultInstance().executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
RealmResults realmResults = realm.where(Contact.class).beginsWith("name", GreenDaoActivity.NAME + ((int)(Math.random() * GreenDaoActivity.RANDOM_SIZE))).findAll();
if (realmResults.size() <= 0) {
return;
}
counts[0] += realmResults.size();
realmResults.deleteAllFromRealm();
}
});
}
刪除數(shù)量 |
CPU峰值 |
內(nèi)存消耗 |
CPU時間 |
10條 |
23.13% |
0 |
229 |
20條 |
21.56% |
0 |
426 |
100條 |
20.45% |
0 |
1729 |
1000條 |
17.04% |
0 |
3359 |
從上圖得出的結(jié)論
10次的更新平均資源消耗
GreenDao刪除數(shù)據(jù)代碼實現(xiàn)和刪除結(jié)果統(tǒng)計
for (int index = 0; index < deleteTimes; index ++) {
User user = userIds.get(index);
user.setName(user.getName() + "_____________NEW");
getUserDao().update(user);
}
更新數(shù)量 |
CPU峰值 |
內(nèi)存消耗 |
CPU時間 |
10條 |
13.81% |
0 |
20 |
20條 |
14.96% |
0 |
43 |
100條 |
14.04% |
0 |
207 |
1000條 |
12.18% |
0 |
1546 |
Realm刪除數(shù)據(jù)代碼實現(xiàn)和刪除結(jié)果統(tǒng)計
for (int index = 0; index < deleteTimes; index ++) {
final int finalIndex = index;
Realm.getDefaultInstance().executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
Contact contact = realm.where(Contact.class).beginsWith("name", GreenDaoActivity.NAME + ((int)(Math.random() * GreenDaoActivity.RANDOM_SIZE))).findFirst();
if (contact == null) {
return;
}
counts[0] += 1;
contact.setName(contact.getName() + "_____________NEW");
}
});
}
更新數(shù)量 |
CPU峰值 |
內(nèi)存消耗 |
CPU時間 |
10條 |
14.93% |
0 |
30 |
20條 |
16.24% |
0 |
57 |
100條 |
16.07% |
0 |
277 |
1000條 |
14.94% |
0 |
3121 |
從上圖得出的結(jié)論
綜上所述
- 插入1000條以內(nèi)的數(shù)據(jù)時,Realm與GreenDao不分伯仲
- 查詢操作比較頻繁猎荠,就使用Realm
- 刪除和更新操作比較頻繁坚弱,就使用GreenDao
需要說明的是使用Realm的話,打包成apk后关摇,大概會大4M左右荒叶,而GreenDao幾乎不會導(dǎo)致安裝包有太大的變化。但是Realm對于內(nèi)存優(yōu)化非常好输虱,號稱是Zero-copy