The Realm vs SwiftData thing encouraged me to try the same project w/ Lighter. It isn't exactly the same as Lighter is no ORM, but it will give some hints on what a little lower level can yield. For now, the 10k plain items test:
SwiftData: User instantiation: 0.0676
Create users: 1.9151
Realm: User instantiation: 0.0229
Create users: 0.1220
Lighter: User instantiation: 0.0049
Create users: 0.0820
I had to implement bulk insert, that wasn't available yet
I'm currently running the test w/ 1m plain items (UUID id, 2 strings, one int). Stuck in SwiftData, currently at 6+ GB RAM usage. We'll see whether it will complete
So I've essentially ported the whole perf test over to Lighter, which was interesting because it also demonstrates some key differences in the approaches. E.g. to update the math grades of the bad students, the sample essentially loads all students and their grades into memory, then updates the grades one-by-one and saves them back to the store.
https://github.com/jacobsapps/RealmVsSwiftData/blob/c18fa4718a9421544e93d1138d756ec7740d6163/RealmVsSwiftData/PerformanceTesting/SwiftStudentsTests.swift#L54
In plain SQL that would be just a single line `UPDATE` statement, no loading at all.
The SwiftData implementation in the test also seems to be not quite optimal. E.g. to update the items, already fetched items get inserted into a new ModelContext and then saved (a lot of new MCs are created, which seems completely counter the idea, though sometimes necessary to keep SwiftData RAM at bounds). Presumably just saving the context used to fetch the items would be quite a bit more efficient.
But hey, the source was provided, so someone can PR an improved SwiftData test
It completed, ~2:45 hours (with ~32 seconds spend in Realm and Lighter).
SwiftData User init: 6.5249
Create: 9913.5297 (2.75h)
Fetch `Jane` in age order: 1.7491
Rename `Jane` to `Wendy`: 133.1398
Realm User init: 1.8732
Create: 6.0422s
Fetch `Jane` in age order: 0.0171
Rename `Jane` to `Wendy`: 0.0113
Lighter User init: 0.5128
Create: 24.1531s
Fetch `Jane` in age order: 0.0222
Rename `Jane` to `Wendy`: 0.0318
Lighter numbers should be close to the max possible in SQLite.
I had defined a SQL index on the `name` column in Lighter. If I drop that index, the inserts get down to 8s (from 24s and close to the 6s in Realm, w/ the lower instantiation time almost the same). However that triples the query time from 22ms to 65ms.
Applying a common SQL bulk import strategy by dropping the index before the import and re-creating it after the import, one gets best of the two worlds (fast imports and queries). Index creation only takes 360ms.
@helge I've not followed this very closely... are those results saying it takes 2.75h to insert each individual student into SwiftData???
@afarnham No, the 2.75h are for inserting 1m of the simple user records, the record (just 4 columns, no relationships): https://github.com/jacobsapps/RealmVsSwiftData/blob/c18fa4718a9421544e93d1138d756ec7740d6163/RealmVsSwiftData/DB/SwiftData/Users/SwiftUser.swift
The test: https://github.com/jacobsapps/RealmVsSwiftData/blob/c18fa4718a9421544e93d1138d756ec7740d6163/RealmVsSwiftData/PerformanceTesting/SwiftUsersTests.swift#L23
@afarnham I had the same issue myself: https://mastodon.social/@helge/110560249470460936
Oh, and in case someone needs a little larger #SwiftData database (or CoreData, have that too) for testing and doesn't want to wait 10 hours, I've packaged up a prefilled one: https://github.com/Northwind-swift/NorthwindSwiftData
@helge ah, got it. That’s crazy. Was about the embark on my first SwiftData experiment in an app and I need to ingest 2GB+ of data once every few weeks… maybe I won’t use SwiftData
@afarnham If it is 10 records w/ 200MB each, that might be OK Right now the situations where SwiftData would be a good choice still seem extremely limited (similar to CoreData). It doesn't scale well enough to even slightly bigger databases. And if the database is small, you just get a lot of complexity for sth you could also just load from a file.
@helge this seems to say Realm is fastest?
@JetForMe For this particular test, it seems like it. I don’t know enough about Realm to say why and how. I’ll see whether I get to actually try the more complex scenario later this week.
@helge So it's probably a good thing I'm sticking to Core Data and not jumping into SwiftData. Got it.
@JoshHrach I wouldn’t expect CoreData to be significantly better, might be worth a try (it is not a complex setup).
It was much better in my Northwind import months ago (but still really slow).