# \`Final\` Optimization Recommendations

**URL:** <https://forums.swift.org/t/final-optimization-recommendations/18835>\
**Category:** Using Swift\
**Tags:** documentation\
**Created:** [December 15, 2018, 12:38pm UTC](https://forums.swift.org/t/final-optimization-recommendations/18835 "2018-12-15T12:38:37Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rod\_Brown](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rod_brown/32/425_2.png) [@Rod\_Brown](https://forums.swift.org/u/Rod_Brown)\
**Post date:** [December 15, 2018, 12:38pm UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/1 "2018-12-15T12:38:37Z")

</div>

Hi there,

I’m just looking into recommendations for our team around optimizations.

In [this optimization guide](https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#unchecked-operations) it mentions the recommendation to add the `final` keyword to reduce dynamic dispatch. Through other talks and threads, it has also been mentioned that `final` is inferred during Whole Module Optimization builds for non-open classes as there is no possibility of overriding these classes after the fact.

Considering that WMO builds are the default for Xcode release builds now, should this guidance be updated to reflect that this is unnecessary in these circumstances?

I’ve noticed many workplaces I’ve written Swift code require prepending all classes with `final` as a matter of policy for the optimization potential. Doesn’t this setting, however, make such requirements redundant? Also, doesn’t this negate the power of the keyword in actually enforcing at compile time a restriction when it’s actually important that a class, property or method should not be overridden by subclasses?

I’m curious what those here who work on the language think the best recommendations are, and whether we could update documentation to clear this up.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [December 15, 2018, 3:29pm UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/2 "2018-12-15T15:29:39Z")

</div>

> [@Rod\_Brown](#):
>
> Considering that WMO builds are the default for Xcode release builds now, should this guidance be updated to reflect that this is unnecessary in these circumstances?
> 
> I’ve noticed many workplaces I’ve written Swift code require prepending all classes with `final` as a matter of policy for the optimization potential. Doesn’t this setting, however, make such requirements redundant? Also, doesn’t this negate the power of the keyword in actually enforcing at compile time a restriction when it’s actually important that a class, property or method should not be overridden by subclasses?

If preserving this optimization is important, then it _is_ important that a class not be overridden. If a co-worker subclasses your class in a different part of the project, then you lose any inferred optimization with no warning. This would be suboptimal if you were relying on it.

---

<div class="post-metadata">

**Author:** ![Rod\_Brown](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rod_brown/32/425_2.png) [@Rod\_Brown](https://forums.swift.org/u/Rod_Brown)\
**Post date:** [December 15, 2018, 8:59pm UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/3 "2018-12-15T20:59:47Z")

</div>

Absolutely. This would be another good example of using this keyword to ensure a component is not overridden when it must not be for specific reason.

I think this recommendation however has been misunderstood and led to many organizations instituting a global “tag everything as final for great optimisation”. This then reduces the value of the keyword in these cases.

---

<div class="post-metadata">

**Author:** ![nuclearace](https://avatars.discourse-cdn.com/v4/letter/n/51bf81/32.png) [@nuclearace](https://forums.swift.org/u/nuclearace)\
**Post date:** [December 15, 2018, 10:54pm UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/4 "2018-12-15T22:54:29Z")

</div>

I would say you should be using final regardless of the optimizations it enables. Generally it’s always best to avoid subclassing in Swift unless you really need it. A lot of tasks that normally would be expressed by subclassing can be better represented through protocols.

Having a mindset of classes should be final first makes it very clear you’re using classes for their reference semantics and not their inheritance capabilities.

---

<div class="post-metadata">

**Author:** ![Rod\_Brown](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rod_brown/32/425_2.png) [@Rod\_Brown](https://forums.swift.org/u/Rod_Brown)\
**Post date:** [December 15, 2018, 11:59pm UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/5 "2018-12-15T23:59:33Z")

</div>

That’s a highly opinionated programming style that tends not to scale well when utilizing existing frameworks. Also, this doesn't delineate between "we discourage subclassing as a design paradigm" and "this must not be subclassed for performance or other reasons". One clearly should have compiler assistance. The other might better be served by linting with something like SwiftLint.

That said, if this is the default for Swift, we should make final the default, and subclassable the option, not overburden everyone’s code with tons of annotations as “policy”, especially considering we get the optimization either way with WMO.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [December 16, 2018, 12:19am UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/6 "2018-12-16T00:19:04Z")

</div>

> [@Rod\_Brown](#):
>
> That’s a highly opinionated programming style that tends not to scale well when utilizing existing frameworks.

It is opinionated but it is not accurate to say it doesn’t scale well when utilizing existing frameworks. It is accurate to say that subclassing is required, but only subclassing of _framework_ classes, not your own classes. There is rarely a _need_ to write your own superclasses.

> [@Rod\_Brown](#):
>
> if this is the default for Swift, we should make final the default, and subclassable the option, not overburden everyone’s code with tons of annotations as “policy”

There many of us who wish `final` was the default and argued for exactly that in the early days of Swift Evolution, but I think that ship has sailed at this point.

---

<div class="post-metadata">

**Author:** ![Rod\_Brown](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rod_brown/32/425_2.png) [@Rod\_Brown](https://forums.swift.org/u/Rod_Brown)\
**Post date:** [December 16, 2018, 12:34am UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/8 "2018-12-16T00:34:25Z")

</div>

I personally disagree with this on a philosophical level, but I see the point.

Nevertheless, could we look to clarify the documentation around this to make it clear WMO also gives you these optimizations? It can be a little confusing. Most developers I've quizzed about their "tag everything as final" rule say they do so for the optimisation benefit, and are confused when I say "that comes for free anyway with the default optimisation."

That will then leave it more fairly for the developer's team to create policy with a more clear viewpoint of the reasons one might use this keyword.

---

<div class="post-metadata">

**Author:** ![David\_Smith](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/david_smith/32/37508_2.png) [@David\_Smith](https://forums.swift.org/u/David_Smith)\
**Post date:** [December 16, 2018, 7:25am UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/9 "2018-12-16T07:25:38Z")

</div>

Note the preface to that document "The intended audience of this document is compiler and standard library developers."

Since the standard library is not a standalone binary like an app is, even WMO can't give the compiler full visibility into the set of types. For a concrete example, I've recently been looking into overhead of Dictionary bridging in JSON decoding, and was able to get a significant performance win by forcing the compiler to generate a specialization of the bridging function for the [String:Any] case. If this code was inlined into WMO-compiled apps, that would have been unnecessary, but in non-inline library code it was worthwhile.

---

<div class="post-metadata">

**Author:** ![Rod\_Brown](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rod_brown/32/425_2.png) [@Rod\_Brown](https://forums.swift.org/u/Rod_Brown)\
**Post date:** [December 16, 2018, 7:41am UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/10 "2018-12-16T07:41:44Z")

</div>

Thanks for the pickup. That's a really good point that I didn't realise.

---

<div class="post-metadata">

**Author:** ![GregLeszek](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gregleszek/32/1853_2.png) [@GregLeszek](https://forums.swift.org/u/GregLeszek)\
**Post date:** [July 2, 2021, 11:50am UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/11 "2021-07-02T11:50:18Z")

</div>

> That’s a highly opinionated programming style

If an opinion is backed by some data or facts, it becomes an argument 🙂

Here is my little test of compiling Swift source files from clean, based on ~400 classes:  
Left side: all classes were marked as final  
Right side: final removed from all classes

| no final | all final |
| --- | --- |
| 49.6s | 39.9s |
| 41.5s | 44.1s |
| 50.6s | 40.1s |
| 49.3s | 38.2s |

Data set is small and I am not providing build configuration, etc, but that is intentional. All projects are different so results might vary. Making little test like the one above could drive the decision. There is no one size fits all.

---

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [July 2, 2021, 6:02pm UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/12 "2021-07-02T18:02:34Z")

</div>

In order to narrow down the performance here, I adapted a previous benchmark to generate 1000 classes, either final or not, and compile them.

```python
#!/usr/bin/env python3
import os

filenames = ["class", "final"]
code = [
  'class A{} {{}}',
  'final class B{} {{}}'
]

for (i, filename) in enumerate(filenames):
    with open(filename + ".swift", "w") as f:
        s = ""
        for j in range(1000):
            s += (code[i] + '\n').format(j)
        f.write(s)
    os.system("hyperfine 'xcrun swiftc {}' --warmup 2".format(filename + ".swift"))

```

Results say they're equivalent as far as compilation speed goes:

```swift
Benchmark #1: xcrun swiftc class.swift
  Time (mean ± σ): 1.285 s ± 0.015 s [User: 1.210 s, System: 0.079 s]
  Range (min … max): 1.260 s … 1.314 s 10 runs
 
Benchmark #1: xcrun swiftc final.swift
  Time (mean ± σ): 1.276 s ± 0.011 s [User: 1.201 s, System: 0.078 s]
  Range (min … max): 1.260 s … 1.293 s 10 runs

```

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [July 2, 2021, 8:21pm UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/13 "2021-07-02T20:21:00Z")

</div>

I wouldn't expect `final` to have a large impact on compile times. It'll eliminate some small overheads proportionate to the number of dynamically-dispatched methods, but that's not really where the compiler is spending most of its time; mostly it'll save time by decreasing code size and thus requiring less I/O. It can also create optimization opportunities, which can always be a compile-time trade-off: you do more work to do the optimization, but maybe it means you shrink the code and later stages go faster.

---

<div class="post-metadata">

**Author:** ![iAshraf](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/iashraf/32/21109_2.png) [@iAshraf](https://forums.swift.org/u/iAshraf)\
**Post date:** [December 27, 2021, 10:58am UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/14 "2021-12-27T10:58:15Z")

</div>

As mentioned in the guide " **This mode is enabled using the `swiftc` command line flag `-whole-module-optimization` . Programs that are compiled in this mode will most likely take longer to compile, but may run faster**."  
So, why not add `final` manually and enjoy optimized compile time and run time 🙂

---

<div class="post-metadata">

**Author:** ![Saklad5](https://avatars.discourse-cdn.com/v4/letter/s/4491bb/32.png) [@Saklad5](https://forums.swift.org/u/Saklad5)\
**Post date:** [December 27, 2021, 2:13pm UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/15 "2021-12-27T14:13:46Z")

</div>

Personally, I treat `final` as a default, to be removed as needed. To a lesser degree, I do the same with `private`.

As a rule, making stronger guarantees allows the compiler to optimize _much_ more aggressively.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [December 27, 2021, 7:04pm UTC](https://forums.swift.org/t/final-optimization-recommendations/18835/16 "2021-12-27T19:04:42Z")

</div>

FWIW, the reason `final` isn’t the default is mostly for modules with library evolution enabled, because clients will skip dynamic dispatch for those classes. But it matters even for regular public classes when it comes to adding protocols: a final class does not need `required` initializers to satisfy protocol requirements (because there are no subclasses). So removing `final` from a public class is a breaking change even for libraries without binary compatibility concerns.
