Home > Software design >  Swift code nested If statement is very slow?
Swift code nested If statement is very slow?

Time:12-07

I have a code that looks like this:

var fullJSON = "["

let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Job")

do {
    if let jobs = try coreDataContext().fetch(fetchRequest) as? [Job] {
        
        // let jobs: [Job] = fetchCoreData(entity: "Job")
        for job in jobs {
            if let json = job.toJSON() {
                
                
               /*if (fullJSON.count > 1) {
                   
                   //print( "size of values is : \(fullJSON)" )
                   
                    //fullJSON  = ",\n "
                }*/
                fullJSON  = json
                
                //print( "size of values is : \(fullJSON)" )
            } else {
                print("COULDN'T JSON \(job.name ?? "")")
                callback("Error decoding \(job.name ?? "")")
                return
            }
        }
        
        fullJSON  = "]"
        
        API.sync(json: fullJSON) { (result) in
           DispatchQueue.main.async {
                if !result.success {
                    callback("Network error: "   result.error)
                    return
                }
                guard let jsonJobs = result.payload?["jobs"] as? [NSDictionary] else {
                    callback("Error parsing result"); return
                }
                
                //delete existing
                let existing: [Job] = self.fetchCoreData(entity: "Job")
                for item in existing {
                    self.coreDataContext().delete(item)
                }
                for job in jsonJobs {
                    let newJob = Job.init(context: self.coreDataContext())
                    newJob.load(job, context: self.coreDataContext())
                }
                
                
                try? self.coreDataContext().save()
                callback(nil)
            }
        }
    } else {
        callback("Error getting jobs")
    }
} 

When I run this code, it is very slow!

I've pin pointed the issue to this code:

if (fullJSON.count > 1) {
    fullJSON  = ",\n "
}

If I remove that code, everything is fast again!

I have no idea why that small part of the code makes everything so slow!

Can someone please advice on this?

CodePudding user response:

Valid comments regarding better approaches to your task, however...

Pretty certain the speed difference is in the use of:

if (fullJSON.count > 1) {

that .count is a very expensive operation.

Try adding this to a view controller. Each time you tap anywhere, we'll simulate your json activity by appending "ABC" to the string var.

The first loop uses your fullJSON.count to decide to add the ",\n"

The second loop uses a Bool variable to append the ",\n" only after the first time through.

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

    var fullJSON: String = ""
    
    var length1: Int = 0
    var length2: Int = 0

    var st1 = CFAbsoluteTimeGetCurrent()
    var st2 = CFAbsoluteTimeGetCurrent()
    var ed1 = CFAbsoluteTimeGetCurrent()
    var ed2 = CFAbsoluteTimeGetCurrent()

    st1 = CFAbsoluteTimeGetCurrent()
    fullJSON = "["
    for _ in 1...5000 {
        if fullJSON.count > 1 {
            fullJSON  = ",\n"
        }
        fullJSON  = "ABC"
    }
    ed1 = CFAbsoluteTimeGetCurrent()

    length1 = fullJSON.count
    
    var b: Bool = false
    
    st2 = CFAbsoluteTimeGetCurrent()
    fullJSON = "["
    for _ in 1...5000 {
        if b {
            fullJSON  = ",\n"
        }
        fullJSON  = "ABC"
        // we've gone through once
        b = true
    }
    ed2 = CFAbsoluteTimeGetCurrent()
    
    length2 = fullJSON.count
    
    print("Timing:", ed1 - st1, ed2 - st2)
    
    // to confirm we get same resulting string lengths
    print("Lengths:", length1, length2)
    
    print()
}

Here's what I get on 5 runs:

Timing: 0.5321569442749023 0.002187013626098633
Lengths: 24999 24999

Timing: 0.5368150472640991 0.0024269819259643555
Lengths: 24999 24999

Timing: 0.5297999382019043 0.002218961715698242
Lengths: 24999 24999

Timing: 0.5305029153823853 0.002167940139770508
Lengths: 24999 24999

Timing: 0.5307689905166626 0.0022219419479370117
Lengths: 24999 24999

This is, of course, not the ideal way to profile code, but we can easily see the big difference here.

  • Related