Distribute directly
C++ uses direct distribution by default, and can be changed to function table distribution with virtual modifier. Direct distribution is the fastest because there will be fewer calls and optimizations can also be performed through the compiler such as inline. The disadvantage is that inheritance is not supported due to lack of dynamicity.
struct DragonFirePosition { var x:Int64 var y:Int32 func land() {} } func DragonWillFire(_ position:DragonFirePosition) { () } let position = DragonFirePosition(x: 342, y: 213) DragonWillFire(position)
After compiling inline, DragonWillFire(DragonFirePosition(x: 342, y: 213)) will jump directly to the place where the method is implemented, and the result becomes ().
Function table distribution
Java defaults to the function table distribution used, and it is changed to direct distribution through the final modifier. Function table distribution is dynamic. In Swift, function tables are called witness tables, and most languages are called virtual tables. An array will be used to store function pointers in a class. The function of the parent class will replace the previous function. The functions added by the subclass will be added to this array. For example:
class Fish { func swim() {} func eat() { //normal eat } } class FlyingFish: Fish { override func eat() { //flying fish eat } func fly() {} }
The compiler will create witness tables for the Fish class and the FlyingFish class respectively. There are swim and eat functions in Fish's function table, and there are swim of the parent class Fish's function table, covering the parent class eat and newly added function fly.
When a function is called, it will first read the object's function table, then add the offset of the function based on the class address, and then jump to that address. From the perspective of compiled bytecode, it only reads and jumps twice, which is still slower than direct distribution.
Message distribution
This mechanism can change the behavior of functions at runtime, and both KVO and CoreData are used. By default, OC is the message mechanism used to distribute, and C is used to directly distribute to obtain high performance. Swift can support message distribution through dynamic modification.
When a message is distributed, the runtime will look up the called function according to the inheritance relationship. However, this is not efficient, so it is necessary to improve efficiency through cache, so that the search performance can be similar to function distribution.
Specific distribution
statement
Value types will be distributed directly. Both class or protocol extensions are distributed directly. class and protocol are function table distributions.
Specify the distribution method
- final: Let the functions in the class be distributed directly, so that the function will be dynamic and cannot be obtained during runtime.
- dynamic: The functions in the class can be distributed using the message mechanism, and the functions in the extension can be override.
Distribution optimization
Swift will optimize this. For example, if a function does not have override, Swift may use the direct distribution method. Therefore, if the attribute is bound to KVO, its getter and setter methods may be optimized to be directly distributed, resulting in the failure of KVO. So remember to add dynamic modification to ensure effectiveness. Swift should do more processing in this optimization later.
The above is a brief discussion of the detailed content of the Swift distribution mechanism. For more information about the Swift distribution mechanism, please pay attention to my other related articles!