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

What are the plans to support macOS 10.11 and iOS? #130

Closed
MrMage opened this Issue Mar 12, 2018 · 19 comments

Comments

Projects
None yet
6 participants
@MrMage

MrMage commented Mar 12, 2018

I am interested in using SwiftNIO's HTTP2 implementation (once available) to add an NIO-based server implementation to https://github.com/grpc/grpc-swift. Given that that project currently depends on several other fairly large libraries, it would be great to also move the client code to SwiftNIO to eliminate those dependencies.

For that to happen, though, SwiftNIO would need to support those client platforms — namely iOS (preferably 10+) and macOS 10.11. Neither currently shows up in the "Supported Platforms" list — does that mean it's technically impossible to support those platforms (e.g. because some low-level networking APIs are missing), or has the library simply not been tested on those platforms, but might already work as-is? Other than that, what level of effort would be required to add support for these two platforms, or is it already planned, and with what timeline?

@Lukasa

This comment has been minimized.

Contributor

Lukasa commented Mar 12, 2018

Great question, and thanks for your interest!

Let me break this down slightly into two separate parts. First, macOS 10.11. I do not think there would be much technical difficulty in supporting that target, though some compatibility code may be required. That would be easy enough to do though, and should only require changing some if #available guards and fixing any compile and test failures that occur.

For iOS, the problem gets a bit thornier. NIO as it exists today uses the BSD sockets API for all its I/O, and pthreads for its thread management. This works just fine on macOS and Linux, but on iOS it's a distinctly suboptimal solution. On iOS neither of these solutions interacts well with the OS: BSD sockets don't provide information to the OS about what's needed from the radios, and pthreads don't let the kernel optimise scheduling the way Dispatch does.

Our ideal long-term solution for iOS work is to have an alternative set of event loops and channels that are built to treat iOS as a first-class citizen, using its platform native APIs to build a solution that works elegantly the rest of the operating system.

Currently the most concrete information I have about timelines for iOS is that we're looking into scheduling that work, but it's not currently in our top list of priorities. We have a bunch of other protocol work we want to do first, to really flesh out the server side of the story.

@tomerd tomerd added the question label Mar 12, 2018

@helje5

This comment has been minimized.

Contributor

helje5 commented Mar 12, 2018

BSD sockets don't provide information to the OS about what's needed from the radios

I'm not entirely sure what do you mean by that, would you be so kind to elaborate? (I'm using a BSD socket server + GCD on iOS, and it is not clear to me what else you could do here)

pthreads don't let the kernel optimise scheduling

On iOS I would assume you would never run more than a single thread aka MultiThreadedEventLoopGroup(numThreads: 1). I can't see how this wouldn't be sufficient (if a handler does expensive work, he can always dispatch out to GCD).

I'm probably going to give NIO on iOS a run later this week.

@Lukasa

This comment has been minimized.

Contributor

Lukasa commented Mar 12, 2018

I'm not entirely sure what do you mean by that, would you be so kind to elaborate?

Sure, my source here is the official networking documentation, which contains this note:

In iOS, POSIX networking is discouraged because it does not activate the cellular radio or on-demand VPN.

On iOS I would assume you would never run more than a single thread aka MultiThreadedEventLoopGroup(numThreads: 1). I can't see how this wouldn't be sufficient (if a handler does expensive work, he can always dispatch out to GCD).

Oh sure, that would definitely work. I should probably have been a bit clearer. On iOS it's advantageous to give Dispatch as much insight into the work patterns of the code as possible, to ensure that it is able to schedule work effectively on the system. This means that from our perspective our ideal model keeps the general architecture of NIO, but uses different primitives on iOS to achieve the same end result.

Of course, users would always be able to select whatever model they wish to, subject to availability on the platform. We just want good options. 😁

@helje5

This comment has been minimized.

Contributor

helje5 commented Mar 12, 2018

In iOS, POSIX networking is discouraged because it does not activate the cellular radio or on-demand VPN.

OK, but this is for software connecting away from the device, it doesn't matter for the server part. (I'm not aware of any other API one could use here). In fact the very same documentation says that right after the part you quoted :-):

For daemons and services that listen on a port, or for non-TCP connections, use POSIX or Core Foundation (CFSocket) C networking APIs.

I wonder how you would hook up non-Posix stuff for outgoing traffic (that is NSURLSession). Certainly possible and probably required for the reasons mentioned.

This means that from our perspective our ideal model keeps the general architecture of NIO, but uses different primitives on iOS to achieve the same end result

OK. So I read this as you plan to use GCD on iOS to back the event loop. I currently use GCD in my own device server (in a single serial event loop sigh, dispatch queue).
I don't think that running on more than 1 thread is very useful on device. The only thing I think I might wish for is a way to give the NIO thread a utility priority.

@Lukasa

This comment has been minimized.

Contributor

Lukasa commented Mar 13, 2018

OK, but this is for software connecting away from the device, it doesn't matter for the server part.

Ah, we were talking past each other: I was talking about client usage. Yes, for server usage BSD sockets are the way to go.

So I read this as you plan to use GCD on iOS to back the event loop.

I mean, we won't remove the MultiThreadedEventLoopGroup from iOS builds, so in situations where you'd prefer to have a single OS thread, that will continue to be an option. We just want to also provide a Dispatch-based abstraction.

@helje5

This comment has been minimized.

Contributor

helje5 commented Mar 13, 2018

BTW: The way I read the docs, a Dispatch based solution wouldn't actually fix the issue. I don't know what CFStream does extra to do the (radio/vpn) stuff a BSD connect doesn't. But I suppose it would be easier to just add that code section for iOS targets, instead of switching the whole stack (unless that part is closed source of course).

@MrMage

This comment has been minimized.

MrMage commented Mar 26, 2018

@Lukasa sorry for the delay in replying to this. Thank you for the feedback, this is very illuminating!

I noticed that MultiThreadedEventLoopGroup only works on macOS 10.12 and above — do you know if there's a specific reason for excluding 10.11 there? (I assume the team just used if #available(OSX 10.12, *) to check for macOS, with less focus on the specific version.) Also, what event loop is being used under Linux, given that MultiThreadedEventLoopGroup wouldn't work?

@Lukasa

This comment has been minimized.

Contributor

Lukasa commented Mar 26, 2018

As discussed above, macOS 11 has been excluded only because it was not actively considered a target we needed to support. There is no profound reason that I'm aware of, and support could be added by dropping the version in those guards and fixing whatever compile errors occur.

The MultiThreadedEventLoopGroup is being used on Linux. You're misreading that guard. The asterisk means "on all platforms not explicitly mentioned, enter this block".

@normanmaurer

This comment has been minimized.

Member

normanmaurer commented Mar 26, 2018

Also the check is not needed anymore as we use our own Thread class and not Foundation.

See #233

@MrMage

This comment has been minimized.

MrMage commented Mar 26, 2018

The MultiThreadedEventLoopGroup is being used on Linux. You're misreading that guard. The asterisk means "on all platforms not explicitly mentioned, enter this block".

So if #available(OSX 10.12, *) means "on macOS, but only 10.12 or newer, or any other platform that is not macOS"? Thanks, I was not aware of this.

@Lukasa

This comment has been minimized.

Contributor

Lukasa commented Mar 26, 2018

Yeah, that's what the guard means. 😄

@Lukasa

This comment has been minimized.

Contributor

Lukasa commented Mar 29, 2018

I believe this is addressed in the current master. Please let me know if it's not.

@Lukasa Lukasa closed this Mar 29, 2018

@normanmaurer

This comment has been minimized.

Member

normanmaurer commented Mar 29, 2018

@SetoKaiba

This comment has been minimized.

SetoKaiba commented Mar 30, 2018

I'd like to know whether it just does not work on iOS. Or it works, but it does not activate the cellular radio or on-demand VPN?

@Lukasa

This comment has been minimized.

Contributor

Lukasa commented Mar 30, 2018

The second.

@SetoKaiba

This comment has been minimized.

SetoKaiba commented Mar 30, 2018

Is there any time frame for a iOS support?
https://stackoverflow.com/questions/25045829/how-can-i-activate-the-cellular-radio-in-ios-since-bsd-sockets-doesnt-activate

According to this post, it seems that I can just listen for Tcp and do nothing. It will keep the cellular radio or on demand VPN activated. Does it mean that this can be a temp workaround for iOS using?

I really love to use Netty like mechanism since my server is in Java based on Netty. I can keep them look the same. Or is there any Netty like lib supporting iOS?
Thank you for your reply.

@SetoKaiba

This comment has been minimized.

SetoKaiba commented Mar 30, 2018

I noticed that you mentioned the pthread management used by swift-nio.
And I found the #233 says that it removes the check, because swift-nio uses its own thread impl now.
Is MultiThreadedEventLoopGroup(numThreads: 1) and dispatch to GCD mentioned by @helje5 is still preferred?

@helje5

This comment has been minimized.

Contributor

helje5 commented Mar 30, 2018

I’m not sure what the latter question relates too. It doesn’t sound like the radio/vpn issue? But yes, on a device I can’t imagine why you’d want to have more than one NIO thread. (unless you put it in a rack an use it as a server ;-) )

You definitely don’t want to do the former. (only listen to keep the radio active) The users will hate you ;-)
(btw the SO article seems to mirror my experience, that TCP seems to be fine w/o any extra tricks, but who knows. and i didn’t try VPN)

@Lukasa

This comment has been minimized.

Contributor

Lukasa commented Mar 30, 2018

Whether NIO works for your needs is entirely dependent on what your needs are. In general, BSD sockets are less than ideal on iOS because the contract given by the operating system does not give you much feedback about the state of the system. The OS is free to do as it pleases with your BSD sockets in non-main-line scenarios (e.g. background your app could invalidate your FDs without notifying you).

Again, the best we can say is that if iOS provides a higher level API for what you’re trying to do, you are best suited using it. If it does not, NIO should work fine as a wrapper around the BSD sockets/pthreads library. GCD integration is on the roadmap, but not immediately imminent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment