NWConnection vs. nw_connection_t

I have ported my code from BSD sockets over to Network.framework, and while blocking issues remain (https://forums.developer.apple.com/forums/thread/747815) and while I can not yet properly instrument my code because os_signpost does not seem to work on XCTestCases profiled directly from Xcode (https://forums.developer.apple.com/forums/thread/748059) I do already have some initial observations.

Perf test case of sending full (~1280 bytes) UDP datagrams back and forth over lo0 indicates that BSD sockets code can achieve 20% higher throughput (in packets per second) than Network.framework based code.

That is not what I expected, and I will continue investigating but for the moment I have one question I did not find answer to.

Will using C based Network.framework API instead of Swift based one bring performance gains?

For example, nw_connection_t provides an interface to send non-contiguous segments of dispatch_data_t without copying, whereas NWConnection only deals with contiguous Data.

Thanks for any insights.

Replies

UDP datagrams back and forth over lo0

I recommend that you run a device-to-device performance test. The loopback interface always involves a round trip into the kernel.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@eskimo I was able to craft together some real device tests from my MBA to an iPhone 14 Pro over WiFi.

The iPhone app is complied in release mode and always uses BSD sockets for easy comparison, so I am essentially testing the MBA/macOS stack.

On the MBA side I profile the test in Instruments with deferred mode recording. No data processing takes place.

The first test uses 1 million UDP packets sent from the MBA to the iPhone 14 Pro to see how fast I can dump them to the network.

Via BSD sockets in 17 seconds, via NWFW in 6 seconds. Repeated multiple times.

The second test uses 1 million UDP packets dumped from the iPhone 14 Pro to the MBA to see how fast they can be received.

Via BSD sockets in 51 seconds, via NWFW in 53 seconds.

In all cases most of the time is spent in sendmsg / recvmsg, or nw_connection_add_read_request_on_queue / nw_connection_add_write_request_on_queue.

These results look much better. Continuing to profile more!

  • Thanks for the update.

Add a Comment