-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Working on issue #15 (work in progress) #16
Conversation
Duplicating a comment I left on Reddit: I tried to mimic the approach of
It seems like it might be impossible for a library to safely do tricky things like |
Hey, thanks for looking into this. Just a heads up, I'm rather swamped at work right now, so I won't really have time to dive into and evaluate this until a few weeks from now. |
Sounds good, thanks @merijn . FYI after the last couple commits the fix seems to be working. This fix depends on haskell/process#154 landing. |
@merijn I've been using this for a while without issue, and the necessary change in |
I wanna check out what some of the RTS functions actually do so I understand what I merge, but it seems fine. I probably won't get around to making a new release until somewhere next week, though. |
Friendly ping here @merijn |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the ping, I got distracted. There's a few redundant imports (I can remove those to, if that's easier). The one thing I'm suspicious about is changing the foreign imports to unsafe. What's the reason for that?
System/Posix/Pty.hs
Outdated
@@ -280,13 +285,13 @@ foreign import capi unsafe "sys/ioctl.h value TIOCPKT_DOSTOP" | |||
foreign import capi unsafe "sys/ioctl.h value TIOCPKT_NOSTOP" | |||
tiocPktNoStop :: Word8 | |||
|
|||
foreign import ccall "pty_size.h" | |||
foreign import ccall unsafe "pty_size.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any specific reason these imports should be unsafe
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, for performance. Foreign code that's not expected to a) block or b) call back into Haskell code can be marked unsafe
to reduce overhead; see https://wiki.haskell.org/Foreign_Function_Interface#Unsafe_calls
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What they forget to mention is that, even for non-blocking functions unsafe can be rather problematic if the function is slow as for the duration of the foreign call the GC is blocked. So if GC is triggered all threads will be blocked and waiting idle for the duration of the foreign call.
So I'd be hesitant to change that, especially for foreign code making syscalls (like these) since the overhead of a safe call is tiny compared to the overhead of making a syscall.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the overhead of a safe call is tiny compared to the overhead of making a syscall
That's not what I thought, do you have a citation? From what I can google the overhead of safe
is pretty significant and can make the overall call 10x slower; see here. Quoting Simon Marlow: "safe calls are more expensive and involve taking and releasing locks, and possibly creating a new OS thread." I'm sure it depends on the syscall as well. For the relatively simple calls like get/set_pty_size I'd expect unsafe
to be a win.
So if GC is triggered all threads will be blocked and waiting idle for the duration of the foreign call.
Not sure what you mean by this -- I believe GHC will simply not trigger GC while an unsafe
call is active, so there's no scenario where other capabilities not involved in the unsafe
call get blocked. Given the syscall duration is probably measured in 10s/100s of nanoseconds and typical GC frequency is measured in 100s of milliseconds it should not be a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course safe calls are more expensive. The question is "does that matter?". You're kinda glossing over the takeaway right at the top of Edward's post :)
Don’t use unsafe in your FFI imports! We really mean it!
Anyway, I'm fairly familiar with the low level details of safe vs unsafe calls and I'm not really inclined to mark foreign calls unsafe unless I'm 100% it's 1) necessary and 2) safe. So, in the absence of data showing a problem I'll keep them as is. I'll merge this without them, do a bit of local testing and then make a new release on Hackage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're kinda glossing over the takeaway right at the top of Edward's post
Not really, he acknowledges in the comments that the C code he's dealing with is doing intensive things like solving SAT problems. I still don't think this rule applies to a short C function with a single syscall / don't get why you'd rather trade off a guaranteed performance hit on every call to avoid delaying a GC iteration by a tiny amount (unless I'm wrong about the "blocking every thread" scenario?). But agreed it's unlikely to cause a noticeable problem.
Thanks for merging!
This is some progress I've made on issue #15. It doesn't solve the problem yet but I'm putting it up now to gather feedback/advice.
I've been trying to follow the approach of the
process
library to make the fork call insideposix-pty
play nicely with the GHC RTS. See howblockUserSignals
/unblockUserSignals
andstopTimer
/startTimer
are used here: https://github.com/haskell/process/blob/master/cbits/runProcess.c#L137I think adding
unsafe
to theforeign import ccall
lines is a good idea no matter what; see http://wiki.haskell.org/GHC/Using_the_FFI#Improving_efficiency