memory race on deep looper

Below is some simple code that does nothing, saves nothing. Yet the memory usage keeps rising. Am I missing something or is this a bug? The code requires 6 core CPU minimum. ContentView.swift

import SwiftUI
import Combine

struct ContentView: View {
    
    @EnvironmentObject var loopClass:LoopClass
    
    var body: some View {
        
        ProgressView(value: Float(loopClass.loop_count), total: Float(loopClass.max_loops) ).progressViewStyle(.circular).padding()
        
        Button("Run looper", action: {
            loopClass.loopFunc()
        }
        )
    }
}

LoopClass.swift

import Combine

class LoopClass: ObservableObject {
    @Published var loop_count = 0
    @Published var max_loops  = 0
    
    func loopFunc () {
        let loopSet = [ 1, 3, 5, 7, 11, 13 ]
        
        max_loops = Int(pow(Double(loopSet.count), 13.0))
        print("max_loops = \(max_loops)")
        
        for loop13 in loopSet {
            
            DispatchQueue.global().async {
                
                for loop12 in loopSet {
                    for loop11 in loopSet {
                        for loop10 in loopSet {
                            for loop9 in loopSet {
                                for loop8 in loopSet {
                                    for loop17 in loopSet {
                                        for loop16 in loopSet {
                                            for loop5 in loopSet {
                                                for loop4 in loopSet {
                                                    for loop3 in loopSet {
                                                        for loop2 in loopSet {
                                                            for loop1 in loopSet {
                                                                DispatchQueue.main.async{ self.loop_count += 1 }
                                                            }
                                                        }}}}}}}}}}}
            }   //  DQ
        }       //  for loop13
    }
}
Answered by DTS Engineer in 758530022

It’s hard to say exactly what’s going on here but I’m not surprised you’re seeing unbounded memory growth. You have multiple CPU cores rapidly dispatching work items asynchronously to the main queue. The main queue is serviced by the main thread, so only a single CPU core can pull work items off the queue to run them. That means you’re producing work items faster than you can consume them, so the queue will just keep growing.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

It’s hard to say exactly what’s going on here but I’m not surprised you’re seeing unbounded memory growth. You have multiple CPU cores rapidly dispatching work items asynchronously to the main queue. The main queue is serviced by the main thread, so only a single CPU core can pull work items off the queue to run them. That means you’re producing work items faster than you can consume them, so the queue will just keep growing.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Verified by commenting-out "DispatchQueue.main.async{ self.loop_count += 1 }"

A simple solution was to move the DQ between loop17 and loop16, the ProgressView works and no memory race.

Thanks Eskimo.

memory race on deep looper
 
 
Q