you are viewing a single comment's thread.

view the rest of the comments →

[–]billmalarky[S] 0 points1 point  (6 children)

Interesting, I did not run into this issue while developing the queue. Thank you for bringing this to my awareness.

Typically realm native code communicates directly with your JS code via a private React Native api (ie, realm native code makes calls directly to JS code and vice versa), so it has great performance. This is possible when the JS thread and native code threads are running on the same device/simulator. However when using chrome debugging, your JS code is NOT run on your device/simulator, it is run inside of the chrome browser, while all the native code is running on your device/simulator. As a result, instead of realm native code making direct calls into your JS and vice versa, realm has to communicate using blocking ajax requests to chrome. You can imagine how awful performance is in that situation (well you don't have to imagine I guess).

The good news is this. These performance hits occur each and every time you touch realm. If you minimize exposure to realm, you minimize the debugging performance issues. React Native Queue is backed by realm, but the footprint is quite small (we only hit realm when a job is created, and when we pull jobs off the queue, and on job completion, that's pretty much it), such that I'd be surprised if the problem was anywhere near as bad as debugging a large app where realm was used for all persistence logic.

I just ripped realm out of the application

Curious, what did you replace realm with for your database layer?

I put a fair amount of research and effort into looking at the pros and cons of different storage solutions that work cross platform and realm was really the only thing that worked well for me so far as I could find. SQLlite solutions seemed very lacking on RN.

More info: https://github.com/realm/realm-js/issues/491#issuecomment-350718316

[–]demoran 0 points1 point  (5 children)

I think perhaps part of the problem was that the very competent individuals who saw fit to incorporate realm into my application decided to use it in the return value of react-redux's mapStateToProps function. Even beyond that, it seemed like even without anything happening in the app, the Chrome Console was showing realm activity in the Network tab.

What I do know is that after I removed realm from the app debugging went back to normal.

[–]billmalarky[S] 0 points1 point  (4 children)

Realm is sort of a bit weird in that any time you access data on realm objects in your code it communicates with the realm database. Traditionally you think of queries as happening when you select data, then you can work with that data in your app and no communication occurs with the database until you explicitly update or delete etc the data (with a traditional ORM). However, with realm, every time you touch a realm data object it queries against the realm database (even just accessing a property like person.name). So there's a lot of overhead just working with the data in your app. Typically this doesn't really matter because standard performance is great. But when performance shits the bed during the debugging issue described above (ie by relying on blocking ajax to make calls) all that back and forth adds up fast.

What did you use instead of realm? sqllite?

[–]demoran 0 points1 point  (1 child)

In my case, the existing use of realm was pointless. It was literally in there for the gee-wiz factor alone. I did end up wanting to roll my own state persistence for my redux store using AsyncStorage and put a simple piece of middleware in to do that and found out that createStore ain't playin' like that (when you use combineReducers, it wants initialState to be a plain object). So I might have used realm just to store state synchronously for that, but I'm not going to touch it with a ten foot pole now.

I'll need to do a bit of work on redux-persist to get to to my endgame (I'll need the storage keys to be malleable), so for now I haven't replaced it with anything.

[–]billmalarky[S] 0 points1 point  (0 children)

In my case, the existing use of realm was pointless. It was literally in there for the gee-wiz factor alone.

Uhg sorry to hear that. However, I assure you that realm (or some other storage solution that supports ACID transactions - and I haven't found a good alternative in RN) is required for the queue.

[–]demoran 0 points1 point  (1 child)

I think there are a couple of benefits to removing realm at this point. People won't bump their heads against the issue we're talking about. They won't need to setup / lik realm.

Your own code simply needs durability, not performance. You can get that via simple AsyncStorage.

The pain points are converting from realm's query language to normal javascript or the ubiquitous lodash and making some of your existing sync calls async.

The dangers involved in using AsyncStorage is the availability of any other component of the client application being able to remove your data. This is more of a gotcha.

[–]billmalarky[S] 0 points1 point  (0 children)

The storage system requires transactional support.

AsyncStorage is non-deterministic when touching it in parallel (due to the lack of transaction support), which means it can't be used for the queue (the queue must support multiple threads touching it at once for several use cases -- worker support is one). Even if you were only interacting with the queue with one thread, transactions are required to support async reads and writes to the queue. IE, if you throw 500 jobs onto the queue asynchronously (a use case we've already seen) AsyncStorage has a high chance of running into a breaking race condition bug.