Receive UDP without allocations

allencook200

Member
Joined
Apr 27, 2021
Messages
9
Programming Experience
1-3

So I'm using this function to try to receive UDP packets without allocating memory, by writing it into an existing buffer, however it's still allocating memory.

C#:
remoteEP = endPointSnapshot.Create(socketAddress);

This maybe looks like the line that could be causing allocations? Could someone assist me in re-writing this so that it's allocation free?
 
Last edited:
Sorry, forgot to post the code I'm using. Here it is
C#:
_UdpClient.Client.ReceiveFrom(ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, ref endPoint);

The code I posted above in the first post was the part of what I think may be causing allocations? I really have no idea. Are sockets in C# known for allocating any memory on send/receive at all in the first place?

To be clear, I am using unity, and sometimes it uses different code than what normal C# generally uses.

C#:
SocketAddress sockaddr = remoteEP.Serialize();

I was told by someone else that the code above could possibly be causing the allocations?
 
That is not all the relevant code. That does not tell us anything about the values used or what you are passing to the called method... We can only do so much for you. The above is not enough for us to help you.

Now might be a good time to start reading about reference types, pointers, and value types. Heap vs Stack and memory management in C#. Value types always stay wherever they are stored/created. So if a method has parameters, and if those parameters are value types, then what would you expect to be the outcome for memory usage within that method? If you were passing in a reference type as as parameter already defined outside your method, then what would you expect to happen to the memory usage of that method and what happens to the reference type you passed in to the method as a parameter? When you understand such things, you can identify what memory you are using and where.

causing allocations
Allocations to what?
To be clear, I am using unity, and sometimes it uses different code than what normal C# generally uses.
Explain? Unity uses .net, and in mono. The only difference would be their custom libraries and classes etc which are still C#. Even unity's behavioural scripts are in C#. o_O
 
Our OP is obsessed with memory performance if you look at his past posts. With our OP writing a game, and for some reason his game is lagging. His initial forays into determining the source of the lagging, he's hit on upon the garbage collection induced pausing. So now he it looks like he is obsessively trying to prevent any memory allocations from happening, so that garbage collection happens less often.
 
Anthony. Take the following with a grain of salt, as my recent posts have been taken out of context and removed for being a little to blunt. Now you know me better than that. I don't and won't forum crawl through any members posts for anyone, and neither should any one else. If someone wants help especially from me, then they need to put in the effort and provide ALL of the necessary information on the opening topic or they will get a bunch of assumptions and speculative answers from us. Other people might not have a problem forum crawling through old posts but my time is valuable as I have a busy hectic life, and my time spent helping on these boards won't be spent crawling through posts just because some OP's won't bother to put in the required time and effort to construct a decent opening question. But I appreciate the pointers you've shared above.

Regarding the OP wanting to circumvent memory allocations and decrease overall memory usage. OP would be best listening to lectures from Bjarne Stroustrup who has suggested trying to write code which does not require a lot of garbage collection. And that's best done by :
reading about reference types, pointers, and value types. Heap vs Stack and memory management in C#.
I have no problem trying to help the OP with the lag they are experiencing, and I am willing to help them to irradiate it if they provide what was previously requested. But they will need to be more forthcoming with code they are using, and for them to do that, they will first need to start profiling their application to see what scripts are causing excessive memory usage, and then sharing the troublesome code files with the community so we can all help them to improve the code they currently have. The OP was asked to provide all relevant code twice as of now. I normally charge a minimum of €180 per hour for game developing; a typical minimum €10,000 per project. And I offer code help for free on these forums providing the OP puts in an equal amount of effort to describe their problem in detail and while providing the troublesome code as well. That's a great bargain if they would trade in some effort. If someone wants help, we should not need to crawl through their previous posts or need be told from other forums members about their previous posts, as they need to make every effort to make it easier for us to help them.
 
Anthony. Take the following with a grain of salt, as my recent posts have been taken out of context and removed for being a little to blunt. Now you know me better than that. I don't and won't forum crawl through any members posts for anyone, and neither should any one else. If someone wants help especially from me, then they need to put in the effort and provide ALL of the necessary information on the opening topic or they will get a bunch of assumptions and speculative answers from us. Other people might not have a problem forum crawling through old posts but my time is valuable as I have a busy hectic life, and my time spent helping on these boards won't be spent crawling through posts just because some OP's won't bother to put in the required time and effort to construct a decent opening question. But I appreciate the pointers you've shared above.

Regarding the OP wanting to circumvent memory allocations and decrease overall memory usage. OP would be best listening to lectures from Bjarne Stroustrup who has suggested trying to write code which does not require a lot of garbage collection. And that's best done by :

I have no problem trying to help the OP with the lag they are experiencing, and I am willing to help them to irradiate it if they provide what was previously requested. But they will need to be more forthcoming with code they are using, and for them to do that, they will first need to start profiling their application to see what scripts are causing excessive memory usage, and then sharing the troublesome code files with the community so we can all help them to improve the code they currently have. The OP was asked to provide all relevant code twice as of now. I normally charge a minimum of €180 per hour for game developing; a typical minimum €10,000 per project. And I offer code help for free on these forums providing the OP puts in an equal amount of effort to describe their problem in detail and while providing the troublesome code as well. That's a great bargain if they would trade in some effort. If someone wants help, we should not need to crawl through their previous posts or need be told from other forums members about their previous posts, as they need to make every effort to make it easier for us to help them.
I know the difference between stack and heap allocations, and I've been writing my game code carefully that I re-use objects during runtime instead of instantiating and deleting. I promise you I'm not an idiot. And yes, the sockets are allocating on the heap, which is a problem because the garbage collector comes along every few seconds and causes a lagspike.

I don't really know what other information you need, other than sendTo and receiveFrom create heap allocations, even though I'm re-using my buffers to receive, and using pre-allocated buffers to send. Unity has it's own profiler and it's quite literally telling me where it's happening.

So apparently this is an unavoidable problem and I just decided to go with a library instead that promises 0 allocations on sending and receiving instead. Though if anyone has a "fix" for it, or a proper tutorial on writing raw sockets that don't allocate memory, I'll happily read it.

Edit: Sorry, if I'm still not providing the information you need. I'm in the middle of finals week and can't spend a whole lot of time on this right now.
 
Good link!

Reading the comments on that GitHub issue, it looks like part of the issue was a design issue, another part of the issue is the problem became worse when the code got re-orged for .NET Core, and another part of the issue is that the engineers were writing defensively (likely because of the code re-org) and so do extra allocations as part of that defensive programming. Cue @Sheepings rant about MS developers. ( It's okay, I don't mind. He knows that I'm an ex-MSFTie and I don't mind this because he often hits upon the truth of things.)

Now, if only Stephen Toub or someone else over at MS would respond to the questions in that link regarding the background history and design decisions, it would likely accelerate the re-writing or creation of another similar API which doesn't allocate as much memory thanks to the magic of open source.

In the meantime, it looks like your best bet is to use another library for your UDP traffic. Personally, I would likely just write some code in C++ that makes direct calls to WSAPI and use IJW to make an assembly accessible from C#, but I don't know how well that will work with Unity and cross-platform.
 
And yes, the sockets are allocating on the heap, which is a problem because the garbage collector comes along every few seconds and causes a lagspike.
Hmm, have you tried or thought to consider changing your design patterns? This may require you to literally rewrite your game, or a lot of it. May I ask if you are using any specific unity assets for world building/lever construction and such? As they can cause problems environmentally in your world viewer. And how much of your world you are rendering to each user of your game?

Cue @Sheepings rant about MS developers. ( It's okay, I don't mind. He knows that I'm an ex-MSFTie and I don't mind this because he often hits upon the truth of things.)
@Skydiver, I always seem to offend the Microsoft X devs for some reason. :)

One thing I have never done on any forum; and that is hold back from saying how I see things. As I consider myself to have good judgement calls simply because I do my homework before I speak or write. I call things as they are or as I see them. If I'm wrong, I will always put up my hand and say 'my bad, I was wrong here'. You may have overlooked my remarks about Microsoft in general and the future of .Net. I bring this up because it's Ironic that you said :
Personally, I would likely just write some code in C++ that makes direct calls to WSAPI and use IJW to make an assembly accessible from C#, but I don't know how well that will work with Unity and cross-platform.
I'm mentioned that in the above linked post. I've found myself doing this quite a lot in the last few months. OK Not specifically what I quoted you on, but I have returned to the realms of lower-level programming to make assemblies for issues similarly reported by the OP. However, in regards to your suggestion, I don't think this would cause an issue in Unity if it was added as an already compiled assembly. The OP could run a test assembly and see if their are any compilation problems (I doubt there will), and if that suggestion works, It too would be the steps I would take. This is actually an easily achievable solution since you can also use Lua in Unity. ( NOTE : This is likely to only work for Desktop and Mobile. )
 
It's what I found delightful about you @Sheepings : you call a spade a spade.

No it's ironic. After reading through the github thread, and then poring over the reference source, as well as some of the github .NET Core source, I can see where the design decisions were buried deep into the .NET Socket class design. Even taking away some of the defensive programming and merging the code bases back together into the same assembly would still incur allocations. The conclusion I came to was that the only option would be to start from scratch to prevent accidentally breaking someone who is dependent on the current behavior. And if the OP is unwilling to start from scratch, then pick up someone else UDP library. Since our OP sounded like they were already skilled in basic TCP/IP socket programming, it seemed like the path of least of resistance is to write some sockets code in C++ and let the MSVC compiler magic provide the appropriate managed code wrappers. I defer to you on the feasibily of using such an assembly a cross platform manner. It sounds like you've already tried it and found that it works.
 
It sounds like you've already tried it and found that it works.
I've done something similar before. You can import an assembly and use the script engine in Unity to communicate with the chosen transport protocol. I should note, that by using Lua as the intermediate language between the assembly and the external Unity plugin, may develop its only latency issues since this would also require you to initialise the Lua runtime as well. While this is still definitely the angle I'd take on it or try, it's worth a note; Lua needing to be initialised, may actually create its own problems and the purpose of introducing Lua originally was to use it with Unity's external plugins (I was assuming the OP knew this). I may need to think a little more on this...

To escape using Lua, you need to not use Unity's external plugins. this would mean writing your own low-level assembly, but correct me If I'm wrong, but wouldn't they then need to write one for each OS they target? Since each OS has different API's Unity would generally build the app bundling the assembly, but it will be up to the OP to determine what OS it is being run on and not Unity.

Regarding running the game on Linux... there is a risk it may not take to the users assembly. Unless one is wrote for each OS?
 
Yup, the would need an IJW assembly for each target OS. I don't know if the MSVC C++ compiler can do that kind of targeting, so the user may have to figure out if Mono has a C++ IJW like compiler.
 
c# now has overloads using a SocketAddress instead of an EndPoint. These new methods avoid the allocations that the older EndPoint methods incurred when they copied the EndPoint. You can read about it here:
 
Thanks for the update.
 
Back
Top Bottom