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-6823] [StringGuts] Bridging benchmark regressions #49372
Comments
Erik, do you think someone can help me find an alternative? We probably don't need all of the machinery of dynamic casts etc. This could just be a load of the meta type and pointer compare, but I couldn't get any alternatives to stick when I tried a month ago. |
(probably just silly ignorance of the right method on my part). Here's the relevant code: @_versioned
@inline(never) // Hide the CF dependency
internal
func _makeCocoaStringGuts(_ cocoaString: _CocoaString) -> _StringGuts {
if let ascii = cocoaString as? _ASCIIStringStorage {
return _StringGuts(ascii)
} else if let utf16 = cocoaString as? _UTF16StringStorage {
return _StringGuts(utf16)
} else if let wrapped = cocoaString as? _NSContiguousString {
return wrapped._guts
} else if _isObjCTaggedPointer(cocoaString) {
return _StringGuts(_taggedCocoaObject: cocoaString)
} _ASCIIStringStorage / _UTF16StringStorage are type aliases of a generic type: internal typealias _ASCIIStringStorage = _SwiftStringStorage<UInt8>
internal typealias _UTF16StringStorage = _SwiftStringStorage<UTF16.CodeUnit> Inside the disassembly, I see calls to getGenericMetadata and dynamicCastClass. Are we not statically producing meta types for those two? Can I force us to, or should I de-generic it? It's only generic for 1-byte vs 2-byte storage, and we could always duplicate code if we must. |
@swift-ci create |
I don't think that's a resilience thing, though I'm not 100% sure. I don't think generic types get statically instantiated, ever. You could avoid dynamicCastClass by using |
I'm trying that in #14148 it helps a tiny bit. Joe S., I looked into this further and there's definitely an extra retain/release pair inside makeCocoaStringGuts that's contributing here. I attached the disassembled CFG. There you can see CFCocoaStringCreateCopy creates a +1 reference and stores it in r14 (this is "immutableCopy" in the source). We bundle it up in a bridgeObject, which retains it again. Then, we release r14. Also notice that there's a constant folding opportunity here: loc_31878a's basic block calls retain on a known-value. Eliminating this makes the analysis simpler: the _swift_unknownRelease should be moved into loc_31878a, and the bridgeObject retain in loc_318775 is eliminated. |
That was harder to explain in prose than I thought. Attached a version with red lines through what should be eliminated and a green arrow for the move. |
Attachment: Download
Additional Detail from JIRA
md5: 9dfd601b63da74d8eacc0fdb401a3614
Issue Description:
Regression from #14046
When bridging in from Cocoa, we check to see if we were originally a Swift type. However, we’re drowning in dynamic type checks. We need a faster way of doing this. I was able to hack around about half this regression from ARC. There’s also still more ARC than strictly needed.
ObjectiveCBridgeStubFromNSString
I’m going to assume all of the following are the same issue, but I haven’t inspected each profile deeply yet. There’s a chance that fixing this won’t fix all of those, and if that’s the case we’ll spin off a separate JIRA.
ObjectiveCBridgeFromNSString
ObjectiveCBridgeFromNSArrayAnyObjectForced
ObjectiveCBridgeFromNSArrayAnyObjectToString
ObjectiveCBridgeFromNSStringForced
ObjectiveCBridgeFromNSArrayAnyObjectToStringForced
ObjectiveCBridgeFromNSSetAnyObjectToString
ObjectiveCBridgeToNSSet
ObjectiveCBridgeToNSDictionary
ObjectiveCBridgeStubFromNSStringRef
The text was updated successfully, but these errors were encountered: