Skip to content

Commit c38adb5

Browse files
committed
[docs] Update optimization tips considering the presence of @_specialize.
1 parent 42db97f commit c38adb5

File tree

2 files changed

+41
-50
lines changed

2 files changed

+41
-50
lines changed

docs/Generics.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,8 @@ on Int), to an operation within a protocol (which requires indirection through
701701
the corresponding vtable), or to an operation on a generic type definition, all
702702
of which can be emitted as object code.
703703

704+
.. _generics-specialization:
705+
704706
Specialization
705707
--------------
706708

docs/OptimizationTips.rst

Lines changed: 39 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Writing High-Performance Swift Code
33
===================================
44

5-
.. contents::
5+
.. contents:: :local:
66

77
The following document is a gathering of various tips and tricks for writing
88
high-performance Swift code. The intended audience of this document is compiler
@@ -45,12 +45,13 @@ Whole Module Optimizations
4545
==========================
4646

4747
By default Swift compiles each file individually. This allows Xcode to
48-
compile multiple files in parallel very quickly. However, compiling each file
49-
separately prevents certain compiler optimizations. Swift can also compile
50-
the entire program as if it were one file and optimize the program as if it
51-
were a single compilation unit. This mode is enabled using the command
52-
line flag ``-whole-module-optimization``. Programs that are compiled in
53-
this mode will most likely take longer to compile, but may run faster.
48+
compile multiple files in parallel very quickly. However, compiling
49+
each file separately prevents certain compiler optimizations. Swift
50+
can also compile the entire program as if it were one file and
51+
optimize the program as if it were a single compilation unit. This
52+
mode is enabled using the ``swiftc`` command line flag
53+
``-whole-module-optimization``. Programs that are compiled in this
54+
mode will most likely take longer to compile, but may run faster.
5455

5556
This mode can be enabled using the Xcode build setting 'Whole Module Optimization'.
5657

@@ -331,64 +332,52 @@ generics. Some more examples of generics:
331332
// [Int]' types.
332333
myAlgorithm(arrayOfInts, arrayOfInts.length)
333334

334-
Advice: Put generic declarations in the same file where they are used
335-
---------------------------------------------------------------------
335+
Advice: Put generic declarations in the same module where they are used
336+
-----------------------------------------------------------------------
336337

337-
The optimizer can only perform specializations if the definition of the generic
338-
declaration is visible in the current Module. This can only occur if the
339-
declaration is in the same file as the invocation of the generic. *NOTE* The
340-
standard library is a special case. Definitions in the standard library are
341-
visible in all modules and available for specialization.
338+
The optimizer can only perform specialization if the definition of
339+
the generic declaration is visible in the current Module. This can
340+
only occur if the declaration is in the same file as the invocation of
341+
the generic, unless the ``-whole-module-optimization`` flag is
342+
used. *NOTE* The standard library is a special case. Definitions in
343+
the standard library are visible in all modules and available for
344+
specialization.
342345

343-
Advice: Allow the compiler to perform generic specialization
344-
------------------------------------------------------------
346+
Advice: Use @_specialize to direct the compiler to specialize generics
347+
----------------------------------------------------------------------
345348

346-
The compiler can only specialize generic code if the call site and the callee
347-
function are located in the same compilation unit. One trick that we can use to
348-
allow compiler to optimize the callee function is to write code that performs a
349-
type check in the same compilation unit as the callee function. The code behind
350-
the type check then re-dispatches the call to the generic function - but this
351-
time it has the type information. In the code sample below we've inserted a type
352-
check into the function "play_a_game" and made the code run hundreds of times
353-
faster.
349+
The compiler only automatically specializes generic code if the call
350+
site and the callee function are located in the same module. However, the programmer can provide hints to the compiler in the form of @_specialize attributes. See :ref:`generics-specialization` for details.
354351

355-
::
352+
This attribute instructs the compiler to specialize on the specified concrete type list. The compiler inserts type checks and dispatches from the generic function to the specialized variant. In the following example, injecting the @_specialize attribute speeds up the code by about 10 times.
356353

357-
//Framework.swift:
354+
::
358355

359-
protocol Pingable { func ping() -> Self }
360-
protocol Playable { func play() }
356+
/// ---------------
357+
/// Framework.swift
361358

359+
public protocol Pingable { func ping() -> Self }
360+
public protocol Playable { func play() }
361+
362362
extension Int : Pingable {
363-
func ping() -> Int { return self + 1 }
363+
public func ping() -> Int { return self + 1 }
364364
}
365-
366-
class Game<T : Pingable> : Playable {
365+
366+
public class Game<T : Pingable> : Playable {
367367
var t : T
368-
369-
init (_ v : T) {t = v}
370-
371-
func play() {
368+
369+
public init (_ v : T) {t = v}
370+
371+
@_specialize(Int)
372+
public func play() {
372373
for _ in 0...100_000_000 { t = t.ping() }
373374
}
374375
}
375376

376-
func play_a_game(game : Playable ) {
377-
// This check allows the optimizer to specialize the
378-
// generic call 'play'
379-
if let z = game as? Game<Int> {
380-
z.play()
381-
} else {
382-
game.play()
383-
}
384-
}
385-
386-
/// -------------- >8
387-
388-
// Application.swift:
389-
390-
play_a_game(Game(10))
377+
/// -----------------
378+
/// Application.swift
391379

380+
Game(10).play
392381

393382
The cost of large swift values
394383
==============================

0 commit comments

Comments
 (0)