I've this code and its taking a lot of time to execute in swift? Each iteration takes 1 second to execute, Why?
CPU Percentage while executing that loop is 97-98% and energy impact is High
Here is the Code
var braces:Int = 1;
var i:Int = startIndex;
let jsFileChars = Array(javascriptFile);
while(i < javascriptFile.count){ //count:1240265
if (braces == 0) {
break;
}
if (jsFileChars[i] == "{"){
braces = braces+1;
}else if (jsFileChars[i] == "}"){
braces = braces-1;
}
i = i+1;
}
This loop is iterated on a very slow pace, why?
The loop is slow because determining the count
of a Swift string is a
O(N) operation, where N is the number of characters in the string.
See also Counting Characters in “The Swift Programming Language”:
NOTE
Extended grapheme clusters can be composed of multiple Unicode scalars. This means that different characters—and different representations of the same character—can require different amounts of memory to store. Because of this, characters in Swift don’t each take up the same amount of memory within a string’s representation. As a result, the number of characters in a string can’t be calculated without iterating through the string to determine its extended grapheme cluster boundaries. ...
Replacing javascriptFile.count
by jsFileChars.count
should already
improve the performance, because the length of an array is determined in
constant time.
Even better iterate over the characters directly, without creating an array at all:
var braces = 1
for char in javascriptFile {
if char == "{" {
braces += 1
} else if char == "}" {
braces -= 1
}
}
Iterating over the UTF-16 view is even faster, because that is what Swift strings (currently) use as internal storage:
let openingBrace = "{".utf16.first!
let closingBrace = "}".utf16.first!
var braces = 1
for char in javascriptFile.utf16 {
if char == openingBrace {
braces += 1
} else if char == closingBrace {
braces -= 1
}
}
When you're thinking of iterating over a collection in Swift (and a String is a collection of characters), it's sometimes faster to use reduce()
instead. You can implement your brace counter using reduce()
like this:
let braces = javascriptFile.reduce(0, { count, char in
switch char {
case "{": return count + 1
case "}": return count - 1
default: return count
}
})
I don't know if that'll actually be faster than using a for
loop in your case, but might be worth a try. If nothing else, the intent is very clear when written this way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With