Reputation: 6968
I am trying to replace SQLite with Realm in an android application.
Following is pseudo code of how I am trying to do it:
//SQLite Insert
public void deleteExistingAndInsertNewItemsInDb(ArrayList<Item> itemList, int userId) {
Log.d("REALM_TEST", "No. of Records :: " + itemList.size());
long start;
if (itemList != null && itemList.size() > 0) {
start = System.nanoTime();
initializeDb();
db.beginTransaction();
// delete existing items from the item list table for the provided userId
db.delete(DataBaseHelper.TABLE_NAME, DataBaseHelper.USER_ID + "=" + userId, null);
// insert new item list into local DB.
for(Item item : itemList) {
ContentValues contentValues = new ContentValues();
contentValues.put(DataBaseHelper.COL1, item.getProperty1());
contentValues.put(DataBaseHelper.COL2, item.getProperty2());
...
...
contentValues.put(DataBaseHelper.COL50, item.getProperty50());
// insert item details into local DB.
db.insert(DataBaseHelper.TABLE_NAME, null, contentValues);
}
db.setTransactionSuccessful();
db.endTransaction();
// close database.
closeDb();
long sum = System.nanoTime() - start;
Log.d("REALM_TEST", "Sqlite Insert :: " + sum/1000000);
}
}
//SQLite Read
public ArrayList<Item> getItemListFromDB(int userId){
ArrayList<Item> itemList = new ArrayList<>();
initializeDb();
long start = System.nanoTime();
Cursor cursor = db.query(DataBaseHelper.TABLE_NAME, DataBaseHelper.COLUMN_LIST, DataBaseHelper.USER_ID + "=" + userId,
null, null, null, null);
if(cursor != null) {
while(cursor.moveToNext()) {
Item item= new Item();
item.setProperty1(cursor.getString(0));
item.setProperty2(cursor.getString(1));
...
...
...
item.setProperty50(cursor.getString(50));
itemList.add(item);
}
}
closeDb();
sum = System.nanoTime()-start;
Log.d("REALM_TEST", "Sqlite read list :: " + sum / 1000000 + "ms For " + itemList.size() + " records");
return itemList;
}
//Realm Insert
public void deleteExistingAndInsertNewItemsInRealm(ArrayList<Item> itemList, int userId) {
Realm realm = Realm.getInstance(Application.getContext());
long start = System.nanoTime();
//delete all objects
RealmResults<RealmItem> results = realm.where(RealmItem.class).findAll();
realm.beginTransaction();
results.clear();
for (Item item : itemList) {
RealmItem realmItem = realm.createObject(RealmItem.class);
realmItem.setProperty1(item.getProperty1());
realmItem.setProperty2(item.getProperty2());
...
...
realmItem.setProperty50(item.getProperty50());
}
realm.commitTransaction();
long sum = System.nanoTime() - start;
Log.d("REALM_TEST", "Realm Insert :: " + sum/1000000);
}
//Realm Read
public ArrayList<Item> getItemListFromRealm(int userId) {
ArrayList<Item> itemList = new ArrayList<>();
Realm realm = Realm.getInstance(Application.getContext());
long start = System.nanoTime();
RealmResults<RealmItem> results = realm.where(RealItem.class)
.equalTo("USER_ID", userId).findAll();
if(results != null) {
for (RealItem result: results) {
Item item= new Item();
item.setProperty1(result.getProperty1());
item.setProperty2(cursor.getProperty2());
...
...
...
item.setProperty50(cursor.getProperty50());
itemList.add(item);
}
}
sum = System.nanoTime()-start;
Log.d("REALM_TEST", "Realm read list :: " + sum / 1000000 + "ms For " + itemList.size() + " records");
return itemList;
}
for 500 items following is read write time in milli seconds:
+--------+-------+--------+-------+
| Write | Read |
+--------+-------+--------+-------+
| Sqlite | Realm | Sqlite | Realm |
| 247 | 382 | 142 | 222 |
| 303 | 321 | 102 | 278 |
| 263 | 303 | 134 | 240 |
| 301 | 292 | 165 | 290 |
+--------+-------+--------+-------+
Am i doing something wrong?
Update:
I have added a working example here. write times are almost similar to my actual app. read times have improved in the example, for realm.
I am using a single data type String for all properties in the example where as its a good mix of data types in actual application.
Upvotes: 2
Views: 734
Reputation: 20126
The test you have written here looks right, so the numbers you get are probably fairly accurate for the hardware it is running on. Note however that benchmarks are notoriously tricky to get right and are impacted by a lot of things outside your control (e.g. other apps running / sensors / GC).
Some pointers for making your Realm code easier is below, but note this will not improve your benchmark result but just make your code a lot easier to read and maintain:
Any reason you are copying all data into a standard Java object? RealmObjects are lazy by default and the performance will be better if you don't actually need to use all 50 fields. If you indeed want to copy all data, consider using Realm.copyFromRealm()
instead. That will automatically copy everything, so you don't have to it by hand as you do now.
Instead of manually filling out all the fields, you can use Realm.copyToRealm()
instead which would be a 1-liner instead of 50 lines and you don't have to maintain it if the fields change.
For deleting all items of a specific type using Realm.clear(RealmItem.class)
is faster.
Upvotes: 1