Energy inefficiency in Xojo

If you participate in t’other forum, you may have seen an interesting thread, where I made a discovery with Xojo shell class. Several members advised me to file a feedback with Xojo, but I’ve become pessimistic and bitter about filing any kind of feedback with Xojo.

Today, I decided that I should at least give it “one more try”…

I’ve discovered the Xojo shell class is energy inefficient when running asynchronous tasks (and potentially workers). It’s been pointed out, that’s because the Xojo shell class replicates a shell and isn’t the best tool for running commandline apps.

When using NSTask (via declares) to run an asynchronous task, the calling application’s energy usage dropped by 90% ~ 98%. Another advantage of using NSTask is that I was able to request the macOS to run the executable on the efficiency cores of a ARMac, thus reducing energy usage even further.

There are two Xojo feedbacks for this functionality .
#26605 - NSTask functionality is required for running console applications in a Sandboxed application
#66317 - Add QualityOfService parameters to Xojo Workers and shells

If anyone is interested in using NSTask in their Xojo made applications, I have made available, the source code that I used for this test (and from within my application).

https://ohanaware.com/appkit/NSTaskEfficiencyTest.zip

I do hope that Xojo will either improve their Shell class or implement a NSTask class, so they can help Xojo customers reduce any wasted electricity.

9 Likes

I slapped together a little app using the traditional Shell method and indeed it is less efficient (at least on the Mac). Oddly, it gathers a lot less data than your method. I suspect there is something about the piping machinery Xojo uses to set up the Shell that causes /usr/bin/log to pause writing, while the NSTask infrastructure somehow buffers it more efficiently.

The efficiency gain isn’t huge, because the app only consumes 2-3% of my CPU while running and gathering data, but your app consumes a mere .4%, and every bit helps.

1 Like

Some notes on how I tested this.
My primary tests were done using a 1 minute timer, I pragmatically captured the number of interrupts and CPU time at the start and at the end of the minute.

Xojo Shell: ~ 50,000 wakeups, ~3.5 seconds of a CPU time.
NSTask (Most efficient): ~ 12 wakeups, as low as 0.01 seconds of CPU time…
NSTask (2nd efficient): ~ 20 wakups, as low as 0.06 seconds of CPU time.

While running the Shell test, I’ve seen the following message posted to the console log.

symptomsd[227:6d239c] [com.apple.symptomsd:debuggability] RESOURCE_NOTIFY trigger for My Application.debug [61292] (45001 CPU wakes over 143.00s seconds, violating limit of 45000 CPU wakes over 300.00s seconds)

Which also causes crashReporter to write a wakeups_resource.diag report… Thus increasing the machine’s energy usage.

The secondary tests were conducted in the application, which is left “running” for hours, because I didn’t cap how long the second tests ran for, I converted the results to CPU usage (apps CPU time / total CPU time).

Xojo Shell: 5.64% CPU usage.
NSTask (most efficient): 0.02% CPU usage.
NSTask (2nd Efficient): 0.11% CPU usage.

Huh? I didn’t even check that. I wonder if it’s because I’m capturing both the error output and standard output?

I also mention the “most efficient test”, because yes there is a way to do it even more efficiently, which is to only extract the data from the pipe at the end of the test, however after several hours I run into the max_buffer limitation on the pipe, and so I had to use the 2nd most efficient technique I’d researched.

It indeed may very, but you’re still using 80% less CPU and electricity.