Open Lukasa opened 4 years ago
@swift-ci create
@swift-ci create
I have a feeling that we may support this now. Let me check. Just starting a build of swift on my side machine.
Yes. This is fixed. I just tried with snapshot from 03/04
// main(_:)
sil hidden [noinline] @$s4test4mainySi7testlib3FooVzF : $@convention(thin) (@inout Foo) -> Int {
// %0 // users: %2, %1
bb0(%0 : $*Foo):
debug_value_addr %0 : $*Foo, var, name "f", argno 1 // id: %1
%2 = load %0 : $*Foo // user: %4
// function_ref Foo.bar.getter
%3 = function_ref @$s7testlib3FooV3barSivg : $@convention(method) (@guaranteed Foo) -> Int // user: %4
%4 = apply %3(%2) : $@convention(method) (@guaranteed Foo) -> Int // users: %6, %5
debug_value %4 : $Int, let, name "result" // id: %5
return %4 : $Int // id: %6
} // end sil function '$s4test4mainySi7testlib3FooVzF'
This was fixed by:
Hmmm... actually I just handled the case where there aren't any writes to the function at all. I have a plan for implementing the case with writes, but it will take more work. I think having the requirement of no writes is not predictable and unexpected for users. Going to unresolved this.
NOTE: I had a different radar internally for tracking this work (including the write case). I duped the original radar in this SR to the one I am actually using for the work, so I updated the radar in this SR to be the actual tracking radar.
Attachment: Download
Environment
Apple Swift version 5.1.1 (swiftlang-1100.0.275.2 clang-1100.0.33.9) Target: x86_64-apple-darwin19.0.0Additional Detail from JIRA
| | | |------------------|-----------------| |Votes | 1 | |Component/s | Compiler | |Labels | Bug, Performance | |Assignee | @gottesmm | |Priority | Medium | md5: fe768e083fde0dd0bb93966e9182970cIssue Description:
Consider a SwiftPM package that defines two modules. The first is called
testlib
, and contains the following code:The second module is an executable called
test
, which is defined like so:This program creates a
Foo
, passes itinout
to a function, and then calls anon mutating
get accessor onFoo
. This code performs some excessive retains/releases intest.main
, which when disassembled looks like this:In this case, a
swift_retain
is performed before the invocation of the computed property.This seems excessive: it seems like the natural semantic for a nonmutating get accessor would be to assume that the reference currently held by the calling function ought to be sufficient to cover the computing needs of that accessor. I'd have assumed, then, that nonmutating calls should be passed self at
+0
and can retain self if they need to.The result of this is that repeated calls to computed properties incur substantial ARC traffic. For example, if we called
Foo.bar
in a loop, we will retain/release once per loop invocation.In the case of a computed property as simple as
Foo.bar
the cost of these retain/release operations will strictly dominate the actual calculation of the computed property.This is non-theoretical: SwiftNIO issue 1218 covers a feature request to have SwiftNIO add an "unsafe" equivalent of its ByteBuffer type to elide refcounting overhead in a parse-heavy loop. The ARC overhead here came entirely from accessing non-inlinable computed properties: making them inlinable halved the runtime of the program and elided the ARC traffic almost entirely. It would be good if we didn't have to make these properties inlinable to allow the compiler to see that they don't need self at
+1
.I've attached a sample project.