Skip to content
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

UDP Sockets #36

Open
softworkz opened this issue Jul 11, 2019 · 23 comments
Open

UDP Sockets #36

softworkz opened this issue Jul 11, 2019 · 23 comments

Comments

@softworkz
Copy link

softworkz commented Jul 11, 2019

One question:

Is this supposed to work with UDP sockets as well?

Did somebody try this?

Thanks,

softworkz

@mgravell
Copy link
Owner

mgravell commented Jul 12, 2019 via email

@softworkz
Copy link
Author

I did.

To make it work in general it requires just a single line change:

var buffer = _receiveFromSocket.Writer.GetMemory(1);

Needs to be changed to this:

var buffer = _receiveFromSocket.Writer.GetMemory(this._receiveOptions.MinimumSegmentSize);

And ZeroLength reads must not be used.

But overall it didn't perform very well due to the frequent flushing (= after each receive).

With UDP, the data doesn't get accumulated in the buffer. You get a single datagram with each receive call. And that causes too many async calls which are becoming a performance issue with high data rates.

@Drawaes
Copy link
Collaborator

Drawaes commented Jul 12, 2019

I'll be honest as a big user of UDP and a user of pipelines I had considered it. However as Marc said it doesn't make a lot of sense in this case, you completely lose the framing of the datagram so then you need to implement framing over the top, at which point I question if you are rewriting tcp over UDP.

@softworkz
Copy link
Author

softworkz commented Jul 12, 2019

No, the framing doesn't get lost as mentioned above because in case of UDP you always get a single datagram with each receive call. In my case, a datagram contains n packets of size x with x being a global constant. Packets are not sliced across datagrams.

Maybe I should say that this is about media streaming. Several protocols in this area are UDP based and the challenge is to find the most effective implementation.

Arguing about protocol design and choice is a dead end in this case.. :-)

@mgravell
Copy link
Owner

To me, UDP seems more like a Channel<ReadOnlySequence<byte>>. Perhaps that's something that we could implement with minimal work, giving you all the benefits without the pain, and respecting the framing differences between UDP and TCP.

Happy to explore that area. I've mostly been TCP focused, but I love expanding my horizons...

@Drawaes
Copy link
Collaborator

Drawaes commented Jul 12, 2019

Which was exactly the discussion I had with Fowler around UDP. I suspect it's not on the pipelines asp.net radar yet either (maybe quic will change that)

@softworkz
Copy link
Author

What do you mean by Channel<ReadOnlySequence> ?
Wasn't 'Channel' the initial term before it became 'Pipeline'?

@Drawaes
Copy link
Collaborator

Drawaes commented Jul 12, 2019

System.Threading.Channels made around the same time as pipelines (which maybe why pipelines was renamed... But that's just a rumour 😀)

@mgravell
Copy link
Owner

mgravell commented Jul 12, 2019

Channel<T> is the high perf reader-writer async queue thing. Yes, the name was also the early name of pipelines, but pipelines lost and became pipelines. Related and overlapping topic, and I do think it would make a good API here, for packet-based rather than stream-based protocols.

@softworkz
Copy link
Author

That sounds really interesting, every time I read about channels somewhere I thought it was about the early pipeline stuff.

Too bad that it doesn't seem to support netstandard2.0 (need to support BSD as well)

@mgravell
Copy link
Owner

Channels and pipelines are both netstandard 1.3+; you're fine

@softworkz
Copy link
Author

@mgravell
Copy link
Owner

Nuget: https://www.nuget.org/packages/System.Threading.Channels/ - click dependencies

@softworkz
Copy link
Author

Thanks a lot, I'll look into it!

@mgravell
Copy link
Owner

In fact, maybe a case could be made for IAsyncEnumerable<ReadOnlySequence<byte>> - I will have to play!

@softworkz
Copy link
Author

Think about small packet sizes and a huge amount of them :-)

@softworkz
Copy link
Author

Don't forget to add a running number when sending udp datagrams for testing.
You need to make sure that you're getting them all.

Mine are about 25k size, I tried to get close to half of the maximum allowed (64k).
The smaller I made the datagrams the worse it got (CPU usage).
(it's a real world application - that means: half datagram size => double amount of datagrams per time)

PS: Watch your e-mail, I can provide some more interesting details if you wish

@mgravell
Copy link
Owner

mgravell commented Jul 13, 2019

Started a spike with this. Looking viable. A running number in the lib would be pointless - it can't tell if it didn't get a packet. Hence IMO any running number must be part of your payload, not the code that makes things work.

If you mean a running number in test code: sure, absolutely.

@softworkz
Copy link
Author

Yes, of course I meant a number inside the payload for testing.

@sebandraos
Copy link

Did anything come of this discussion? I can see a UDP branch but it doesn't seem like it ever got merged into master. Was an alternative to that branch implemented instead? Thanks

@mgravell
Copy link
Owner

mgravell commented May 22, 2020 via email

@sebandraos
Copy link

Ok, cool thanks.

@sgf
Copy link

sgf commented Sep 28, 2020

The TCP protocol performs very badly in the case of a wide geographical distance around the world.
UDP is controlled by appropriate high-level algorithms to achieve an ideal low latency.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants