Skip to content

feat(minor): Use Swift 6's isolated(any) feature to unblock the main actor and run benchmarks in whatever isolation context they require (#358) - #359

Open
wadetregaskis wants to merge 2 commits into
ordo-one:mainfrom
wadetregaskis:main
Open

wadetregaskis wants to merge 2 commits into
ordo-one:mainfrom
wadetregaskis:main

Conversation

@wadetregaskis

@wadetregaskis wadetregaskis commented May 31, 2026

Copy link
Copy Markdown
Contributor

Description

See #358 for full details, but in short: previously, the main thread / actor was being blocked by a wait on a semaphore inside runAsync, which meant any benchmark which relied on executing something on the main thread / actor / queue would deadlock.

Now, the main actor / thread / queue is not blocked - and furthermore, benchmarks can annotate themselves with a global actor (e.g. @MainActor) and be run there directly, by the Benchmark framework.

How Has This Been Tested?

I added three new unit tests covering two critical cases:

  1. Make sure a @MainActor benchmark runs on the main actor.
  2. Make sure a 'regular' (no-specific-isolation) benchmark can hop to the main actor / queue explicitly. In both sync and async versions.

(hopefully the explicit-hop case is made uncommon by being able to just @MainActor the benchmark to begin with, but the big concern is the indirect use of code which does that, such as in some library or deep down a callchain)

Note: I've only tested this with Swift 6.2.4 on Sequoia.

Minimal checklist:

  • ✅ I have performed a self-review of my own code
  • N/A I have added DocC code-level documentation for any public interfaces exported by the package
  • ✅ I have added unit and/or integration tests that prove my fix is effective or that my feature works

…un benchmarks in whatever isolation context they require (ordo-one#358).
@supersonicbyte supersonicbyte changed the title Use Swift 6's isolated(any) feature to unblock the main actor and run benchmarks in whatever isolation context they require (#358) feat(minor): Use Swift 6's isolated(any) feature to unblock the main actor and run benchmarks in whatever isolation context they require (#358) Jun 3, 2026
@supersonicbyte

Copy link
Copy Markdown
Contributor

Awesome, thanks for the contribution!

Just a few concerns:

  • Should we also add the @isolated(any) annotations to the synchronous BenchmarkClosure so we capture isolation of sync functions? It would force us then to await them, since they could change the isolation, but then we would capture isolation even from functions like this:
let closure = { @MainActor in
   print("hello")
}
  • There are some convenience initializers in Benchmark+ConvinienceInitializers.swift which need additional @isolated(any) annotations in order to capture the isolation properly

  • With these changes we could should drop the Package@swift-5.9.swift and rename it to Package@swift-6.0.swift.

@hassila

hassila commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

I think we can drop pre 6.0 swift now if needed, no problem - in general the official stance is the last 3 major releases at any given time (same as most Apple projects).

@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.12230% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.50%. Comparing base (2f192a6) to head (b094c5a).

Files with missing lines Patch % Lines
Tests/BenchmarkTests/BenchmarkTests.swift 98.08% 2 Missing ⚠️
Sources/Benchmark/Benchmark.swift 94.74% 1 Missing ⚠️
Sources/Benchmark/BenchmarkRunner.swift 92.31% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #359      +/-   ##
==========================================
+ Coverage   69.27%   70.50%   +1.23%     
==========================================
  Files          35       35              
  Lines        3296     3393      +97     
==========================================
+ Hits         2283     2392     +109     
+ Misses       1013     1001      -12     
Files with missing lines Coverage Δ
Sources/Benchmark/BenchmarkExecutor.swift 87.67% <100.00%> (ø)
Sources/Benchmark/Benchmark.swift 68.63% <94.74%> (+6.90%) ⬆️
Sources/Benchmark/BenchmarkRunner.swift 59.80% <92.31%> (+2.04%) ⬆️
Tests/BenchmarkTests/BenchmarkTests.swift 98.70% <98.08%> (-1.30%) ⬇️

... and 1 file with indirect coverage changes

Files with missing lines Coverage Δ
Sources/Benchmark/BenchmarkExecutor.swift 87.67% <100.00%> (ø)
Sources/Benchmark/Benchmark.swift 68.63% <94.74%> (+6.90%) ⬆️
Sources/Benchmark/BenchmarkRunner.swift 59.80% <92.31%> (+2.04%) ⬆️
Tests/BenchmarkTests/BenchmarkTests.swift 98.70% <98.08%> (-1.30%) ⬇️

... and 1 file with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2f192a6...b094c5a. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants