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.