|
2 | 2 | Writing High-Performance Swift Code
|
3 | 3 | ===================================
|
4 | 4 |
|
5 |
| -.. contents:: |
| 5 | +.. contents:: :local: |
6 | 6 |
|
7 | 7 | The following document is a gathering of various tips and tricks for writing
|
8 | 8 | high-performance Swift code. The intended audience of this document is compiler
|
@@ -45,12 +45,13 @@ Whole Module Optimizations
|
45 | 45 | ==========================
|
46 | 46 |
|
47 | 47 | 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. |
54 | 55 |
|
55 | 56 | This mode can be enabled using the Xcode build setting 'Whole Module Optimization'.
|
56 | 57 |
|
@@ -331,64 +332,52 @@ generics. Some more examples of generics:
|
331 | 332 | // [Int]' types.
|
332 | 333 | myAlgorithm(arrayOfInts, arrayOfInts.length)
|
333 | 334 |
|
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 | +----------------------------------------------------------------------- |
336 | 337 |
|
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. |
342 | 345 |
|
343 |
| -Advice: Allow the compiler to perform generic specialization |
344 |
| ------------------------------------------------------------- |
| 346 | +Advice: Use @_specialize to direct the compiler to specialize generics |
| 347 | +---------------------------------------------------------------------- |
345 | 348 |
|
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. |
354 | 351 |
|
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. |
356 | 353 |
|
357 |
| - //Framework.swift: |
| 354 | +:: |
358 | 355 |
|
359 |
| - protocol Pingable { func ping() -> Self } |
360 |
| - protocol Playable { func play() } |
| 356 | + /// --------------- |
| 357 | + /// Framework.swift |
361 | 358 |
|
| 359 | + public protocol Pingable { func ping() -> Self } |
| 360 | + public protocol Playable { func play() } |
| 361 | + |
362 | 362 | extension Int : Pingable {
|
363 |
| - func ping() -> Int { return self + 1 } |
| 363 | + public func ping() -> Int { return self + 1 } |
364 | 364 | }
|
365 |
| - |
366 |
| - class Game<T : Pingable> : Playable { |
| 365 | + |
| 366 | + public class Game<T : Pingable> : Playable { |
367 | 367 | 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() { |
372 | 373 | for _ in 0...100_000_000 { t = t.ping() }
|
373 | 374 | }
|
374 | 375 | }
|
375 | 376 |
|
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 |
391 | 379 |
|
| 380 | + Game(10).play |
392 | 381 |
|
393 | 382 | The cost of large swift values
|
394 | 383 | ==============================
|
|
0 commit comments