|
You last visited: Today at 08:39
Advertisement
Optimizing to use less CPU?
Discussion on Optimizing to use less CPU? within the CO2 Private Server forum part of the Conquer Online 2 category.
10/15/2011, 17:32
|
#1
|
elite*gold: 0
Join Date: Feb 2007
Posts: 340
Received Thanks: 38
|
Optimizing to use less CPU?
Hello everybody.
I would like to ask you how could I optimize a server to use less CPU and use more RAM instead?
I know that some things can't be taken by the RAM but even so there can be a lot of things to make a server run faster.
So how could that be made?
|
|
|
10/16/2011, 00:21
|
#2
|
elite*gold: 12
Join Date: Jul 2011
Posts: 8,282
Received Thanks: 4,191
|
C++
|
|
|
10/16/2011, 03:08
|
#3
|
elite*gold: 21
Join Date: Jul 2005
Posts: 9,193
Received Thanks: 5,380
|
Ok... the real question is why would you try to 'shift it towards ram'?... why not just increase the efficiency of your coding and avoid the issue all together?
Lets face it... these days ram and cpu prices on servers are **** cheap (vps or dedi, doesn't matter). Because of this it's all to tempting to write something less efficient and save yourself some work because well... who cares really if it uses a few extra kb of ram?
If you're needing to ask this question though is sounds more like you've got some large inefficiencies in your programming which is causing threads to remain open, (near) infinite looping, memory leaks or other types of issues causing your resources to be put into any real amount of demand.
Note: I apologize if you meant this as a theoretical question...
|
|
|
10/16/2011, 04:21
|
#4
|
elite*gold: 0
Join Date: Feb 2009
Posts: 920
Received Thanks: 3,514
|
or maybe, just maybe, hes talking about his pc which doesn't have the specification of a vpn?
|
|
|
10/16/2011, 06:28
|
#5
|
elite*gold: 20
Join Date: Jan 2008
Posts: 2,012
Received Thanks: 2,885
|
Using CPU is less expensive than using RAM, that's why. Getting more RAM is no problem, getting a better processor is a hassle. The point is though, if you're worrying about these kinds of things you really should be using C++
|
|
|
10/16/2011, 07:22
|
#6
|
elite*gold: 0
Join Date: Feb 2009
Posts: 920
Received Thanks: 3,514
|
Quote:
Originally Posted by InfamousNoone
Using CPU is less expensive than using RAM, that's why. Getting more RAM is no problem, getting a better processor is a hassle. The point is though, if you're worrying about these kinds of things you really should be using C++
|
huh? did you just mix things up? lol ;p
|
|
|
10/16/2011, 10:17
|
#7
|
elite*gold: 21
Join Date: Jul 2005
Posts: 9,193
Received Thanks: 5,380
|
Quote:
Originally Posted by m7mdxlife
or maybe, just maybe, hes talking about his pc which doesn't have the specification of a vpn?
|
If his home pc can't outperform a crappy vps then he should stop using windows 98 and get into the current millennium.
Seriously... most server stats people are using to host servers are more similar to the stats on my phone then my home pc.
|
|
|
10/16/2011, 10:17
|
#8
|
elite*gold: 0
Join Date: Feb 2007
Posts: 340
Received Thanks: 38
|
well I don't have any issues with memory leaks but I made plenty of threads to take care of several things so they could be done faster than they were if only 1 or 2 threads were looping the specific code
there could be some things that are really inneficient
Mobs attacking, checking near players (this would take a lot of CPU):
There's a hashtable taking each map with monster, then each monster in that hashtable is checking if any player is close to that mob.
Now during that check it is taking every single player in that map and it's checking if the player is a tanker (checking a stack of players) and this way if it doesn't find a tanker it goes through all players again to find a target.
Now there's this tanking check...
If you didn't move for 3 seconds it checks once for all players in your map and on your location and makes them "not tank" so you become the tanker...this is a stupid way to make tanks but it worked though it's inneficient.
And I made 3 threads for players (to fill their stamina, xp, regular checks,)
and 3 threads for player attacks
1 thread for mobs spawning
1 thread for mobs attacking,checking (couldn't split these threads to check for half and half mobs)
I don't know if this takes more CPU or not but I noticed that if I use only 1 thread for all these checks then it's slower and uses more CPU (permanently 80-100%)
All suggestions are welcome
and EDIT: well I'm running a VPS from godaddy because they don't have a dedicated server in Europe...I chose them because they can help me with the DDoS problems I have...so if anyone knows some services of dedicated servers in europe with a good DDoS protection you can link that one too
|
|
|
10/16/2011, 10:32
|
#9
|
elite*gold: 21
Join Date: Jul 2005
Posts: 9,193
Received Thanks: 5,380
|
Quote:
Originally Posted by ryuchetval
well I don't have any issues with memory leaks but I made plenty of threads to take care of several things so they could be done faster than they were if only 1 or 2 threads were looping the specific code
there could be some things that are really inneficient
Mobs attacking, checking near players (this would take a lot of CPU):
There's a hashtable taking each map with monster, then each monster in that hashtable is checking if any player is close to that mob.
Now during that check it is taking every single player in that map and it's checking if the player is a tanker (checking a stack of players) and this way if it doesn't find a tanker it goes through all players again to find a target.
Now there's this tanking check...
If you didn't move for 3 seconds it checks once for all players in your map and on your location and makes them "not tank" so you become the tanker...this is a stupid way to make tanks but it worked though it's inneficient.
And I made 3 threads for players (to fill their stamina, xp, regular checks,)
and 3 threads for player attacks
1 thread for mobs spawning
1 thread for mobs attacking,checking (couldn't split these threads to check for half and half mobs)
I don't know if this takes more CPU or not but I noticed that if I use only 1 thread for all these checks then it's slower and uses more CPU (permanently 80-100%)
All suggestions are welcome
|
Few questions... please don't take them as flames I'm a mix of curious and concerned though...
#1: Hashtables... why on earth are you using hashtables? They are out-performed by just about every data collection from what I've seen... What .net are you using? :S Definitely consider moving to the newer versions of .net and moving towards systems that are not so depreciated.
#2: Your threading and screen systems seems... incredibly over complicated...
Personally my map system uses a collection of all ILocatableObjects on a map instance. All this contains is object UID, X and Y. Because of this we can query objects based on UID (looking up an object such as a target for trade/attack packet) or based on coordinate information (including simple geometry to find all objects within the 'screen' of another object).
For my monster threading system I simply do the following...
(simplified description as it's quite a long snippet if I were to post the full thing)
I keep a simple collection of the UID of all objects of each type currently on my screen... When a player moves I pull all objects queried as on screen from its new position. Then what I do is I compare the NEW objects to the OLD objects.
Any objects in the new list that are NOT on the old must be spawned :: if it's an entity and is Inside its view range then ADD it to active entities
Any objects in BOTH lists can be ignored (they were not removed or added. Still on screen)
Any objects NOT in the new list and ARE in the old list means we need to remove them (from local list and send despawn packet) :: If it's an entity and is outside our viewrange then remove it from active entities.
Now, my threading system ONLY operates on this active entities collection. This means the monster should be both ON a player screen AND inside view range of it.
When iterating this collection I do a few quick safety checks such as if monster is null or dead (always do most generic checks first so you can skip the rest of the loop using continue  . Once you've done safety and error checks on the objects you want to do your normal ai calculations (does it have a target yet, can it move yet, can it attack yet, does it have valid possible targets.
If the monster no longer has any targets within its viewrange it becomes idle and is removed from active monster collection entirely.
Because this thread only operates on current monsters it should never be processing more than a few hundred items at once. A full AI check of this scale should take a few milliseconds max and poses very little cpu strain whatsoever. (Note: you can loop the thread quickly.. say 50-100 ms just make sure you always use things such as when the actual object can move/attack again. Makes things run smoother)
#3: 3 threads for player attacks? what the hell are you doing that for?... all I do is say take all my connected players (I use a dictionary personally just storing <uint, Player> and check if it's nextattack > now and if it has a target. If either of those checks fail go on to the next loop. If they do not fail then try to pull its target, out of range clear it, etcetc. All simple logic checks and quickly you narrow down the iteration to more like 5-50 iterations total... again virtually no cpu strain whatsoever.
#4: a warning... be sure that your using proper thread sleeping on your infinite loops or it will obviously just suck your cpu.
Also be sure that your threads are not performing stupidly slow due to silenced errors. I had that issue with my mob threading for a while and tracked it down by using the stopwatch class. Basically I timed how long the entire thread took to run and if it was suspiciously high (say... over 10-50 ms depending on how much is running on the thread) then you know there's some serious inefficiencies inside that thread loop and/or it should be split into more threads.
|
|
|
10/16/2011, 12:02
|
#10
|
elite*gold: 0
Join Date: Feb 2007
Posts: 340
Received Thanks: 38
|
Well I didn't study c# at all, I started using the source (5165, from arco's FAQ thread) for 1 year and learned pretty much from messing around with the source... so I don't really know the fastest way to deal with a collection.
Also from what I can think with a collection of <uid, x, y> still makes me think of taking all uids and check if i am in range of it's x, y coords, so it's still slow? I know very little of taking elements from collections.
However all those threads for attacks are pretty usefull, if I use only 1 some characters might attack 1 second after they click to attack and CPU will be even more stressed.
Also I use 5 miliseconds sleep after each thread loop (until it reaches the time that it should run again) or should I make it sleep the interval of time it should loop by after each execution?
|
|
|
10/16/2011, 12:10
|
#11
|
elite*gold: 0
Join Date: May 2011
Posts: 1,769
Received Thanks: 756
|
Quote:
Originally Posted by ryuchetval
Well I didn't study c# at all, I started using the source (5165, from arco's FAQ thread) for 1 year and learned pretty much from messing around with the source... so I don't really know the fastest way to deal with a collection.
Also from what I can think with a collection of <uid, x, y> still makes me think of taking all uids and check if i am in range of it's x, y coords, so it's still slow? I know very little of taking elements from collections.
However all those threads for attacks are pretty usefull, if I use only 1 some characters might attack 1 second after they click to attack and CPU will be even more stressed.
Also I use 5 miliseconds sleep after each thread loop (until it reaches the time that it should run again) or should I make it sleep the interval of time it should loop by after each execution?
|
Just make a collection with clients in the currentmap. Instead using an integer as mapid, then use a struct or a class, depending on your needs. Then you can handle everything within the map there. Much easier ^^
|
|
|
10/16/2011, 12:52
|
#12
|
elite*gold: 20
Join Date: Mar 2006
Posts: 6,126
Received Thanks: 2,518
|
I think you need to have a rethink to be honest, CPU and RAM are not interchangeable, CPU increases when things are worked, you cannot work data in RAM, so you cant just reduce CPU load by increase RAM load.
If your really having trouble, and by that i mean 100% CPU 100% of the time, then you need to look at redesigning your use of threads in your source, move more things to the threadpool class for example, making sure that your not spinning threads unnecessarily and therefore using CPU without actually working anything. You could look at using more of a task orientated approach.
|
|
|
10/16/2011, 13:46
|
#13
|
elite*gold: 21
Join Date: Jul 2005
Posts: 9,193
Received Thanks: 5,380
|
Quote:
Originally Posted by ryuchetval
Well I didn't study c# at all, I started using the source (5165, from arco's FAQ thread) for 1 year and learned pretty much from messing around with the source... so I don't really know the fastest way to deal with a collection.
Also from what I can think with a collection of <uid, x, y> still makes me think of taking all uids and check if i am in range of it's x, y coords, so it's still slow? I know very little of taking elements from collections.
However all those threads for attacks are pretty usefull, if I use only 1 some characters might attack 1 second after they click to attack and CPU will be even more stressed.
Also I use 5 miliseconds sleep after each thread loop (until it reaches the time that it should run again) or should I make it sleep the interval of time it should loop by after each execution?
|
You need to understand how inheritance and interfaces work. It lets you compare objects of different types (players, mobs, npcs, etc) using variables they share in common (in this case they all have a uid and game map position). This lets you do simple calculations such as 'onScreen' type bools very quickly without having to convert between object types every time manually.
5 ms seems stupidly slow... what possible thing does a character do that needs to occur 200 times a second?
My attach threading is more like 100-200 ms sleep (10-20 times a second... NO character will EVER attack that fast). I store a variable for the time when the next attack can occur on that character (determined by stats, cyclone, etc when i execute an attack).
If the thread tries to run on that character and it can't attack yet, I simply move to the next character.
Also... I don't use auto attack for first attack... what I mean by that is that when I click a target I try to process that attack. If my character can't attack yet (they already clicked something else within last X ms) it sets their auto attack packet to the received packet. Thread takes over from there and will process within the next 100-200 ms.
As mentioned by others... I'd go back to basics and learn some more about the language in general and how to make things more efficient across the board. It sounds like it will help you out a great deal.
|
|
|
10/16/2011, 15:58
|
#14
|
elite*gold: 0
Join Date: Feb 2007
Posts: 340
Received Thanks: 38
|
by the way, when I'm taking a foreach do I have to lock the object/collection I'm searching in (for ex taking characters in characters pool) so that some errors like "moddified collection" don't occur?
|
|
|
10/17/2011, 01:43
|
#15
|
elite*gold: 21
Join Date: Jul 2005
Posts: 9,193
Received Thanks: 5,380
|
Use a form of thread safe collection such as concurrent dictionary.
(was debated at great lengths in another thread while everyone /facepalmed at people's refusal to upgrade to newer versions of .net)
|
|
|
All times are GMT +1. The time now is 08:39.
|
|