Bug 4910 - GameKit's GKSession causes Sockets to slow down and behave erratically. (Sample included)
Summary: GameKit's GKSession causes Sockets to slow down and behave erratically. (Samp...
Alias: None
Product: iOS
Classification: Xamarin
Component: General ()
Version: 5.3.x
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Rolf Bjarne Kvinge [MSFT]
Depends on:
Reported: 2012-05-06 22:53 UTC by Dermot
Modified: 2012-09-15 21:51 UTC (History)
4 users (show)

Is this bug a regression?: ---
Last known good build:

Example project showing problem (62.89 KB, application/zip)
2012-05-06 22:53 UTC, Dermot
New Sample Project including iOS and Windows test projects (5.38 MB, application/zip)
2012-07-08 04:08 UTC, Dermot

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Dermot 2012-05-06 22:53:39 UTC
Created attachment 1810 [details]
Example project showing problem

Initializing a GKSession causes socket code using System.Net.Socket to behave strangely. The problem mainly manifests itself as an extreme slow-down of the data throughput of the socket.  I have attached a sample app to demonstrate the problem.

Note: This was tested on iOS 5.1 on iPhone 4/3gs and iPad 1

Install AsyncSocketTest sample app on two devices with bluetooth enabled (not sure if this is necessary or not, but it was my configuration) and WiFi enabled. Ensure both devices are connected to same WiFi Network.

It is necessary to know the IP of at least one of the devices on the local network.

Run the AsyncSocketTest app on both devices.
On device 1. tap "Listen as Host"
On device 2. enter the IP Address of device 1 in the box that by default contains 10.0.0.
On device 2. press connect as guest.
On device 2. press "Send 1x Small Data", "Send 3x Large Data" and "Send 50x Small Data". Note how the data is received almost immediately on device 1. 
Now on both devices, press "Init. GameKit Session". This creates a new gamekit session, initializes it as a client and makes it available (GKSession.Available = true). Now try again to Send data using the "Send 1x Small Data" button and the other send buttons. Note the major slowdown of the socket.

Dev Environment:

Installation UUID: 21414c31-eb69-499d-9e13-8d22ab1cfd19
	Mono 2.10.9 (tarball Tue Apr 17 18:59:12 EDT 2012)
	GTK 2.24.10
	GTK# (
Apple Developer Tools:
	 Xcode 4.3.2 (1177)
	 Build 4E2002
Monotouch: 5.2.11
Mono for Android not installed
Build information:
	Release ID: 20808004
	Git revision: cc9fe83c70d36f9fdab70456392f0fb6d5a83b29
	Build date: 2012-03-30 20:24:12+0000
	Xamarin addins: 1b1a87abc15656938a8342c93dbef8a567442ea0
Operating System:
	Mac OS X 10.7.3
	Darwin MacbookAir.local 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 18:47:41 PST 2012; root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64
Comment 1 Dermot 2012-05-12 01:34:32 UTC

I would really appreciate if this can be confirmed as a bug or not. The functionality that it affects is central to my app.
The attached sample should allow you to see is it a bug or not within minutes.

Thank you.
Comment 2 Rolf Bjarne Kvinge [MSFT] 2012-05-12 05:24:33 UTC
I'll have a look on Monday.
Comment 3 Rolf Bjarne Kvinge [MSFT] 2012-05-14 20:08:57 UTC
I tried with an iPad2 and iPad3 (wifi & bluetooth enabled), and didn't experience any significant slowdowns after enabling gamekit. Ot might be a bit slower (about 0.5s in 25% of the clicks I think), but I wouldn't have noticed unless I was looking for it.

Do your wifi network have internet access? This is just a pure guess, but maybe gamekit is trying to access the internet? Have you tried logging in/out of the gamekit account?
Comment 4 Dermot 2012-05-15 20:43:12 UTC
Ok, I've done quite a bit of testing with this. I've tested it with the following combination of devices:

iPad 1
iPad 2
iPad 3

iPhone 3G
iPhone 3GS
iPhone 4
iPhone 4s

I first replicated the test you performed between an iPad 2 and an iPad 3. I can confirm that the problem did not occur for me either. 
I've noticed that its the receiving device that decides if it will work or not. The following devices received fine:
iPad 2
iPad 3

I've just tested it with an iPhone 4S also, and I notice that on the 4s, the bluetooth icon disappears even though bluetooth is on, and only appears when a something is using it. If I turn on gamekit on the iPhone 4s, and its connected as  the guest in the test app, the problem occurs. I notice that when trying to send data to the 4s via the socket code, the bluetooth icon keeps turning on and off whenever I perform a send from the sending device.

I only have a short amount of time with all these test devices so I cannot test any further, but if the receiving device is a iPad 2 or iPad 3, the problem does not occur. If the receiving device is an iPhone 3G, 3GS, 4, 4S or iPad 1, the problem does occur.
Comment 5 Rolf Bjarne Kvinge [MSFT] 2012-05-16 06:39:01 UTC
Ok, I can get my hands on an iPhone4 later today, and I'll try with that.
Comment 6 Rolf Bjarne Kvinge [MSFT] 2012-05-16 19:03:51 UTC
I can somewhat reproduce it now with a receiving iPhone4, but it's not very consistent. Some times I have to click around a lot before it stops transferring.

I did notice one curious thing though: the large messages are consistently transferred in 8192 byte chunks until a GKSession has been created, and after that the size of each chunk seems to be quite random (I added a C.WL in ProcessReceive, printing out e.BytesTransferred). No idea if this actually means anything though.

CC'ing Gonzalo: do you have any idea what may cause this problem, or even where to start debugging?
Comment 7 Dermot 2012-05-23 07:53:50 UTC
Yes, this is similar to my experience. Its the reason it took me so long to narrow down. The more devices connected the more obvious it becomes (Im not sure if the test app is currently setup to allow multiple connections, it might be, the network code does work with multiple connections).

I've also noticed that the sending of data via the BLUETOOTH GameKit connection was extremely slow too. Taking about 1 minute per megabyte. I assumed that this was the maximum speed of bluetooth as it was my first time working with it, but now im thinking the speed of the bluetooth may also be slowed down by the sockets? (and vice versa).

As I mentioned previously, the bluetooth icon on the iPhone 4s only comes on when bluetooth is actively being used (by design). What I found strange was that initialising the GameKit object didnt cause the bluetooth icon to stay lit in the status bar, but when sending data via the SOCKET, the icon flashes on for a second prior to the data flowing through the socket. This seems strange as my code is doing nothing but initialising the gamekit object, and is not interacting with it at all when sending or receiving data (in the sample). Seems like there are some wires crossed behind the scenes in the socket code that is used for raw sockets, plus bluetooth.

Please let me know if you need any further info or tests to assist with solving this.
Comment 8 Rolf Bjarne Kvinge [MSFT] 2012-06-01 04:30:47 UTC
I've had another look at this issue, but unfortunately I haven't found out anything more. I started playing with changing the socket options for both the receiving and sending sockets (NoDelay, Timeouts, BufferSizes and different parameters to SetSocketOptions), but either this will not fix/workaround anything or I didn't hit the right combinations.

That said, have you tried using a desktop machine as the sending or receiving end? I also just found out how to do packet tracing on iOS: http://developer.apple.com/library/mac/#qa/qa1176/_index.html#//apple_ref/doc/uid/DTS10001707-CH1-SECIOSPACKETTRACING - I can try this later today to see if anything interesting shows up.
Comment 9 Dermot 2012-07-08 04:08:50 UTC
Created attachment 2173 [details]
New Sample Project including iOS and Windows test projects

This attachment contains an iOS Monotouch project with some simple instructions on how to see the error occurring.
It also includes a Windows project which can connect to the iOS app to demonstrate the issue even when communicating with a windows machine.

Finally, this attachment also includes a PDF spreadsheet of my test results when testing across multiple different devices.
Comment 10 Dermot 2012-07-08 04:18:04 UTC
I have tested this extensively today with new sample projects. It seems to affect all devices (newer devices are affected less, but still affected) Its a pretty major bug whatever is causing it.

I have tested it communicating with a desktop machine and the problem still occurs. Within the new attachment is a spreadsheet of my tests with the speeds I got across different devices.

I've been developing my app for the last 16 months and this is stopping me from releasing it, so any time you can spend to help find a solution would be greatly appreciated.
Comment 11 Dermot 2012-07-10 06:54:31 UTC
I have done some more testing which may narrow down the cause of this. It seems it only affects the socket connection when GKSession.Available is set to true. This property determines if the local device publishes/broadcasts itself over WiFi and over Bluetooth. It can safely be turned off after a connection has been made.

I have successfully done the following:

1. Connected two devices via a WiFi Socket connection with a GKSession initialized but Available set to false
2.Sent data between them at full speed with no slowdowns.
3.Set Available=true and made a connection from one device to the other via a GKSession (have tested it with both Bluetooth & WiFi - by disabling the opposite radio respectively)
4. Noted that the Socket started to backlog data while Available = true (in keeping with previous tests)
5. Set Available=false on both devices GKSession object
6. Bluetooth connection remains active between both devices GKSession objects, but the Socket now sends data at full speed again.

With the above in mind, it seems to me that the problem may in fact be something to do with Bonjour. I would imagine that setting Available=true begins broadcasting a Bonjour service on the Local Network, as well as setting Bluetooth discovery to true (I would imagine, not too familiar with Bluetooth). Once the broadcasting stops (Available=false) the problem disappears.
What's strange is that I use Bonjour itself (NSNetService) elsewhere in my project with zero issues. In fact, my app is always broadcasting a Bonjour service.

So it seems that what ever way GameKit advertises itself over WiFi is what is causing the problem, not that Bluetooth or the GKSession itself is somehow interfering directly with the sockets.

Hope this helps.
Comment 12 Dermot 2012-07-10 07:15:08 UTC
One last thing... :-)

I've just tested it without WiFi by using 3G only on my iPhone, connecting directly to my Windows PC's external IP. The result was that turning on or off Availability of the GameKit session had ZERO effect on the speeds of the socket.

This is in keeping with my previous suspicion of GameKits usage of Bonjour causing the problem. With WiFi off, the service doesn't get published via Bonjour on WiFi, and so doesn't affect the socket in any way.

Im not sure how GameKit's usage of Bonjour is different from regular NSNetService usage. Eitherway, im now pretty sure from extensive testing that that is where the problem lies.
Comment 13 Rolf Bjarne Kvinge [MSFT] 2012-07-17 09:16:23 UTC
Just an idea: do you have to use GameKit as opposed to NSNetService? Can you somehow rework your code to use NSNetService instead?

I've been looking at your test case (very nice btw), and I can reproduce the slowdown between iPad3 and Windows (400-500ms vs 400ms-4000ms - the speed with GKSession.Available = true varies a lot, sometimes there is a slowdown, sometime there isn't).
Comment 14 Dermot 2012-07-22 00:28:18 UTC
I wasn't aware it was possible to use Bluetooth without using GameKit. Can you point me in the direction of a tutorial or some documentation regarding this?  From what i've read, as of iOS5, NSNetService no longer publishes over Bluetooth (see note below table: http://developer.apple.com/library/ios/#qa/qa1753/_index.html#//apple_ref/doc/uid/DTS40011315 )
Comment 15 Rolf Bjarne Kvinge [MSFT] 2012-07-23 07:40:38 UTC
There is an interesting note there: "The new policy is that a Bonjour app must explicitly opt in to Bluetooth support. This change was made to reduce interference with Wi-Fi." I wonder if you're experiencing the wi-fi interference. In fact if you google for wifi and bluetooth interference / slowdowns, you'll find that it is a common problem actually.

Here is a couple of the most interesting links I found:

I tried disabling bluetooth on my device and ran your test app again, and I didn't see any slowdowns anymore (which you've also found in your testing iirc).
Comment 16 Lassic 2012-08-15 04:26:09 UTC
I'm just sharing that I'm also experiencing the same problems with BT/Wifi not playing nice together.
I tried resorting to the new iOS 5 DNSSD (NSNetService low level equivalent that lets you specify which interface to advertise on), but still getting slowdowns randomly on iPad1, iPad2, iPod Touch 4, iPhone 4Gs & 3Gs.

This SO thread should get anyone going with DNSSD and Bluetooth without GameKit:

I hope this helps anyone, I'll keep tracking this issue since it affects me as well.
So far, from all I'm reading, it could be a plain interference issue between BT/Wifi that operate on the same frequency and thus subject to random collisions and slowdowns.
Comment 17 Dermot 2012-09-15 21:51:38 UTC
I have removed all GKSession code from my application and changed to the DNSSD approach to allow broadcasting Bonjour over Bluetooth interface, then communicating via a link local TCP socket connection.

Far better solution, and gives me speeds close (~80%) to the theoretical max speed of Bluetooth. (compared to GKSession, which was far, far slower).

In reply to Lassic's slow down issue, I found that if browsing or resolving is left turned on (by not calling EndResolve() or EndBrowse() I too experience slowdowns, but turning them off once im finished solves this problem.

Im changing this to Works for me (finally!). If you would like to keep it open please change it accordingly.