Performance for Protocols that conforms AnyObject

This slides in WWDC24 showed that we can improve the generics's performance if we can settle with conditional conformance to AnyObject.

Can someone please share more details about what else will be improved if the generic conforms to AnyObject, except the run time cost needed to determine the MemoryLayout? I might be missing something here, but wouldn't class only generics have the same performance overheads from indirections such as using Value Witness Table, and TypeMetadata? If that's true, then the cost to compute the MemoryLayout is just suppose to be an one time cost right?

Another potential benefit I can see is that maybe we don't need existential containers any more if we have:
func foo(datas: [any ClassOnlyProtocol]) {}
Is that true from the actual implementation? Or maybe this is totally irrelevant.. Thank you in advance!

2 Likes

Class-only generics should be able to skip the value witness table entirely for many operations. For example, copying a struct requires copying each member of the struct individually, but copying an instance of a class is always the same: call swift_retain.

Now, sometimes calling swift_retain isn't what you wanted, either for performance reasons or semantic reasons, but if you're fine with that then being able to skip the VWT lookup is a nice bonus.

And yes, knowing the size ahead of time skips the need for existential boxes. Boxes containing a class instance are fairly efficient anyway since it can store up to 3 words inline, but not doing it at all is still better.

7 Likes

Understood. Then it feels like having the protocol / generic constrained by AnyObject is an additional trick we can do to improve the overall Generics performance on top of using @inlinable / CMO for specialization, which covered by multiple posts before. Thank you for explaining.