Host a separate server on the mobile app

I think I’m facing a real blocker :frowning:

I need to do some heavy calculations and they need to interface with custom native code.
Having the calculations on the UI thread will make the app unresponsive.
Having them in a web worker seems impossible, since native code can’t be accessed.

Now, wild thinking: Ionic hosts the mobile app in a http server.
Would it be possible to spawn a second such server and communicate between them with HTTP?
I think the encapsulation rules for web workers prevent the native access. So maybe a second server goes around that?
Anything that gives me a second thread with access to native code would be awesome.

Web workers are great, but they aren’t necessary for CPU-intensive tasks that you don’t want to block the UI. You can do what old-school MacOS used to call “cooperative multitasking”, whereby various processes periodically “yield”. This can be done either with Promises or Observables, and if you want to get fancy you can try to implement progress reporting.

The basic idea, though, is to create a “work context” object that encapsulates the current state of activity, a “doChunk” function that does whatever a single chunk of work constitutes (I try to keep these under 300ms).

Hm, thanks for the feedback.
This will be tricky to do right, to split it in adequately sized portions.
I benchmarked it and thought I was good to go, but then realized that the performance will probably be much different on a 3 year old android :frowning:

I hope that it’s doable, but it will be a huge liability once the calculations become more complex.
There might be atomic operations of huge latency, even on modern hardware.

Is there no proper way of doing this? Anything to get access to native code from a separate thread?
I guess this would be a huge amount of work to implement, but making it possible to call native code over HTTP would be great. This might be a very clean way of exposing plugins, instead of wiring them through to capacitor over a native bridge, host a REST API together with the app.

To be honest, this problem had me looking at other technologies again.
The flutter team does a lot of impressive propaganda…
But for what it’s worth, they have the exact same problem !?

Anyways I think that this can potentially be a strong limitation. Is there a way to be able to call platform plugins from a secondary isolate?

That’s also dealable. The way the Linux kernel (used to, at least) do this was to run a little performance test loop at the beginning in order to have a rough understanding of how fast the CPU does stuff. A technique I’ve used in the past is to split it into aggressively small portions, and then use a wall clock, so every time we get control of the CPU, we new Date(). Then on each micro-loop, we check to see if we’ve had control for >250ms (or whatever). If so, then we yield. Otherwise, do one more microtask and check again.

I guess this really comes down to how parallelizable your underlying problem is.

I guess beauty is in the eye of the beholder, but that sounds like a fair amount of overhead and potential security problems for not a lot of gain. The big problem with cooperative multitasking on MacOS was (IMHO) a tragedy of the commons. Each app cared more about its performance when it was in the foreground than it did the gestalt of the UX, so people didn’t call WaitNextEvent frequently enough. Also, since there was no memory protection, one NULL pointer dereference in one app crashed the whole OS. If you control all the competing tasks, you don’t have any incentive to compete against yourself, and so I still think the cooperative multitasking approach is going to be the most practical for you.

Thanks for the insights, this is really interesting.

When you say yield, in js this would literally be a yield, right?

No, sorry, that’s just what the old MacOS call used to be. I mean something like the “idler” from this SO question.

1 Like

Hi, I know nothing about the context of your app, but in the case the local processing power is not enough, could these calculations be done in the cloud with some cloud functions and get the results back to the app? Is that even a viable option in your case?

Cheers,
Gustavo.

I think Javascript has yield, too.
But it always returns a value and then you somehow have to discard that.

The pattern you have linked will be extremely useful, thanks a lot!!!

Hi Gustavo,

Sure I’ve thought about hosting it. But there are no ressources available for this. Except for some data logging the app must be entirely stand-alone.

@rapropos, after some experimentation, I think that your advice solves the problem.
So I’ll mark your answer as the solution :slight_smile:
Thanks again !