ID:764350
 
(See the best response by Nadrew.)
Profile:
                                  Profile results (total time)
Proc Name Self CPU Total CPU Real Time Calls
-------------------------------------------- --------- --------- --------- ---------
/mob/mobs/start 2836.503 2896.235 582370.563 21578
/mob/proc/mobcheck 33.849 2830.942 565216.563 532645
/client/proc/savegame 145.881 496.566 48782.426 15704
/mob/Write 333.418 333.436 333.473 15703
/mob/Stat 7.362 134.555 521407.375 249926
/obj/projectile/Fire 78.327 121.768 72620.891 31897
/mob/proc/updatestats 1.779 103.227 103.305 229675
/client/Move 22.159 101.889 102.175 650676
/mob/proc/bullycheck 0.078 98.561 17088.494 9797
/mob/proc/updatecompletestats 89.838 90.216 90.319 186142
/mob/Move 73.695 85.811 86.211 873278


Problem description: The server uses too much CPU. I don't know any other means of reducing it, I have tried random fixes.

/mob/mobs/start: starts the AI
/mob/proc/mobcheck: checks surrounding mobs around you that aren't 'active'
/mob/proc/bullycheck: checks for a certain mob and starts it


Saving:
client/proc
savegame()
set background = 1
var/savefile/f = new("players/[ckey].sav")
if(mob)
f["playername"] << mob.name
f["mob"] << mob


AI:
mob/proc
bullycheck(var/mob/m)
set background = 1
if(istype(m, /mob/mobs/Bully) && !m.active) spawn() m.start()

mobcheck()
set background = 1

for(var/mob/mobs/m in viewers(7, src))
if(!m || m.active && m.target != null || !see_invisible && m.invisibility || istype(m, /mob/mobs/Bully))
continue

m.target = src
spawn() m.start()

mob
start()
set background = 1

if(active || !target)
return

active = 1

while(active && target != null && get_dist(src, target) <= 7)
if(stamina >= maxstamina * 0.20)

if(get_dist(src, target) == 1 && punchdelay <= world.time) attack(target)
if(get_dist(src, target) >= 2) step_to(src, target)

else

step_away(src, target)

sleep(4)
Looks like /mob/mobs/start() is taking up most of the resources, you should look into refining that function to be less intensive.
In response to Nadrew
Nadrew wrote:
Looks like /mob/mobs/start() is taking up most of the resources, you should look into refining that function to be less intensive.

I don't know the greatest way to write AI systems, I try to do with what I know. I have to have the mobs moving around obstacles, things like step_towards() doesn't do that.

EDIT: I updated the original post with the AI.
Best response
You should probably be leaving the AI inactive unless it needs to be active. Doing something like 'activating' the AI when a player comes within view of the NPC saves a lot of resources.
In response to Nadrew
Nadrew wrote:
You should probably be leaving the AI inactive unless it needs to be active. Doing something like 'activating' the AI when a player comes within view of the NPC saves a lot of resources.

mobcheck() is called on client/Move(), this is how an AI is activated. start() is the actual AI loop.
It appears that the start() loop isn't being allowed to finish; it looks like it should with the distance check but perhaps there's something else causing it to trigger needlessly.

Are you making sure NPC's can't cause the AI of other NPC's to activate?
In response to Nadrew
I could perhaps use (target in viewers(7, src)), but I heard that it uses more resoureces, and I doubt that the get_dist() doesn't work.

client
Move()
if(mob.movementdelay > world.time)
return

spawn() if(mob.level >= 20) mob.mobcheck()

return ..()


It's built on client/Move(), so I presumed non-players couldn't active them.
BYOND's profiler doesn't make it easy to tell where the CPU time is spent. I'm pretty sure it includes calls to sleep towards the proc's self CPU time. The start() proc has a lot of CPU time because it hits the sleep() statement a lot, not because it's doing a lot of expensive computations.

As long as there's no way you're activating the mob's AI loop twice for the same mob, I don't see anything that'd be using up a lot of CPU time.
The problem is that step_to()/get_step_to()/walk_to (anything that deals with _to()) uses an insane amount of CPU usage. With 3 players and almost a full screen of active mobs, the CPU usage peaked over 100%.

This would freeze up the Linux server I am using, causing me to have to forcefully shutdown DreamDaemon through kill.

EDIT: With approximately 120 mobs, with world.cpu, it returned, on average, 100-130%. The server CPU was approximately 50-65%, on average. (only when the mobs are attempting to step_to() another mob)