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.