i’ve been spending a couple of days debugging a memory leak in my application, which leaks over 300MB of memory per second. i was able to isolate the issue to a call to withTaskGroup(of:), which looks pretty much like this:
private
func peg<Client>( ... , using client:Client, as:Client.Type,
whenever instructions:
@Sendable () async -> (price:Decimal<Int64>, indicators:T)?)
async -> [Fill<T>]
where Client:Executor
{
let pollster:Task = .init
{
while self.closed < size
{
await self.poll(using: client)
}
}
while self.closed < size
{
...
}
...
let _:Void = await pollster.value
...
}
private
func poll<Client>(using client:Client) async
where Client:Executor
{
await withTaskGroup(of: Order.self)
{
(group:inout TaskGroup<Order>) in
for identifier:Int64 in self.orders.keys
{
group.addTask
{
await client.status(order: identifier)
}
}
for await order:Order in group
{
...
}
}
await Task.yield()
}
originally, i thought the issue was in the tasks being added to the task group, but i found that the memory leaks (at the same rate!) even when no tasks are added at all, and even when the return type is set to Void:
private
func poll<Client>(using client:Client) async
where Client:Executor
{
// still leaks!!!
await withTaskGroup(of: Void.self)
{
(group:inout TaskGroup<Void>) in
}
await Task.yield()
}
the only thing that stops the memory leak is removing the call to withTaskGroup(of:) entirely.
i have also tried profiling the application on MacOS with Instruments, but the memory leak does not seem to occur on MacOS, only on Linux builds.
i’m trying to build the toolchain locally in the meantime, but i’m running into SR-14710 :/ (symlinking .swiftenv to the toolchain didn’t work). the error output suggests the flag --skip-early-swift-driver, but this doesn’t seem to be a valid option for utils/build-toolchain. do you know of a workaround?
it is also complaining about .distcc/zeroconf/hosts contained no hosts; can't distribute work, but i am not even using the --distcc flag…