-
Notifications
You must be signed in to change notification settings - Fork 559
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance Problems when working with large datasets #2499
Comments
Do you write the records in one big transaction or 50 small transactions? The overhead of durability guaranty can be large, so smaller transaction can be expensive. |
Also ensure you don't open/close the entire Realm every time. A simple repro would be appreciated in case none of the above helps you. |
It's one big transaction and we leave a persistent Realm connection open. I'll get to work on a repro. |
Alright, I haven't reproduced the slow writes yet, but I'm definitely getting much slower reads than I'd expect when doing a slice to get the end of an array. It looks like it's doing a scan through the whole dataset to find the last 3 records? I can work around this in my app by sorting differently and grabbing the first record, but yeah, it's surprising behaviour to me. Here's the repro: |
Still haven't been able to reproduce this in my minimal test case, but in the full app I've narrowed it down. It's the lag between calling const start = new Date();
realm.write(() => {
console.log(
`Transaction start time: ${(new Date().getTime() - start.getTime()) / 1000} seconds`
);
// Rest of my saving logic
}); Produces:
...etc What can I do to figure out why this is taking so long? Is there logging of Realm internals I can enable? I'm also happy to send the full app to you guys privately if that'd help. |
Hmm,regarding read perforamnce: I would hope slice is implemented better than that :-) We just provide an iterator to slice. Another thing, using |
@bmunkholm, thanks for that. I definitely see 18 second read times if I slice the end rather than the beginning. If I reverse the sort and grab the beginning it's <100ms. That's definitely reproduced in the repo above. I'll try your suggestions to see if I can make it even better. The write lag is definitely the killer at the moment. |
Re Write, I'm not sure what your "write logic" is and what happens between the timing logs. But writing something definitely don't take seconds. |
It’s definitely release mode and it’s a Samsung Galaxy S9. Is there any logging I can enable so I can see what it’s doing in the 60 seconds between calling realm.write and getting the callback called? |
There is nothing between the start line and the console log line other than the realm.write call. I’m happy to send the project over so you can see the write logic. Would that help? |
We don't have any logging. You can use |
Ok, I'll keep logging in my code and see if I can figure out what's causing it, then put that into the reproduction. The idea is the import of photos happens in the 'background' (as much as we can in JS anyway) and that the user can keep using the app while the import is happening, so yes, there are other writes happening while this is underway. But again since JS isn't multithreaded, saying it's happening simultaneously would be wrong. |
To answer the cloud question, no, there is no cloud syncing happening at all, this is purely an on device database. I've reproduced very odd behaviour around I've added a reproduction case in thekevinbrown/realm-js-slow-writes@c7ba3ba My leading theory at the moment is that my writes are so slow because:
There was logic like this to work around a "Transaction already in progress" error, but the real question is why in the world is a transaction already in progress there? If JS is single threaded and In any case, I wouldn't expect to be able to crash the app like this by setting my JS up this way. |
Running the repro as it stands immediately crashes the app on the Galaxy S9 we're using, but just in case you have trouble reproducing it, here's an Android bug report bundle from the device: bugreport-2019-08-29-15-52-58.zip
|
Doing write transactions in listener can be tricky as the listener might be called before the first call has terminated. We have seen issues in some cases, and they "guided" us to implement the manual transactions ( I need to investigate a bit more in order to explain the crash. |
Thanks very much for your help @kneth. Logically I don't understand the difference between the two constructs, but if there is a difference between: realm.write(() => {
// whatever
}); and realm.beginTransaction();
// whatever
realm.commitTransaction(); That'd be good to understand better. We've worked around this for the time being in our app by replacing all Realm listeners with JS listeners that fire after the Or another way to say it is there are use cases for serializable transactions in SQL, or atomic writes in CouchDB / Redis / MongoDB and in those cases it's crucial that data is either there or not there and nothing in between. It seems like we as a team don't understand the guarantees that Realm gives us in this regard, so if there are docs I can read about it that'd be really helpful, or if we've just hit a bug that's good to know too. |
The advantage of manual transaction is that you can do something like
Compared to other databases, Realm objects are live. It means that they are updated as the database is updated. The notifications are done through the event loop (on Android we use Once We don't have much documentation on how it works. A bit iOS centric but https://academy.realm.io/posts/live-objects-fine-grained-notifications-realm-update/ gives you an overview. |
@kneth so if I've understood correctly you're saying that this is a feature:
That's the expected behaviour? I buy the logic for notifying quickly, and for why there might be a delay in updating existing live objects to reflect the new data, but asking for a new result set needs to return a correct result. Otherwise how do we actually build a feature with listeners? The app's UI will be updated quickly but it'll be wrong. The screen won't reflect the item the user just added to the DB, and then when it's "really" there we don't get any notification to re-render. |
@kneth, it's now been a while, can you at least confirm whether this is expected behaviour or a bug? I'm considering splitting out the various issues so we can untangle them and follow progress on each if they're going to be long running things. |
Since this has been running for a month and there are separate issues raised, I've split them out into separate issues so we can track progress on each item. |
@thekevinbrown Thanks for splitting into multiple issues. I hope that I can return to them shortly. |
Goals
Our app allows users to sort the photos on their device in a unique way. This means they can't just use the built in photos app to do the sorting.
As a result we have Photos and Albums. We store a URI to the photo and what albums the photo has been sorted to.
Expected Results
Writing 50 records should take less than a second.
Actual Results
If there are more than 5,000 records in the database, adding 50 more takes ~1 second. Since this is react native this absolutely kills the responsiveness of the app.
NOTE: This is definitely a release build, Android.
Steps to Reproduce
I'll create a repro if necessary, just want to make sure this isn't expected behaviour before I do.
Code Sample
Version of Realm and Tooling
The text was updated successfully, but these errors were encountered: