-
Notifications
You must be signed in to change notification settings - Fork 656
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Unify wrapper paths #1423
Unify wrapper paths #1423
Conversation
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.
I'm okay with this if we can show that it leads to the same assembly. Back when we first wrote this, the optimiser couldn't optimise those two cases into the best code which is why we had to split it. I'm happy to undo this now if we can show that the code isn't affected by this.
Sources/NIO/System.swift
Outdated
if err == EINTR { | ||
continue | ||
} | ||
if err == EINTR { continue } |
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.
nit: we usually put newlines after every {
Sources/NIO/System.swift
Outdated
} | ||
|
||
/* Sorry, we really try hard to not use underscored attributes. In this case however we seem to break the inlining threshold which makes a system call take twice the time, ie. we need this exception. */ | ||
@inline(__always) | ||
@discardableResult | ||
internal func wrapSyscall<T: FixedWidthInteger>(where function: String = #function, _ body: () throws -> T) throws -> T { | ||
internal func call<T: FixedWidthInteger>(nonblocking: Bool, where function: String = #function, _ body: () throws -> T) throws -> IOResult<T> { |
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.
I think we should still name this wrapSyscall
or callSyscall
or something. This wrapper only works if the called function behaves like a unix syscall (ie. -1 == error)
I think addressing the generated code issue first is more important, fixing the style stuff can come later. I checked on an ubuntu build, it depends on how you write the code and what you want the result to be. Looking at the code for: while true {
let res = try body()
if res == -1 {
let err = errno
if err == EINTR { continue }
if blocking && err == EWOULDBLOCK { return .wouldBlock(0) }
preconditionIsNotBlacklistedErrno(err: err, where: function)
throw IOError(errnoCode: err, reason: function)
}
return .processed(res)
} generates the same assembly (modulo offsets) - I've attached the before and after results. However, it generates two functions, the static function and the merged function. Writing it as: while true {
let res = try body()
if res == -1 {
let err = errno
switch err {
case EINTR: continue
case EWOULDBLOCK:
if blocking { return .wouldBlock(0) }
fallthrough
default:
preconditionIsNotBlacklistedErrno(err: err, where: function)
throw IOError(errnoCode: err, reason: function)
}
}
return .processed(res)
} produces a single function instead. The single function is a little bit heavier on the frame size, but overall reduces the amount of code. There is a minor amount of extra overhead (2 extra |
The path was duplicated because the compiler was not previously able to optimize with the constant value and would generate poor code. This has now been addressed, so unify the blocking and non-blocking paths.
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.
Thank you! That looks good to me
Yes, that would be wonderful. Small steps make it easier :) |
The path was duplicated because the compiler was not previously able to optimize with the constant value and would generate poor code. This has now been addressed, so unify the blocking and non-blocking paths. Co-authored-by: Cory Benfield <lukasa@apple.com>
Merge the block and non-blocking sys call wrappers
Motivation:
The two paths are nearly identical with the core difference being that blocking calls ignore
EWOULDBLOCK
. This simplifies the handling for the different types by adding a parameter to thewrapSyscall
method.Modifications:
Added a new parameter
nonblocking
to thewrapSyscall
andwrapSyscallWouldBlock
. Those paths are then merged into a singlecall
method.Result:
No external changes.