Skip to content

Suboptimal compile times using 5.3.2 compiler #146

Closed
@iainsmith

Description

@iainsmith

While benchmarking a different project, I noticed that the compilation / type checking of StrideCollection.offsetBackward is the bottleneck when building swift-algorithms. On a 2019 8 Core MacBook Pro using Xcode 12.4 a small refactor reduced compiling Stride.swift from 6.5s -> 1s, so that it is no longer the bottleneck in the build graph.

Swift Algorithms version: 0.2.1/ main
Swift version:

Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
Target: x86_64-apple-darwin19.6.0

Checklist

  • If possible, I've reproduced the issue using the main branch of this package
  • I've searched for existing GitHub issues

Steps to Reproduce

  • Install and select the 5.3.2 toolchain
  • Update package.swift to include debug flags below
  • Compile in Xcode and navigate to Stride.swift -> StrideCollection.offsetBackward
  • View issues in Xcode
  • (Optional) Run xclogparser parse --project swift-algorithms --reporter html to generate the screenshots below
targets: [
    .target(
      name: "Algorithms",
      dependencies: [
        .product(name: "RealModule", package: "swift-numerics"),
      ],
      swiftSettings: [.unsafeFlags([
        "-driver-time-compilation",
        "-Xfrontend",
        "-debug-time-compilation",
        "-Xfrontend",
        "-debug-time-function-bodies",
        "-Xfrontend",
        "-debug-time-expression-type-checking",
        "-Xfrontend",
        "-warn-long-function-bodies=500",
        "-Xfrontend",
        "-warn-long-expression-type-checking=500",
      ])]),
    .testTarget(
      name: "SwiftAlgorithmsTests",
      dependencies: ["Algorithms"]),
  ]

Screenshots

xcode-type-checking

Before After
before-benchmark after-benchmark

Proposed fix

-    let distance = i == endIndex
-      ? -((base.count - 1) % stride + 1) + (n - 1) * -stride
-      : n * -stride
+    // We typically use the ternary operator but that stresses out the compiler.
+    // To avoid slow build times for consumers, we use the longhand below.
+    let distance: Int
+    if i == endIndex {
+      distance = -((base.count - 1) % stride + 1) + (n - 1) * -stride
+    } else {
+      distance = n * -stride
+    }

Expected behavior

Users build time shouldn't be unnecessarily impacted by using swift-algorithms.

Actual behavior

Builds for consumers are slower than necessary. As swift-algorithms is likely to be early in a dependency graph, this is likely to affect users overall build times.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions