🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

UDP multithreaded load balancing

Started by
27 comments, last by taby 3 years, 3 months ago

Good for you.

If I may I'd just like to recommend using Python or something like that for these kinds of jobs in the future (particularly for any new readers of this thread in the future), it's much easier to use and less work/code needed to get the job done.

I used Python code to connect and keep-alive/relog on disconnect 1000 clients to my server with only about 100 or so lines of code (template code is easy to find online) here:

Advertisement

Thanks for your comments.

I used to code in Python (e.g., https://github.com/sjhalayka/opencv_sparks),​ but it's glacial in speed. ? To compare line counts is a little suspicious, because there are a lot of { } in the C++.

Anyway, did you put load balancing into your code? If so, what kind of algorithm did you use? Was it multi-threaded?

I see. I used a single machine, actually the same for both the server and the clients. To be fair it also runs on TCP, not UDP.

Neither the server or the client emulation is multithreaded, the client code uses asyncio and the server runs on a single thread.
I'm not sure/don't really think load balancing is viable for our/this game.

I really only had the subject of stresstesting the server in mind, load balancing seems like a secondary concern after getting the stresstesting working which I wasn't sure you had in the beginning.

I'm not sure, but I assume load testing for game servers is only really viable for servers that allow the client-server pair to be somewhat out of sync (cheat detection rather than cheat prevention) where all the servers communicate with either the load server or a separate server tracker that tries to keep work shared equally across the network?

For that it seems to me if tasks are linear you share work based on the number of jobs, if they're not linear or perhaps the HW used is not the same for different servers, then you'd use resource assessments instead based on the server's CPU% and/or MEM% usage for example.

source61 said:

I see. I used a single machine, actually the same for both the server and the clients. To be fair it also runs on TCP, not UDP.

This was how I was testing it too. ? I've also written TCP speed tester and generic client-server TCP code – https://github.com/sjhalayka/tcpspeed3_multithreaded_listener

Neither the server or the client emulation is multithreaded, the client code uses asyncio and the server runs on a single thread.
I'm not sure/don't really think load balancing is viable for our/this game.

I call select before I call recvfrom. Non-blocking behaviour is basically asynchronous behaviour, right?

I really only had the subject of stresstesting the server in mind, load balancing seems like a secondary concern after getting the stresstesting working which I wasn't sure you had in the beginning.

Yes, the original UDP speed tester that I wrote like 20 years ago was single-threaded, and there was no load balancing – https://github.com/sjhalayka/udpspeed​​

I used this original UDP code to stress test fibre lines. Our ISP must have been metering the line because damned if we didn't get a result of 100 Mbits/second on the nose LOL.

Anyway, now I'm on version 5, which is multi-threaded and has load balancing. All the versions are on my GitHub.

I'm not sure, but I assume load testing for game servers is only really viable for servers that allow the client-server pair to be somewhat out of sync (cheat detection rather than cheat prevention) where all the servers communicate with either the load server or a separate server tracker that tries to keep work shared equally across the network?

For that it seems to me if tasks are linear you share work based on the number of jobs, if they're not linear or perhaps the HW used is not the same for different servers, then you'd use resource assessments instead based on the server's CPU% and/or MEM% usage for example.

I could have simply assumed that all IPs generate the same amount of socket chatter, which lets one assume that one can simply divide up the total number of jobs into the four (or however many) threads. My code instead looks for a local (perhaps global) standard deviation – a matter of elementary statistics.

P.S. I see that current (circa 2021) AMD Threadripper CPUs have like 128 threads. Why not take advantage of that?

taby said:

Neither the server or the client emulation is multithreaded, the client code uses asyncio and the server runs on a single thread.
I'm not sure/don't really think load balancing is viable for our/this game.

I call select before I call recvfrom. Non-blocking behaviour is basically asynchronous behaviour, right?

I'm not the right person to comment on this generally speaking, but asynchronous in Python basically means virtual multithreading, or that's how I understand it. It allows you to slip in and out of functions with their contexts (variables etc) at any arbitrary position, switching to another task/function/position, and switch back again within microseconds.

I really only had the subject of stresstesting the server in mind, load balancing seems like a secondary concern after getting the stresstesting working which I wasn't sure you had in the beginning.

Yes, the original UDP speed tester that I wrote like 20 years ago was single-threaded, and there was no load balancing – https://github.com/sjhalayka/udpspeed​​

I used this original UDP code to stress test fibre lines. Our ISP must have been metering the line because damned if we didn't get a result of 100 Mbits/second on the nose LOL.

Anyway, now I'm on version 5, which is multi-threaded and has load balancing. All the versions are on my GitHub.

Cool. Sounds like you probably know more C than I do if you wrote that 20 years ago. I wrote hello world 20 years ago by copying code from an outdated book on C++. Never really learned much more than that in C until a year or two ago when I decided to write my own simplified MMO game server.

P.S. I see that current (circa 2021) AMD Threadripper CPUs have like 128 threads. Why not take advantage of that?

It depends on what you're doing with it. Multithreading has their drawbacks: 1) Complexity of code (original server codebase is already 100k lines of C++ designed only for single threaded use), 2) Overhead.

I use multiple cpu threads for map loading, that's it.

And again the reason I don't use it for anything else like I explained earlier is that the server I use (the core design of the game) is that it's completely synchronous except for strictly speaking client-server latency.
There is no player movement, map updates, conversations, nothing without the server first saying “go”, and the client (slave) drawing the change.

For this model I suspect multithreading will virtually never pay off (might be wrong, but that's what I suspect, most certainly with the language I use), only for server-client pairing where asynchronous behavior is allowed.

Not to mention a single server is already capable of hosting approximately 3000 players. How many more players does one need. If I get 3000 players I'll be happy with that :D

asynchronous in Python basically means virtual multithreading

Python can run “threads,” but only one at a time. There's simply no way to saturate many cores in a single Python program – you'll have to fork (multiprocess) it to make that happen. This limitation is shared with JavaScript/node, btw.

For this model I suspect multithreading will virtually never pay off

The topic of the post is “UDP multithreaded load balancing” although I think a post saying “for me, that wasn't worth it” still fits…

enum Bool { True, False, FileNotFound };

Well, technically, the UDP speed tester is the Hello World of socket programming. LOL

As for udpspeed 1.0, that weighs in at 300 or so lines. udpspeed 5.0 weighs in at 700 or so lines. 400 lines of extra code is not bad for adding in multi-threading, job handling, timing, and IP address management. Like 100 of those lines are class definitions, so the extra code in main() is not the whole 400 lines.

I started with BASIC, and my dad had a miniframe at work with a console that supported BASIC. :D I started C when I was in my teens, and C++ when I was in my early 20s. I only learned Python a couple of years ago, so you probably have me there!

hplus0603 said:

The topic of the post is “UDP multithreaded load balancing” although I think a post saying “for me, that wasn't worth it” still fits…

Are you saying that there's no use for load balancing?

Are you saying that there's no use for load balancing?

No, I'm saying that source61 recommended against multithreading, in a thread asking about multithreading, but I think that's alright – many different opinions are valuable!

enum Bool { True, False, FileNotFound };

Cool. Sorry about that.

This topic is closed to new replies.

Advertisement