Performance in Large Datasets (SwiftUI+SwiftData app)

Hi everyone,

In the simple app below, I have a QueryView that has LazyVStack containing 100k TextField's that edit the item's content. The items are fetched with a @Query. On launch, the app will generate 100k items. Once created, when I press any of the TextField's , a severe hang happens, and every time I type a single character, it will cause another hang over and over again.

I looked at it in Instruments and it shows that the main thread is busy during the duration of the hang (2.31 seconds) updating QueryView. From the cause and effect graph, the update is caused by @Observable QueryController <Item>.(Bool).

  1. Why does it take too long to recalculate the view, given that it's in a LazyVStack? (In other words, why is the hang duration directly proportional to the number of items?)

  2. How to fix the performance of this app? I thought adding LazyVStack was all I need to handle the large dataset, but maybe I need to add a custom pagination with .fetchLimit on top of that? (I understand that ModelActor would be an alternative to @Query because it will make the database operations happen outside of the main thread which will fix this problem, but with that I will lose the automatic fetching of @Query.)

Thank you for the help!

import SwiftData
import SwiftUI

@main
struct QueryPerformanceApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .modelContainer(for: [Item.self], inMemory: true)
        }
    }
}

@Model
final class Item {
    var name: String

    init(name: String) {
        self.name = name
    }
}

struct ItemDetail: View {
    @Bindable var item: Item
    var body: some View {
        TextField("Name", text: $item.name)
    }
}

struct QueryView: View {
    @Query private var items: [Item]

    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(items) { item in
                    VStack {
                        ItemDetail(item: item)
                    }
                }
            }
        }
    }
}

struct ContentView: View {
    let itemCount = 100_000
    @Environment(\.modelContext) private var context
    @State private var isLoading = true

    var body: some View {
        Group {
            if isLoading {
                VStack(spacing: 16) {
                    ProgressView()
                    Text("Generating \(itemCount) items...")
                }
            } else {
                QueryView()
            }
        }
        .task {
            for i in 1...itemCount {
                context.insert(Item(name: "Item \(i)"))
            }
            try? context.save()
            isLoading = false
        }
    }
}
Performance in Large Datasets (SwiftUI&#43;SwiftData app)
 
 
Q