Why is this swift code so slow?

You find the code at git@github.com:tallinn1960/day9.git.

It contains Rust and Swift solutions for the Advent of Code 2023 Day 9 challenge, both parts each.

Benchmarks both on the Rust side using Criterion and on the Swift side using XCTest measure show that Swift performance is abysmal, 20 times slower than the Rust code. I can't figure out why that is. I made a branch swift-performance where the benchmarks can be built without the shenanigans needed for Rust/Swift interoperability.

Here is the correct link: GitHub - tallinn1960/day9

1 Like

Honestly, XCTest's measure method is pretty hard to use correctly.

For the results to be at all useful, those tests need to return in release mode with optimizations turned on. But the default test suites Xcode creates for you run in debug mode (which is the right choice, you want faster builds, and more debug information).

I'd suggest making a second test suite specific for performance, ensuring that optimizations are enabled, and checking your measurements then.

1 Like

As I recall, Rust has all functional operations like map lazy by default, while in Swift you need to opt-in using lazy evaluation with .lazy at the start, that should make a difference as you have a lot of chained operations there.

The numbers given are in release mode. Swift XCTest measurements are run by swift test -c release. On master, where Rust and Swift may call each other, both criterion and divan benchmarks give 2 ms for Swift, which again is build and tested in release mode. Rust needs about 110 µs for the same task.

Maybe give the benchmarks package a try, I’ve found that more reliable than XCTest.

2 Likes

I recommend starting with Instruments. Since the Time Profiler instrument is sampling-based, make sure to add an outer loop around your code that repeats enough times that it takes a couple of seconds to complete so you have accurate data. You can select the Time Profiler template, then pick your desired target binary. From there you can look at the flame graph (new in the Xcode 16 beta) or the call tree to see what part of your code is using the most time.

1 Like