在 Swift 中通过计算属性访问静态属性效率低吗?
假设我有一些应该被视为类变量的常量。
static let constant1 = 1
static let constant2 = 2
static let constant3 = 3
为了访问 constant1
,我需要遍历该类,例如 OwnerClass.constant1
。
但我也可以通过计算属性访问它们。例如,
var constant1:Int { get{ return OwnerClass.constant1 }}
这样做是为了避免重复输入 OwnerClass.
。
但问题是,这样效率低吗?
Say I have some constants that should be treated as class variables.
static let constant1 = 1
static let constant2 = 2
static let constant3 = 3
In order to access constant1
, I need to go thru the class, like OwnerClass.constant1
.
But I can also access them thru computed properties. For example
var constant1:Int { get{ return OwnerClass.constant1 }}
This is done to avoid the need to type OwnerClass.
repetitively.
But the question is, is that inefficient?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
与大多数优化问题一样,这取决于您的精确代码和编译器的版本,而且我们不必猜测,我们可以检查。
我所说的“效率低下”是指“无法内联访问器调用”。
TL;DR 是:在几乎所有情况下,优化器都会以任何一种方式内联它。在某些特殊情况下,访问器版本不是内联的,例如,如果调用者位于顶层(不在函数内部)并且该类不是最终类。 (我不知道为什么这是一个极端情况;它可能是一个优化器错误。)
我对这是否是一个好的设计持中立态度。我对此很满意(我自己偶尔也会使用这种模式)。但我当然不会出于性能考虑而避免它。 (如果一个额外的函数调用会成为问题,无论如何您都需要手动优化。)
细节
与大多数优化/性能问题一样,这将取决于您的确切代码和编译器的版本。正如我所说,在某些极端情况下,这一点没有得到优化。我用 Swift 5.5.2 进行了测试。
首先,我创建了一个测试程序:
然后我用 OwnerClass 的几个版本检查了它(我使用 12345678 以便更容易在输出中找到):
唯一遇到问题的程序(例如,当我没有包装它时)全部在一个函数中),是带有访问器的非最终类。
为了了解优化器的作用,我使用 swiftc -emit-sil -O x.swift 进行编译。在所有情况下,这都是
f()
编译的结果:需要注意的重要一点是,常量 12345678 作为 %0 内联到函数中(包装到 %1 中),然后使用两次在%4和%6中调用
handle()
。不会调用访问器。 OwnerClass 甚至没有被引用(c
的创建被优化掉了)。As with most optimization questions, it depends on your precise code and the version of the compiler, and also we don't have to guess, we can check.
By "inefficient" I'm going to assume you mean "fails to inline the accessor call."
The TL;DR is: In almost all cases the optimizer will inline this either way. There are corner cases where the accessor version is not inlined, for example if the caller is at the top-level (not inside a function) and the class is non-final. (I don't know why that's a corner-case; it may be an optimizer bug.)
I'm neutral on whether this is a good design. I'm fine with it (and occasionally use this pattern myself). But I certainly wouldn't avoid it out of performance concerns. (In cases where one extra function call would be a problem, you're going to need to hand-optimize anyway.)
The details
As with most optimization/performance questions, it will depend on your exact code and the version of the compiler. As I said, there are some corner cases where this doesn't get optimized. I tested with Swift 5.5.2.
First, I created a test program:
Then I checked it with several version of OwnerClass (I use 12345678 to make it easier to find in the output):
The only one that ever had trouble (for example, when I didn't wrap it all in a function), was the non-final class with an accessor.
To see what the optimizer does, I compiled with
swiftc -emit-sil -O x.swift
. In all cases, this is whatf()
compiles to:The important thing to note is that the constant 12345678 is inlined into the function as %0 (wrapped into %1), and then it's used twice in %4 and %6 to call
handle()
. No calls are made to the accessor. OwnerClass isn't even referenced (the creation ofc
is optimized away).