When maximumNumberOfActiveVersions is decremented?

I can see when maximumNumberOfActiveVersions is incremented but I can’t find when this value is decremented. We set 66 for production and it is not enough

Can you be a bit more specific? Where can you see maximumNumberOfActiveVersions - in code? In a Function? Endpoint call? Can you clarify what’s being asked and include some example code if possible?

In realm swift you use config object to instantiate Realm:

var config = Realm.Configuration(
            fileURL: fileURL,
            schemaVersion: 0,
            deleteRealmIfMigrationNeeded: false,
            objectTypes: ...
        )
        config.maximumNumberOfActiveVersions = 66

One of the parameters is maximumNumberOfActiveVersions. At some point Realm is crashing with next message Number of active versions (66) in the Realm exceeded the limit 67. We can see in which cases this counter is increasing but it is not clear how to make Realm decrease it.

Ah, I see. So you’re using a local only Realm (no sync) and (maybe?) during a migration.

That value is set by the developer so Realm will ‘crash’ instead of creating a ginormous file that cannot be opened. If it’s hitting that limit you set, there’s something else likely going wrong, as that’s a big number.

Are you processing a huge dataset on a background thread perhaps? One of our apps, cranks through 2Gb of data and we never had that issue.

I would think doing some troubleshooting may help - if there are a lot of threads active at once or if frozen objects are left frozen; maybe a class is not being deallocated? Maybe a runaway process? Checking memory with XCode may lead to why that’s happening.

Wish I had more precise info but it seems that issue is caused by something else in the app.

Yes, only local realm DB, no sync and crash is happening during normal read/write operations not a migration.

The way how I was managed to reproduce it:

let realm = ...

// Create on main thread
realm.objects(Entity.self)
    .collectionPublisher
    .sink { completion in } receiveValue: { value in  }
    .store(in: &subscriptions)

DispatchQueue.background.async {
    (0..<1_000).forEach {
        let realmBackground = ... 
        try? realmBackground.write(...)
   }
}

If I move writing to main thread maximumNumberOfActiveVersions will never raise an exception.

if there are a lot of threads active at once or if frozen objects are left frozen; maybe a class is not being deallocated

  • Yes, we have at least couple of threads.
  • we don’t use frozen objects
  • do you mean realm db not deallocated or realm entity? Bu I think we are not holding reference to any of them

That is why I want to understand in which case Realm decrement maximumNumberOfActiveVersions :slightly_smiling_face:
I found a unit test which demonstrate when it is incremented but I can’t find unit test or explanation in documentation when it is decremented

I am not sure I am clear on the code. What does the first section have to do with the second?

Then in the second, it looks like 1001 Realms are being created with each one written to. While technically they allocated and deallocated that doesn’t seem like a good thing.

Are you using an autorelease pool anywhere? See Avoid Pinning Transactions

Ok, let me try to explain what is happening. I have next class to work with Realm DB

final class DBClient {
    private let dispatchQueue: DispatchQueue = .init(label: "db", qos: .utility)

    func store(report: Report) {
        dispatchQueue.async {
            let realmBackground = ... 
            try? realmBackground.write(report)
        }
    }

    func observeReports() -> AnyPublisher<[Report], Never> {
        let realm = ...
        realm.objects(Report.self)
            .collectionPublisher  
            ...
    }
}

I think I’ve read that creating new instance of realm is cheap operation. That is why I create a new instance on each call to avoid accessing realm from different threads.

In my case store functions is executed very often and at some point it leads to a crash, because we reached maximum number of active version. From the documentation I can see that Older data is only garbage collected when it is no longer referenced or actively in use by a client application. But in my case for some reason doesn’t happen.

If you’re writing 1000 objects to realm, there’s no reason to create 1000 realm instances to do that; create one and do your write, ensuring it’s on a background thread to avoid blocking the UI. For a great option see Run A Transaction.

That store function, as is, does not lead to a crash for us, nor cause any issues with maximumNumberOfActiveVersions.

To verify, we created 100,000 objects and called that function to write them to realm. There was no issue or crash. My guess is, the issue is caused by something else other than that specific code.

That is correct and if you’re working with larger datasets, it’s a good idea to wrap it in an autorelease pool so they are disposed of as soon as possible once they go out of scope. Here’s some additional reading that may help

See this answer on StackOverflow along with this one and maybe this one too.

The question about maximumNumberOfActiveVersions;

from my understanding this is set to 0 by default and then you, as the developer can set it to a non-zero number. e.g. it doesn’t change itself - you have to do that. So there isn’t a way to decrement that number; that being said it can be handy to determine if you’ve got runaway processes, memory issues etc. Setting it to a small number will cause a app crash in instead of creating a crazy large datafile that’s corrupted or to large to be opened.

That helps find issues before they are bigger issues.

Also one of the reasons I created realm instance for each call was to “avoid” holding realm instances. When I saw first time exception Number of active versions (66) in the Realm exceeded the limit 67 I thought that this is because I’m not releasing realm object. But from what I can see it should be OK to keep 2 Selma instances: one to observe and one to write in background thread.

thanks, I’m already using autoreleasepool

Yes it is clear, that I can’t manually decrement this value, but I’m wondering how it is implemented in Realm, I mean when realm decides that maximumNumberOfActiveVersions should be decremented. When all realm DB instances released or etc