Extrema

by Pirion
This library creates a container that allows you to store a single value within minimum and maximum constants.
In response to Theactivenet
You must be doing something wrong.

http://files.byondhome.com/TheMagicMan/walkrand.jpg

This is 2169 mobs at 10fps doing nothing but walk rand. It hovers around 20% cpu usage.

Anyway, as far as I am aware there is no BYOND game that even has half as many players as this active at once. And if I'm not mistaken, BYOND doesn't handle movement the same way it handles procs being called so it's not really accurate to compare the two.
If the game gets popular, it sure as hell will. As little as 350 default movement calls at 10fps half way maxes out a 3.5ghz thread, and since BYOND's single threaded that could impose a big issue for a lot of games.


What in the name of spode are you doing that maxes out a 3.5ghz thread at 3500 movements per second?

I've had 50,000 objects moving per second in my test environments on a 3.6ghz core I7.
mob

Stat()

stat("CPU:", world.cpu)
stat("Objects", omg.len)

Login()

var/obj/pixel/p

for(var/x = 1 to 352)

p = new
p.Move(locate(1,1,1),0,0,x-1)

global.omg += p

..()

obj/pixel
icon = 'pixel.dmi'
step_size = 1

var
omg[0]

mob/verb/GetReadyMove()
for(var/any in omg)
walk(any, EAST)

world
maxx = 11
maxy = 11
maxz = 1


That's all I'm doing and the fps is by average around 45-55 on an i7-4770K after GetReadyMove() is called. I assume pixel movement isn't active in your projects and/or there isn't continuous movement?

Anyway, as far as I am aware there is no BYOND game that even has half as many players as this active at once. And if I'm not mistaken, BYOND doesn't handle movement the same way it handles procs being called so it's not really accurate to compare the two.

There doesn't have to be any players for the Move() call to take place. If every player had their own exclusive little doppelganger the amount of Move() calls could double.

Just copy it into a new project and comment out 'pixel.dmi' and you'll get an fps after GetReadyMove is called.

Anyways, speaking of BYOND internals... This is pretty funny... Here's how to get garbage data in BYOND that might be kin to inducing a memory leak.

mob/Login()
src << A
var A = 5

Returns a /list for me that causes Dream Seeker to hang up if you try to find it's length, or if you try to access one of its elements.
Your problem is that you are not just moving objects, you are creating objects on the fly in the same location.

Your objects are stacking up on top of each other, and they have to consider one anothers' density when moving. This makes the Move() proc take a lot longer.

Space them out a bit, and you'll notice your CPU goes down significantly.

mob

Stat()

stat("CPU:", world.cpu)
stat("Objects", omg.len)

Login()

var/obj/pixel/p

for(var/x = 1 to 352)

p = new
p.Move(locate(1,x,1),0,0,x-1)

global.omg += p

..()

obj/pixel
icon = 'pixel.dmi'
step_size = 1

var
omg[0]

mob/verb/GetReadyMove()
for(var/any in omg)
walk(any, EAST)

world
maxx = 11
maxy = 352
maxz = 1


For me, this simple change drops the world CPU to 0.

Part of the reason your example hurts world CPU so bad, is that you have to call Cross 352^2 times, and Uncross 352^2, Crossed 352^2 and Uncrossed 352^2 times per object per frame, ten frames a second.

That's approximately 123,904 of each of the 4 procs per frame, or 495,616 function calls per frame, or 4,956,160 function calls per second.

Obviously, that's a lot of work that you are loading onto BYOND. Consider your claim debunked.
For further proof that BYOND can handle more than a paltry 350 objects moving at one time:

mob

Stat()

stat("CPU:", world.cpu)
stat("Objects", omg.len)

Login()

var/obj/pixel/p

for(var/z = 1 to 7)

for(var/x = 1 to 10000)

p = new
p.Move(locate(1,x,z),0,0,x-1)

global.omg += p

..()

obj/pixel
icon = 'pixel.dmi'
step_size = 1

var
omg[0]

mob/verb/GetReadyMove()
world << "([world.maxy],[world.maxx],[world.maxz])"
for(var/any in omg)
walk(any, EAST)

world
maxx = 100
maxy = 10000
maxz = 7
icon_size = "1x1"


This peaks at a little over 101 CPU on my machine at 10FPS. That's 70,000 objects, and Seven hundred thousand movements per second
In response to Ter13
I didn't consider those conditions; thanks for enlightening me.
And my CPU peaks at around 70 with your example. I guess my computer's just better well optimized than yours is.
This is a side question that's a little off topic but what program is that speed test run in? Sorry if its off topic.
This is a side question that's a little off topic but what program is that speed test run in? Sorry if its off topic.

Dream Seeker has a profiling tool. Right click on the title bar of Dream Seeker, and click on server->Profile...
In response to Zecronious
If the situation calls for an object, then I would say it should be turned into an object. There's nothing wrong with using objects that way (I do it myself), in fact I find it to be very robust.
Not sure if relevant, but I usually keep a handy Clamp function laying around.

// Text Macro Form
#define Clamp(N,L,H) max(min(N,H),L)

// Function Form
proc/Clamp(N=0,L=0,H=100)
return max(min(N,H),L)

// Example Use:
proc/Test()
var/d = 100
d = Clamp(d,0,50) // d is now 50.
world << d // prints 50.
Thanks, sure is relevant. I actually added the macro form in my last update.
Page: 1 2