I noticed one of my performance test cases failing since adding a to-many relationship to one of my models:
let tags = List<Tag>()
Even when not populated this seems to reduce read / write performance by ~200%. Is this expected behaviour?
What do you want to achieve?
Quickly read from a model that contains a to-many relationship
What did you expected to happen?
Results are returned in a similar time to a model without a relationship
What did happened instead?
Results are returned ~200% slower
Add a to-many relationship to a model:
let tags = List<Tag>()
Here's a minimal test case:
import XCTest
import RealmSwift
class A: Object {
dynamic var id: Int = 0
// let children = List<B>()
}
class B: Object {}
class RealmPerformanceTests: XCTestCase {
var realm: Realm!
override func setUp() {
super.setUp()
var config = Realm.Configuration()
config.inMemoryIdentifier = self.name
self.realm = try! Realm(configuration: config)
}
func writeObjects(count: Int) {
self.realm.add((0...count).map { A(value: ["id": $0]) })
}
func testWritePerformance() {
self.measure {
try! self.realm.write {
self.writeObjects(count: 100000)
}
}
}
func testReadPerformance() {
try! self.realm.write {
self.writeObjects(count: 100000)
}
self.measure {
var objects = [A]()
for object in self.realm.allObjects(ofType: A.self) {
objects.append(object)
}
}
}
}
Results:
testWritePerformance: 2.188 seconds
testReadPerformance: 0.263 seconds
Uncommenting the relationship line and re-running the tests gives:
testWritePerformance: 6.292 seconds
testReadPerformance: 0.863 seconds
ProductName: Mac OS X
ProductVersion: 10.12
BuildVersion: 16A304a
/Applications/Xcode-beta6.app/Contents/Developer
Xcode 8.0
Build version 8S201h
/usr/local/bin/pod
1.1.0.beta.1
Realm (1.0.2)
RealmSwift (1.0.2)
Realm (from `https//github.com/realm/realm-cocoa.git`, branch `master`)
RealmSwift (from `https//github.com/realm/realm-cocoa.git`, branch `master`)
/bin/bash
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)
carthage not found
(not in use here)
/usr/local/bin/git
git version 2.9.3
Thanks!
There is unfortunately a lot of unavoidable overhead. The most expensive part of reading an object from a Realm is just allocating the memory for the object, and adding a List property adds a few more allocations that can't be done lazily. That said, I think currently each List property requires three eager allocations, and two of them could probably be deferred until the property is actually used.
Most helpful comment
There is unfortunately a lot of unavoidable overhead. The most expensive part of reading an object from a Realm is just allocating the memory for the object, and adding a
Listproperty adds a few more allocations that can't be done lazily. That said, I think currently eachListproperty requires three eager allocations, and two of them could probably be deferred until the property is actually used.