Faster TCPSockets

Splitting off from here

I did some tests…

There’s a manufacturer’s software (an Editor) that connects to a piece of hardware. They communicate via TCP.
When the software is connecting directly to the hardware, it takes 36 seconds to synchronize. (Passing around 1mb of data)
Speed is the same on MacOS or Windows.
I created a test app in Xojo, using 2 TCPSockets, one receiving/sending from/to the Editor and one doing the same for the hardware. Each receive a packet and send to the other, with no processing in-between, and it takes around 7 minutes! to synchronize. Again, same speed on MacOS or Windows.

I then created an app in VB.NET on Windows, doing the same thing that the Xojo App is doing, passing the packets back and forth with no processing, and it takes only 36 seconds to synchronize, essentially adding no overhead to the communication at all. I wasn’t even using threads!

Clearly the Xojo TCPSocket is REALLY slowing things down. (Like 10x)

Would MBS Sockets work faster?

Would love to see the code for you Xojo stuff as I’ve done a decent amount with TCP Sockets (going as far as creating a full db “plugin” with them) and they arent THAT slow
So I’m curious about your code to see why it behaves this way for you

1 Like

Basically:

RawConsoleSocket = New TCPSocket
RawConsoleSocket.Address = "192.168.1.128"
RawConsoleSocket.Port = 50000
RawConsoleSocket.Connect

RawEditorSocket = New TCPSocket
RawEditorSocket.Address = "127.0.0.1"
RawEditorSocket.Port = 50000
RawEditorSocket.Listen

While Not RawEditorSocket.IsConnected And RawEditorSocket.LastErrorCode = 0
  App.DoEvents
Wend

While RawEditorSocket.IsConnected
  EditorMsg = RawEditorSocket.ReadAll
  RawConsoleSocket.Write(EditorMsg)
  
  App.DoEvents
  
  ConsoleMsg = RawConsoleSocket.ReadAll
  RawEditorSocket.Write(ConsoleMsg)
Wend

Properties of the MainWindow:
RawConsoleSocket, RawEditorSocket: TCPSocket
ConsoleMsg, EditorMsg: String

btw, without DoEvents the app just hangs…

The loop is blocking the GUI from updating, but the app is probably not actually hung. Once the loop exits the GUI should become responsive again. Calling DoEvents is neither necessary nor appropriate here, and is almost certainly a major cause of the slowness.

Try it again without DoEvents and wait until the loop completes, even if the GUI hangs. I expect the the timing to be much closer to what you’re expecting.

To avoid blocking the GUI either put your loop in a Thread, or use the events of the socket (Connected, DataAvailable, etc.) to avoid looping at all.

No, the app definitely hangs. The sockets will not do anything unless there’s a DoEvents in there.
I also created the app with event-driven sockets, using DataAvailable and so on. Speed was the same.

I’m quite sure that putting it into a thread will be just as slow. But if you feel very certain of this, I can give it a try.

If this is a console app, wait less time in DoEvents. You’ll use more CPU, but you can process more events per second.

If this is a desktop app, dear god stop this mayhem and refactor away from synchronous sockets. Use the actual socket events, never DoEvents, and you should have better results.

Everyone, please keep in mind this is just a test.
Don’t lose sleep over the doevents thing. It’s not going to kill babies.

Again, I have done it both ways, with events and in a loop, to see if there was any difference. There wasn’t.

1 Like

What happens if you replace DoEvents with Socket.Poll()?

We have an app with console, ServerSocket and DoEvents.
When there is no connection, we use a delay of 10ms. If there is a connection, we use 1ms to be more responsive. And when there is an active transfer, we use 0ms delay to be as fast as possible.

and DoEvents runs Socket.Poll on each call.

I wonder what a ReadAll does if there is nothing to read yet. I would not be surprised if that could be (one of) the reason(s) of the slowness you encounter. I would definitely go the asynchronous way like @charonn0 and @thommcgrath already proposed or at least check for data availability before the reads.

ReadAll returns immediately if there is no data.

Please stop thinking about DoEvents, everyone. It’s a red herring. If it gets the conversation moving, my previous version of the test worked the “usual” way with DataAvailable. I was only trying to see whether events were slowing things down so I tried it without events to see if it would be faster. It wasn’t. It was the same.
Here’s what was inside each Socket’s DataAvailable handler:

EditorSocket.DataAvailable:

Sub DataAvailable()
  EditorMsg = Me.ReadAll
  ConsoleSocket.Write(EditorMsg)
End Sub

ConsoleSocket.DataAvailable:

Sub DataAvailable()
  ConsoleMsg = Me.ReadAll
  EditorSocket.Write(ConsoleMsg)
End Sub

this should be about as fast as you can get since you dont do any buffering etc

Ok, then would you agree that the Xojo TCPSockets implementation is the likely culprit?

@MonkeybreadSoftware, are your Sockets faster?

How would I “drop in” an MBS Socket in place of the TCPSocket to test?

Based on what you have posted there would seem to be evidence that suggests they are not optimal

I have been able to flood very fast connections with them as well (sending & receiving)

Please let me know what sockets from us you talk about.

maybe RAWSocketMBS class?

You tell me! :sweat_smile:
Do you have something that would work in place of a Xojo TCPSocket and be faster?

The weird thing is that the data rate from the device is pretty darn slow. 1mb in 36s is like 27kB/s???

We have various classes for various use cases.
e.g. CURLSMBS can do connection (with or without SSL) and you can then use Send/Receive commands to handle the protocol yourself.
Otherwise RAWSocketMBS is a good socket replacement to do a bit more than the built-in one.

Not sure what you mean by “handle protocol yourself”?
It’s TCP, sending strings of bytes to and from.
So RAWSocketMBS then?

Do you have any documentation on how to drop in a RAWSocketMBS in place of a TCPSocket?