Fork me on GitHub
#planck
<
2016-06-09
>
johanatan02:06:16

@mfikes: another interesting discovery

johanatan02:06:00

I'm finding that when I issue an 'sh' with a long-running CPU-bound command (5-10 seconds on average), planck itself also uses 100% CPU. That doesn't seem right to me

johanatan02:06:04

Any idea why that would happen?

johanatan02:06:36

[I have 8 cores and end up using 200/800% during each of these-- 100% for each of planck and the command executed]

mfikes02:06:16

@johanatan: Does the command itself emit a lot to stdout?

johanatan02:06:32

@mfikes: nope, it's emitting nothing

mfikes02:06:18

I agree. That does appear to be odd. There are a few bugs surrounding sh, this one being the most troubling: https://github.com/mfikes/planck/issues/88

johanatan02:06:24

did you try reproducing?

mfikes02:06:24

Feel free to log an issue… I plan to continue to work on sh until it is bug free

mfikes02:06:37

Can’t yet (busy)

johanatan02:06:46

ahh, ok. i will file an issue. thx!

johanatan19:06:12

@mfikes: I filed the issue and am now thinking that I'd like to take a stab at solving it. Do you have any tips/advice for how to approach this one?

mfikes19:06:28

@johanatan: There is a Wiki page here describing stuff surrounding building Planck: https://github.com/mfikes/planck/wiki/Development

johanatan19:06:08

ahh, this is the problem

johanatan19:06:19

"polls the current run loop until the class exits"

mfikes19:06:20

Other than that, it is using a fairly standard-looking way to launch processes

mfikes19:06:07

If there is a better way, perhaps some other mechanism could be used, one that also doesn’t hang like NSTask appears to do

mfikes19:06:42

Give it a shot 🙂 There are definitely issues with the way it is currently being done.

johanatan19:06:14

How is that even valid Objective-C?

johanatan19:06:19

[Also throughout the file]

johanatan19:06:46

Oh, nevermind.

johanatan19:06:58

I see the close square bracket corresponds to line 172

mfikes19:06:09

🙂 Obviously I don’t give much concern about the gracefulness of that code

mfikes19:06:34

It is all just a means to make ClojureScript available 🙂

johanatan19:06:51

Do you have any example in the code where an async method call from JS -> Obj-C -> JS is performed?

johanatan19:06:01

[i.e., an Obj-C func that accepts a JS callback]

johanatan19:06:10

That's probably what we'd have to do here I think.

mfikes19:06:42

I think perhaps the timer callbacks are the only place

mfikes19:06:01

If planck.shell/sh gains async, we’d have to figure out a way to support the older sync interface, and also, play the same trick to keep Planck processing alive when there are outstanding async tasks

johanatan19:06:43

Actually I just thought of a simpler solution

johanatan19:06:49

[for sync only]

johanatan19:06:23

So, just replace the call to 'waitUntilExit' (which stupidly polls killing the CPU) with use of dispatch_semaphore .

johanatan19:06:35

We'd still be 'blocking' but we wouldn't eat the CPU up while doing so. 🙂

mfikes19:06:56

Worth a try

johanatan19:06:27

[but yes going forward when the time is right for async, i think we'd want to follow the pattern of the timers on the js -> objc bridge side of things and use core.async/andare on the JS side]

johanatan19:06:52

Ok, I'll give it a shot. Pretty sure it will work.

mfikes19:06:19

Maybe there’s a slight chance something like that will fix #254

mfikes19:06:20

The real problem (apart from hogging some CPU) is the inexplicable hanging that occurs if you try to use Planck to, say, run something that does a maven build or lein build, which makes it hard to use Planck to automate dev stuff

mfikes19:06:27

(That’s #88)

johanatan19:06:47

These changes didn't help the CPU usage:

Jonathans-MacBook-Pro:planck jonathan$ git diff
diff --git a/planck/PLKSh.m b/planck/PLKSh.m
index 4e4b8b1..9387b26 100644
--- a/planck/PLKSh.m
+++ b/planck/PLKSh.m
@@ -111,11 +111,17 @@ NSDictionary* cljs_shell(NSArray *args, id arg_in, NSString *encoding_in, NSStri
         [errData appendData:data];
         [errLock unlock];
     }];
-    
+
+    NSLog(@"doing semaphore thingie\n");
+    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+    aTask.terminationHandler = ^(NSTask *task) {
+      dispatch_semaphore_signal(sema); };
+
     // We'll block during execution
     @try {
         [aTask launch];
-        [aTask waitUntilExit];
+        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
+        NSLog(@"done doing semaphore thingie\n");
     }
     @catch (NSException *exception) {
         return @{@"exit": @(-1),

johanatan20:06:43

Looks like internally that method dispatch_sempahore_wait also polls 😮

johanatan20:06:37

[According to 'Barry' on this page: http://stackoverflow.com/questions/4326350/how-do-i-wait-for-an-asynchronously-dispatched-block-to-finish , quote: "Yep, this is ghetto polling that will murder the battery" lol