[gsoc-2026] Task tracking , a few questions on design

Hi everyone,

I’m Ege Kaya, a final-year Computer Engineering student and I’m interested in the Task/TaskGroup tracking project.

I’ve been reading through the Concurrency runtime to understand where this could fit. From what I see:

  • Tasks could be added after task_create in swift_task_create_commonImpl

  • Removed in AsyncTask::~AsyncTask() before memory is freed

  • PrivateStorage seems like the right place for tracking data due to ABI constraints

  • Task IDs might work well for splitting/sharding

At first I thought about using a sharded structure with locks, but based on the concern about locking in the hot path (mentioned here [GSoC 2026] Task and TaskGroup tracking for Swift Concurrency - #3 by al45tair ), I’m now also looking into lock-free options. The tricky part seems to be safe removal.

A few questions:

  • Is there a rough target for acceptable overhead on benchmarks like TaskGroups.swift or AsyncTree.swift?

  • For a lock-free approach, is it okay if removal is more complex or slightly delayed?

  • For TaskGroups, is tracking the group itself (and using its existing child records) enough?

I’d appreciate feedback from anyone interested and I’ll tag the mentors as suggested. @al45tair @Mike_Ash

Thanks!
Ege

1 Like

Assuming you need tracking data in the AsyncTask itself, of course. Maybe you don't? It's worth contemplating.

I think we're interested in getting the overhead as low as possible; double-digit percentages would clearly be unacceptable, but I wouldn't say that e.g. less than 10% was a target. Ideally the overhead would be 0%, but that's unrealistic :slight_smile:

Possibly. The tracking here is mostly for debugging purposes — we want to be able to list the tasks that are still extant, but not necessarily scheduled onto a thread.

I think that's likely the case, yes.

Hi Alastair,

I’ve already submitted my formal proposal for the project, but I’ve been refining my thinking based on your feedback here and your earlier comments regarding the design space.

  1. On Storage & ABI:
    I initially leaned toward PrivateStorage to keep the tracking intrusive, but your point is well-taken. Moving to an external tracking structure (keyed by task identity) is a much cleaner way to sidestep ABI constraints entirely. I’m also weighing the trade-offs of a Swift-side implementation versus C++ for this; I’d like to see if we can maintain the necessary atomic performance while staying in Swift before committing to a runtime-level C++ solution, as you mentioned might be worth thinking about.
  2. On Implementation & Contention:
    To address your concern about "unintentionally serializing" execution through a single lock, I’m looking at a sharded design to distribute the synchronization load. My plan is to treat this as an empirical investigation: I’ll benchmark a sharded mutex approach against a more complex lock-free design (like a per-shard Treiber stack) using AsyncTree and TaskGroups. I want to find the simplest implementation that keeps the "hot path" overhead low before committing to high-complexity atomics.
  3. On Removal:
    The clarification that real-time precision isn't the priority for debugging is a huge help. That allows for a much more efficient, non-blocking destruction path. If the goal is debuggability, then a "lazy cleanup" or a deferred reclamation strategy is a great trade-off to ensure that a task finishing its work isn't stalled by registry overhead just to check out.

I've also outlined these as my initial "Phase 1" investigation goals in the proposal, and I’m looking forward to sharing some concrete benchmark data if the project moves forward!

1 Like