New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SR-11335] excessive ARC on String algorithm #53736
Comments
Drive-by comment that this seems sensible to me at the moment: a Substring really is an independent entity that might escape and so it can't not retain its base while live. That does have unfortunate implications about passing around Substring rather than Range<String.Index>, though, and we definitely try to encourage the former. |
@belkadan Agreed. But I'd have expected that it does it once, not once per loop iteration. Note that it will only recurse if it actually finds Actually, I just found an even worse program (which operates only on substring): func find<S: StringProtocol>(_ string: S,
needle1: Character,
needle2: Character?,
needle3: Character?) -> String.Index? {
var index = string.startIndex
while index < string.endIndex {
if string[index] == needle1 {
if let needle2 = needle2 {
if find(string[string.index(after: index)...],
needle1: needle2,
needle2: needle3,
needle3: nil) == string.index(after: index) {
return index
}
} else {
return index
}
}
index = string.index(after: index)
}
return nil
}
let howMany = 1_000_000
let end = CommandLine.arguments.dropFirst().reduce(into: "") { $0.append($1) }
print("xx[\(howMany)]xx\(end)")
let s = String(repeating: "x", count: howMany) + end
if let found = find(s[...], needle1: "f", needle2: "o", needle3: "o") {
print(s[found ... s.index(after: s.index(after: found))])
} else {
print(":( didn't find foo")
} which (with the 3rd August master snapshot) is up to 4M retains (3M of them real ones, 1M for the String(repeating:count):
|
@swift-ci create |
@weissi can you submit this as a benchmark? It seems useful for us to track and seems like it would fit easily. |
@gottesmm sure, working on it now. |
Hm, I guess so. Even though |
Comment by Pop Flamingo (JIRA) Thanks to everyone for taking a look at this. In case somebody ever needs to check how this impacts the performance of the project @weissi linked, the master branch will probably have changed quite a lot in other to get rid of those performance bottlenecks the commit that will still expose the issue is this one : PopFlamingo/ParserBuilder@4ced9d2 |
Attachment: Download
Additional Detail from JIRA
md5: f85968cf346327433d0a176cb463e22d
Issue Description:
From the example program https://github.com/adtrevor/ParserBuilder which seems to retain a little to much, I compiled a reduced example which uses the same sort of things from the Swift language: Strings, Substrings,
index(after🙂
, (Sub)String subscript with index and (Sub)String subscript with a range.The algorithm is a simple algorithm to find the letters
foo
in a string that is 1M {{x}}s followed by a concatenation of all command line args.If we run this like this:
we see that this program calls swift_retain over
3M2M times (for a string that's 1M+3 characters long...) with roughly Xcode 11 beta 6.I think that's way too many.
With
swift-DEVELOPMENT-SNAPSHOT-2019-08-03-a.xctoolchain
the number of retains drops to2M1M, quite good but not good enough 😉.Update:
When running with
we can see that 1M of those retains are from
String(repeating: "x", count: howMany)
which I don't care much about.Xcode 11 beta 6ish has as expected two retains in
find
:The text was updated successfully, but these errors were encountered: