11

This is what the documentation has to say about accessing a realm using GCD:

"You should use an explicit autorelease pool when accessing a Realm from a dispatch queue."

Documentation

I have used this practice in my app but I am suddenly seeing the following message in my console: "RLMRealm instance was deallocated during a write transaction".

It is not throwing an error, it is just silently printing it to the console. Nothing is written to the database.

I found this issue on github that seems very similar.

My question is now: What practice should I use? The one used in the Realm documentation or the answer found in the github issue?

Thanks for any clarification.

Community
  • 1
  • 1
fisher
  • 1,286
  • 16
  • 29

1 Answers1

13

GCD blocks manage their own @autorelease pools, but there's no guarantee when that will actually occur, and it may happen a fair amount of time after the block itself has completed (See this SO answer)

Realm maintains read-locks on all of its instances across threads (This is how it's possible to still read from Realm while a write transaction is open on another thread), so as a result, it's recommended to explicitly dealloc a Realm instance when you're done so that disk space can be reclaimed.

If you don't use an @autoreleasepool, nothing too bad will happen; just the size of the Realm file on disk will increase.

Best practice is to use an @autoreleasepool block, and to ensure that all of your write transactions are committed inside that block.

@autoreleasepool {
    let realm = try! Realm()
    try! realm.write {
        // ... perform changes
    }
}

It's usually recommended to use realm.write over beginWrite()/commitWrite() since it lets you safely perform transactions without forgetting to commit, and also provides some extra error handling.

The problem with the issue on GitHub was that there was a logic path that would cause the @autoreleasepool to exit before the write transaction had been committed. In this case, you need to review your code logic and make sure you haven't got anything similar.

Community
  • 1
  • 1
TiM
  • 15,812
  • 4
  • 51
  • 79
  • 1
    `nothing too bad will happen; just the size of the Realm file on disk will increase.` if it takes too long, your Realm size can increase drastically (depending on the number of concurrent threads), though. – EpicPandaForce Dec 19 '16 at 20:11
  • That doesn't apply here. That's when long-running transactions increase the transaction log size. Not draining background Realm instances never `drastically` increased the size, but it did cause them to grow more than they needed. In any case, we're aware of the transaction log issue and are working on a solution: https://github.com/realm/realm-core/issues/2343 :) – TiM Dec 19 '16 at 20:46
  • @TiM would using DispatchQueue(label: "someLabel", autoreleaseFrequency: .workItem).async have the same effect as having an autorelease pool for most cases? Complete question here: https://stackoverflow.com/questions/49459967/for-realm-swift-could-i-use-dispatchqueue-with-autorelease-frequency-of-workit – hyouuu Mar 24 '18 at 00:25
  • 2
    @hyouuu Hmm, I've never tried that API so I'm not sure. The general idea is you want to make sure the objects are released as soon as possible after the dispatch queue has completed its work. The longer they stay in memory, the longer version pinning occurs (and your Realm file size can grow). In any case, I'd say that's still a far better approach than not having any autoreleasepool handling at all. – TiM Mar 26 '18 at 05:40
  • We have observed Realm files growing too large to open due to a lack of `autoreleasepool`s around transactions happening on background threads. It's pretty rare that they grow this large, and it likely takes a long time, but it can happen. – Isaac Overacker Mar 21 '19 at 18:01
  • Even if we added `autoreleasepool` the relam files are still growing drastically. Because we have a cache system which is based on realm database. The write transaction is called frequently. So we have to save the cache to the memory first to prevent this problem. – Kimi Chiu Aug 28 '20 at 11:19
  • One thing to keep in mind is that Realm files don't shrink. If you write a lot of data, but then delete it, the Realm file will expand, but won't shrink. This can happen even if you're using an autoreleasepool (But not using one exacerbates the problem), so without knowing more about your code, this might be normal. You should definitely set a clean up policy in your Realm configuration to manage it. This might be worth a new SO question if you still need help. :) – TiM Aug 28 '20 at 11:49
  • Realm file do shrink, you just have to call `compactRealm`. For me, it's a cache system, so I just delete all data in the database while the realm initialization is failed to keep my app works well. The file size is still growing very fast even if we have decreased the operations to realm database already. – Kimi Chiu Aug 28 '20 at 11:58