Weight/second live chart memory overload

Hi all,

I'm trying to implement a dynamic chart to log weight over time for an espresso app. I've been struggling to find recourses to plot a continuously updating chart so, I'm currently using a timer to append new data to an array and then redraw the chart.

Thats all working fine but, I'm getting 1GB< Memory usage after appending only 15 seconds worth of data at 10 datapoints/second. I would love to find a way to optimise this.

Data Format
struct weight_time:Identifiable {
    let id = UUID()
    let weight: Float
    let time: Double
}
var cList: [weight_time] = [ ]

Here is my main View Controller. There is some connect to scale stuff in there but, for testing I'm bypassing the scale data. All I'm doing is upon opening the view I'm:
starting a counter,
converting the counter to a min, sec ,millisec value,
appending time information from my counter to the array,
appending a random value from 1-10 as my mock weight data to the array,
calling my chart view because it lives in a different file

ChartVC
import UIKit
import AcaiaSDK
import SwiftUI
import Charts

    var cList: [weight_time] = []
    var timer: Timer!
    var count: Double!
    var timeInDouble: Double!
    var isCounting: Bool!
    var hideview: Bool = true
    

class ChartVC: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()   
    }
    
    override func viewWillAppear(_ animated: Bool) {
    }
    
    override func viewDidAppear(_ animated: Bool) {
        timeInDouble = 0
        count = 0
        createTimer()
        print("Timer Started")
        isCounting = true
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        if isCounting == true {
            timer.invalidate()
            print("Timer Stopped")
            isCounting == false
        }
    }
 
    
    func createTimer(){
        cList.removeAll()
        timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(counter), userInfo: nil, repeats: true)
    }
    
    @objc func counter(){
       
        count += 0.1
        let minutes = Int(count) / 60 % 60
        let seconds = Int(count) % 60
        let mil = Int(count*10) % 10
        //print(mil)
        let m_s = String(format:"%02i.%02i%01i", minutes, seconds,mil)
        timeInDouble = Double(m_s)
        //if mil == 1 {
             fillChart()
      //  }
        print(timeInDouble!)
    }
    
    func fillChart(){
        cList.append(weight_time(weight: Float(.random(in: 1...10)) , time: timeInDouble))
        setupView()
    }

// MARK: test Chart import
    func setupView(){
    
        let controller = UIHostingController(rootView: chartvalues())
        guard let chartView = controller.view else{
            return
        }
            view.addSubview(chartView)
            controller.view.isHidden = false
        
            chartView.snp.makeConstraints{make in
                
            make.centerY.equalToSuperview()
            make.leading.equalToSuperview().offset(15)
            make.trailing.equalToSuperview().inset(15)
            make.height.equalTo(300)
        }
    }
}
My chart

`import SwiftUI
import Charts
import Foundation
import AcaiaSDK
import UIKit

struct weight_time:Identifiable {
let id = UUID()
let weight: Float
let time: Double
}

struct chartvalues: View{
let testList = [
weight_time( weight: 0.0, time: 0.5),
weight_time(weight: 0.5, time: 1.0),
weight_time(weight: 1.2, time: 1.5),
weight_time(weight: 1.72, time: 2.0),
weight_time(weight: 2.8, time: 2.5),
weight_time(weight: 3.0, time: 3.0),
weight_time(weight: 4.25, time: 3.5),
weight_time(weight: 4.94, time: 4.0),
weight_time(weight: 5.62, time: 4.5),
weight_time(weight: 6.6, time: 5.0)

]


var body: some View{
    if cList != nil {
        Chart(cList){
            weight_time in
            LineMark(
                x: .value("Time", weight_time.time),
                y: .value("Weight", weight_time.weight)
            ).foregroundStyle(.red)
            
        }
    }
    
    //Text(cList)
}

}`

Hi @reinerterig,

Apple has asked that questions about their proprietary frameworks, including UIKit, SwiftUI, and Charts, be asked over at their own developer forums. These forums are meant to be about using the Swift programming language itself.

This question is mainly about creating a large array without memory getting out of control.

I'm happy to ask elsewhere if it is outside the scope of this forum.

In your timer proc you are calling "fillChart()" that besides appending an element to the data structure also doing this: "setupView()". I suggest not doing that, just insert the data (and follow the relevant to UIKit or SwiftUI rules to how that data change propagates and results in the subsequent UI update).

Your data structure is not huge:

struct weight_time:Identifiable {
    let id = UUID()
    let weight: Float
    let time: Double
}
var cList: [weight_time] = [ ]

at 10 FPS it would hardly grow faster than 1K per second. And you can make it smaller if needed (e.g. change id to an auto-incremented 32-bit integer, or use a smaller resolution (and bit size) time field.