Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Realm causing lots of ANR

Tags:

android

realm

In my own testing I did not encounter this issue but once my app was published the ANRs started flooding in. My app currently has 22 ANRs with some being reported as many 100 times. All of the traces seem to be from attempting to create a new Realm instance on the UI thread.

"main" prio=5 tid=1 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x4183ede0 self=0x417548b8
| sysTid=19680 nice=0 sched=0/0 cgrp=apps handle=1073975684
| state=S schedstat=( 2816413167 710323137 3658 ) utm=215 stm=66 core=1
at io.realm.Realm.createAndValidate(Realm.java:~495)
- waiting to lock <0x41df9c98> held by tid=12          (IntentService[UASyncService])
at io.realm.Realm.create(Realm.java:486)
at io.realm.Realm.getInstance(Realm.java:404)
at io.realm.Realm.getInstance(Realm.java:366)
at io.realm.Realm.getInstance(Realm.java:347)

I believe the root of this issue is, as beeender mentioned, that I have an open Realm transaction in a worker thread which is blocking my attempts to get a Realm instance on the UI thread causing ANRs.

I will update again later after I have a solution.

*Edit: Added updated information.

like image 891
MichaelAnDev Avatar asked Jul 20 '15 16:07

MichaelAnDev


1 Answers

Realm no longer has this issue.

For reference my solution at the time was:

Thanks to beeender for pointing me in the right direction and linking this PR https://github.com/realm/realm-java/pull/1297

Issue

When there is a pending Realm transaction, any call to Realm.getInstance on a different thread will block until the pending transaction has been committed or cancelled.

In my case I have an IntentService which populates my Realm with existing user data, meanwhile I try to display any current data by querying Realm on the UI thread. Although the queries are simple and don't cause any issues normally, if there is a pending transaction in the IntentService, calling Realm.getInstance will be blocked, blocking the UI thread, potentially causing an ANR.

My first attempt at a solution was to pull beeender's PR branch and create a jar. I believe this fix did get me one step further, allowing the Realm instance to be created without blocking, but the UI thread was still blocked by small transactions I was trying to perform on UI thread.

Solution

The solution I implemented involves several steps:

  • Create duplicate objects for all of my models. The duplicates do not extend RealmObject (since RealmObjects cannot be used across threads.)
  • Move all accesses to Realm onto background threads. Basically I wrapped my queries in AsyncTasks and added listeners which return the non-RealmObject version of the model.
  • Make more small transactions rather than fewer large transactions. Where previously I began and committed transactions on either side of a loop which created many new RealmObjects, I now begin and commit the transaction per object. The purpose of this is to reduce the total uninterrupted time that Realm may be in an open transaction state so my queries providing data for the UI can complete without having to wait as long.

Conclusion

I was initially hesitant to use Realm due to it still being in beta as well as the caveat that RealmObjects cannot be used across threads. After some tests I felt confident that I could perform simple queries on the UI thread without issue (still with a guilty feeling in my gut though.)

Overall Realm is a great project to keep an eye on but I feel that it is not ready for large scale commercial projects. Using Realm on this project may have saved some time upfront but it cost many displeased customers and a difficult to diagnose issue.

*Edit: Clarified issue.

like image 69
MichaelAnDev Avatar answered Nov 15 '22 03:11

MichaelAnDev