BGContinuedProcessingTask what's the point?

Hi,

This post is coming from frustration of working on using BGContinuedProcessingTask for almost 2 weeks, trying to get it to actually complete in the background after the app is backgrounded.

My process will randomlly finish and not finish and have no idea why.

I'm properly using and setting

task?.progress.totalUnitCount = [some number] task?.progress.completedUnitCount = [increment as processed]

I know this, because it all looks propler as long as the app insn't backgrounded. So it's not a progress issue. The task will ALWAYS complete.

The device has full power, as it is plugged in as I run from within Xcode. So, it's not a power issue.

Yes, the process will take a few minutes, but I thought that is BGContinuedProcessingTask purpose in iOS 26. For long running process that a user could place in the background and leave the app, assuming the process would actually finish.

Why bother introducing a feature that only works with short tasks that don't actually need long running time in the first place.

My process will randomlly finish and not finish and have no idea why.

What do you mean by "not finish"? Is it expiring or is something else happening?

I know this, because it all looks propler as long as the app isn't backgrounded. So it's not a progress issue. The task will ALWAYS complete.

What actually happens when you enter the background? Also are you locking the device or switching over to other apps? I'm double checking, but I think we may expire tasks on device lock.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

What do you mean by "not finish"? Is it expiring or is something else happening?

It is expiring and calling the expirationHandler.

What actually happens when you enter the background? Also are you locking the device or switching over to other apps? I'm double checking, but I think we may expire tasks on device lock.

I'm just sitting in the Springboard watching the progress indicator move forward. It looks to be moving slowly because 5000 items are being processed, but there is constant movement. The device is not being locked, nor am I opening another app. I haven't gotten that far yet.

Thoughts?

It is expiring and calling the expirationHandler.

Huh. How long does it take to expire once you enter the background? What does the console log show (particularly from "duet") when your task is expired?

I'm just sitting in the Springboard watching the progress indicator move forward. It looks to be moving slowly because 5000 items are being processed, but there is constant movement. The device is not being locked, nor am I opening another app. I haven't gotten that far yet.

As background context, what's the work you're actually "doing"?

Thoughts?

A few different questions/suggestions:

  • How fast is that progress in real-world terms?
  • How long does it take to process "one" item?
  • How often are you updating progress?

Ruling out the obvious, what happens if you reduce the work such that you make "rapid" progress, both in terms of how long you take to complete and how frequently you report progress?

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Huh. How long does it take to expire once you enter the background? What does the console log show (particularly from "duet") when your task is expired?

It can be a few minutes. I haven't time it.

As background context, what's the work you're actually "doing"?

I'm curious to why this would make a difference. It is running a long initial sync of data loading data into CoreData from a server. It almost always dies when trying to load relationships into CoreData. We are talking about 7000 plus relationship connections.

How fast is that progress in real-world terms?

A minute or two.

How long does it take to process "one" item?

A fraction of a second, I don't have exact times.

How often are you updating progress?

Many times a second.

if you reduce the work such that you make "rapid" progress, both in terms of how long you take to complete and how frequently you report progress?

I can't reduce how long it takes to update CoreData, On an initial sync, it's all or nothing; otherwise data will be corrupted.

I broke up the work to advance the progress bar, showing faster updates. Example, 1000 at a time, updating from 0 to 1000. The user feedback is noticeably faster, but the expirationHandler still gets called.

This initial sync is rare from a user perspective. Some may never have initial syncs that will take 2-3 minutes.

Question is 2-3 minutes outside the use case for this new feature?

So, let me start by jumping to the immediate point here:

This initial sync is rare from a user perspective. Some may never have initial syncs that will take 2-3 minutes. Question is: 2-3 minutes outside the use case for this new feature?

No, not at all. We can't guarantee any specific time, but there isn't any artificial throttle on timing and, theoretically, a task could run for an hour+ under the right circumstances. On an idle device as you're describing, 2-3 min. should have been fine.

The next step here is to figure out what duet logged when we expired the task.

Huh. How long does it take to expire once you enter the background? What does the > console log show (particularly from "duet") when your task is expired?

It can be a few minutes. I haven't timed it.

OK. So the key here is that it's long enough that the processing task is keeping your app alive, at least some of the time.

As background context, what's the work you're actually "doing"?

I'm curious to why this would make a difference. It is running a long initial sync of data loading data into CoreData from a server. It almost always dies when trying to load relationships into CoreData. We are talking about 7000 plus relationship connections.

The specifics on their own don't matter, but the larger context often helps catch issues that would otherwise be missed.

Case in point:

How fast is that progress in real-world terms? A minute or two.

How long does it take to process "one" item? A fraction of a second, I don't have exact times.

How often are you updating progress? Many times a second.

All other issues aside, this is something you need to take a closer look at. One of the common traps that is easy to accidentally fall into is updating progress on "computer time" not "real world time". The back of the envelope math here is:

7000 ("event count")/ 120s (2 minutes) = 58 updates/sec.

That's FAR faster than it needs to be. This might seem irrelevant, but every progress update involves a certain amount of locking (to protect the values), inter-thread communication (shifting the data to the "working" thread), and IPC (to update the visible interface). That can VERY easily steal a LOT more performance than you'd realize.

My general rule of thumb here is to update progress 2-10x/sec., assuming "meaningful" progress occurs over that time span. That's generally a good balance between looking smooth and not throwing away cycles.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Kevin,

When you as for duet log are you refering to the logs from this:

What is duetexpertd?

  • It's a background daemon (part of Apple's "Duet" proactive intelligence framework) that handles personalized features and data syncing across iOS and macOS.

When I talk of syncing it is our own syncing process and not iCloud syncing.

Regarding your last point, about human time vs computer time, I will look into reporting process on human time.

When you ask for duet log, are you referring to the logs from this:

No, what I actually meant was "dasd" ("Duet Activity Scheduler Daemon"). I confess that I generally "get" to it from other processes* and didn't actually remember the daemon's name as I was writing that.

*Meaning, I start by finding the task logging from the source process and then trace that activity back or forward "into" dasd.

What is duetexpertd? It's a background daemon (part of Apple's "Duet" proactive intelligence framework) that handles personalized features and data syncing across iOS and macOS.

Yeah... that does not describe what it actually "does". I believe it's actually responsible for collecting and managing the on-device usage data that the device uses for things like intelligent app suggestions, etc. I have no idea where the idea it was involved with data syncing came from, but no, that's not at all what it does.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

BGContinuedProcessingTask what's the point?
 
 
Q