Improving Swift Charts performance

Viewed 79

I want to make a Swift Chart that updates on each frame - I expect to be monitoring a data source that updates constantly. I've made a little demo view to do this, but CPU usage is through the roof - a constant 90%

What can I do to play more nice with SwiftUI and bring the CPU usage down to a more modest level, yet still update at screen refresh rate?

My example is here:

import SwiftUI
import Charts

struct DataPoint: Identifiable {
    var id: Int { return x }
    
    let x: Int
    let y: Float
}

class ViewModel: ObservableObject {

    @Published var data: [DataPoint] = []
    
    init() {
        data = _regen()
        
        Task {
            await loop()
        }
    }
    
    func regen() {
        data = _regen()
    }
    
    func loop() async {
        try? await Task.sleep(nanoseconds: 1_000_000_000 / 120)
        Task { @MainActor in
            regen()
        }
        await loop()
    }
    
    private func _regen() -> [DataPoint] {
        let start = Int(Date().timeIntervalSince1970 * 60) % 100
        let end = start + 300
        let vals: [DataPoint] = (start..<end).map {
            DataPoint(x: $0, y: sin(Float($0) / 10.0))
        }
        return vals
    }

}

struct ContentView: View {
    
    
    @ObservedObject var viewModel: ViewModel = ViewModel()
    
    var body: some View {
        VStack {
            
            Chart(viewModel.data) {
                LineMark(
                    x: .value("", $0.x - viewModel.data[0].x),
                    y: .value("Value", 1-($0.y))
                )
            }

            Chart(viewModel.data) {
                LineMark(
                    x: .value("", $0.x - viewModel.data[0].x),
                    y: .value("Value", $0.y * 0.2)
                )
            }

            Chart(viewModel.data) {
                LineMark(
                    x: .value("", $0.x - viewModel.data[0].x),
                    y: .value("Value", $0.y)
                )
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
0 Answers
Related