Skip to content
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-13221] No type erasure technique both specializes and generalizes to multiple operations #55661

Open
dabrahams opened this issue Jul 15, 2020 · 2 comments

Comments

@dabrahams
Copy link
Collaborator

@dabrahams dabrahams commented Jul 15, 2020

Previous ID SR-13221
Radar None
Original Reporter @dabrahams
Type Bug
Additional Detail from JIRA
Votes 1
Component/s Compiler
Labels Bug, Generics, Optimizer, Performance
Assignee None
Priority Medium

md5: 9c1d28b2fc80561734765c514037f198

Issue Description:

This gist is a survey of known type erasure techniques along with a performance analysis.

Build with swiftc -O -g -whole-module-optimization.

Set a breakpoint on line 17 and issue “disassemble” to LLDB when you hit it to inspect
the code generated for cases that I've noted fail to specialze.

The techniques that do specialize properly have the drawback of being poorly suited to type erasure over more than one operation. A manually-created table of functions would incur lots of ARC and can't be initialized in a static member of a generic type, which would lead one to build a threadsafe dictionaries mapping types to function tables—the kind of thing the runtime library implements—which users shouldn't have to build.

@dabrahams
Copy link
Collaborator Author

@dabrahams dabrahams commented Jul 15, 2020

@karwa
Copy link
Contributor

@karwa karwa commented Oct 3, 2020

BTW, this is really bad for ManagedBuffer subclasses. It means their deinitializer is always called, even for trivial element types, and things like accessing the 'count' of initialized elements from the header can be extremely expensive (again, isn't specialised - but I think it is inlined? I was storing my count as a UInt8 and saw lots of unspecialised generic integer methods for the widening to Int).

I'm currently working around it using the private _isPOD function :S

deinit {
      // Swift does not specialize generic classes at all right now (!).
      // That means this deinit will never be eliminated, and even querying `.count`
      // can be very expensive.
      if Swift._isPOD(Element.self) == false {
        _ = withUnsafeMutablePointers { headerPtr, elemsPtr in
          elemsPtr.deinitialize(count: headerPtr.pointee.count)
        }
      }
    }

But it's still not amazing. I still get calls to objc_destructInstance, for example. It does noticeably reduce the cost of destroying buffer objects, though.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants