ID:1947134
 
(See the best response by Lummox JR.)
Code:
/*
These are simple defaults for your project.
*/


#define DEBUG
client/preload_rsc = "http://files.byondhome.com/Kamuna/testart.zip"

world
fps = 60 // 25 frames per second
icon_size = 32 // 32x32 icon size by default

view = 6 // show up to 6 tiles outward from center (13x13 view)


// Make objects move 8 pixels per tick when walking

mob
step_size = 8
var/list/overlay_objects = list()

verb/ChangeResource(T as text)
client.preload_rsc = T
icon = 'wow.dmi'

proc/AddOverlay(obj/O)
overlays += O
overlay_objects += O
O.overlay_appearance = overlays[overlays.len]
O.overlay_num = overlays.len

proc/RemoveOverlay(obj/O)
src.overlays -= O
src.overlay_objects -= O
var/list/overlays = src.overlays.Copy()
for(var/i = O.overlay_num to overlays.len)
var/obj/A = src.overlay_objects[i]
//world << "[O.overlay_num] <= [A.overlay_num] <= [overlays.len]"
A.overlay_num -= 1
//world << "[O.overlay_num] <= [A.overlay_num] <= [overlays.len]"
O.overlay_appearance = null
O.overlay_num = 0



Login()
. =..()
spawn()
while(src && src.client)
winset(src,"mainwindow","title=\"Server - CPU Usage: [world.cpu]%\"")
sleep(world.tick_lag)

var/image/I = new
I.icon = 'hat.dmi'
I.loc = src
src.client.images += I

for(var/i = 1 to 22)
var/obj/O = new
O.icon = 'hat.dmi'
//O.pixel_y = 16
O.layer = FLOAT_LAYER
O.color = rgb(rand(0,255),rand(0,255),rand(0,255))
AddOverlay(O)
/*spawn(rand(30,90)/*22/i*/)
RemoveOverlay(O)*/
spawn()
while(O && O.overlay_appearance && O.overlay_num)
//world << O.overlay_num
ChangeOverlayLayer(O.overlay_num, 1)
I.pixel_x = 0
I.pixel_y = 1
sleep(0.5)
I.pixel_x = 1
I.pixel_y = 0
if(O && O.overlay_appearance && O.overlay_num)
ChangeOverlayLayer(O.overlay_num, FLOAT_LAYER)
sleep(0.5)

obj
step_size = 8
var/appearance/overlay_appearance
var/overlay_num


mob/proc/ChangeOverlayColor(olay, clr)
var/list/overlays = src.overlays.Copy()
if(!clr) clr="#fff"
var/i
if(isnum(olay))
i = olay
olay = overlays[i]
else
i = overlays.Find(olay)
if(i)
var/obj/O = overlay_objects[i]
//O.appearance = olay
O.color = clr
O.alpha = 255 // no fair including alpha in the color
overlays[i] = O
src.overlays = overlays
O.overlay_appearance = src.overlays[i]

mob/proc/ChangeOverlayLayer(olay, layer)
var/list/overlays = src.overlays.Copy()

var/i
if(isnum(olay))
i = olay
olay = overlays[i]
else
i = overlays.Find(olay)
if(i)
var/obj/O = overlay_objects[i] //Instead, add and remove and change using "[olay] - [i]"
if(O)
//O.appearance = olay
O.layer = layer
overlays[i] = O
src.overlays = overlays
O.overlay_appearance = src.overlays[i]


mob/proc/ChangeOverlayIcon(olay, icon)
var/list/overlays = src.overlays.Copy()

var/i
if(isnum(olay))
i = olay
olay = overlays[i]
else
i = overlays.Find(olay)
if(i)
var/obj/O = overlay_objects[i] //Instead, add and remove and change using "[olay] - [i]"
if(O)
//O.appearance = olay
O.icon = icon
overlays[i] = O
src.overlays = overlays
O.overlay_appearance = src.overlays[i]


Problem description:
This is a quick test project I had laying around, so please don't mind the sloppiness and the generally bad practices. But Dream Seeker seems to be using up tons of memory without freeing it. It seems to do have something to do with images, appearances, or proc calls. As soon as I changed the code to not remove the overlays and create an image and continuously shake it, DS keeps using memory but never uses existing memory or frees memory.
It does this for my current project (which currently doesn't change any overlays at all, and doesn't use much overlays, but uses a ton of images), but is around 10 to 100 times as bad. Any clue why this is happening? I know DS caches appearances, but after a certain point, it should stop using up memory and just reuse old memory, and yet it doesn't. The server remains fine, no problems with the server at all, which stays at a constant memory usage. The version I am using is 509.1300.

Edit: Tested it on 508.1299, and it doesn't have the problem at all. Uh oh. I guess it's time to make a bug report?
Best response
There are a couple of leaks going on in 509.1300 that will be addressed in the next build. I was hoping to get that released today but some annoying crap came up. Even more annoying crap has come up that I'll have to sort out tomorrow, but I think 1301 is on track for release then anyway.
Ah, that makes sense. When I check the bug reports, I see some things that might be related. Well, since you've seen this, and since there are other bug reports on memory leaks that may be related, I guess there's no need to make a bug report. I thought that it might just be something in my coding somehow, so that's why I didn't put this in bug reports in the first place.
1301 is out, so you should be able to use it without the leak.
Well crap, this update breaks everything with images, which then promptly crashes Dream Seeker.

EDIT: Another note is that too many images using animate() on screen slows down the client considerably. This is on the stable release, too.

EDIT2: Wait, no, that's not the problem. The problem seems to be too many images with icon/icon_states being on the screen at once, however, it doesn't seem to have a problem with others... Let me do some more research.

EDIT3: Huh, this seems to happen just based on pixels, as if it is using my CPU instead of my GPU. Strange...

EDIT4: Nope, using software mode is much slower. Well, I'm stumped. I'll just hope for better rendering or that it's only an issue on my end. Doesn't really matter much anyways on multiplayer mode.
Bumping to say that the problem stops occurring after removing animate() from being called for so many images. Could have also been a failed install or couple of failed compiles. Who knows? At this point, I don't need animate() for players anymore, as I have my own system in place in order keep the animations for each part in sync without much detriment to the server at all.
Are images broken or not? I'm not sure I follow your post at all. If there's a bug here, please do post a bug report so I can investigate.
Yes, they very much are, I just tested. Use animate() on a pack of images every so often, and use icon_state, like so (this is a simplification, but it still breaks):
for(var/p = 1 to globalparts.len) //Parts are images.  Only images are in globalparts.
var/image/o = src.globalparts[p]
animate(icon_state = "[src.animation]_[frame]", time = time, loop = loop)


To add more on the behavior, it seems as if random maptext is appearing in place of the actual image icon.
Your animate() call isn't actually doing anything with the image. You're not specifying an object, so animate() is adding stages onto the last new animation you created.
Sorry, that was the wrong part to copy, since I copied only the most relevant pieces (I thought you could figure it out, but I understand now that that was a poor assumption since it was so ambiguous.). Here is the full simplified version (some values you must define yourself):
            for(var/p = 1 to globalparts.len)
var/image/o = src.globalparts[p]
var/frame = src.ani_frame
var/startup = TRUE
if(maxframes > 1)
for(var/i = 1 to maxframes)
if(frame > maxframes)
frame -= maxframes

if(startup)
animate(o, icon_state = "[src.animation]_[frame]", time = time, loop = loop, flags = ANIMATION_END_NOW)
startup = FALSE
else
animate(icon_state = "[src.animation]_[frame]", time = time, loop = loop)

frame += 1
firstimage = FALSE
else
src.ani_frame = 1
o.icon_state = "[src.animation]_1"


Same concept, however. Just one was taken more out of context than the other. Editing this post right now to give you an even more simplified version...
Actually I don't have time to right now, gotta catch a bus. After I come back, I'll do it.
If you can condense this down into a demo and post a bug report I can take a look at it. Or even if you can't condense it, if there's a project that shows it reliably, that's a help.
var/maxframes = 6
var/list/globalparts = list()
for(var/i = 1 to 22)
globalparts += image('icon.dmi', src, layer=3+i)
src.client.images += globalparts[i]

//...

for(var/p = 1 to globalparts.len)
var/image/o = globalparts[p]
for(var/i = 1 to maxframes)
if(startup)
animate(o, icon_state = "animation_[i]", time = time, loop = loop, flags = ANIMATION_END_NOW)
startup = FALSE
else
animate(icon_state = "animation_[i]", time = time, loop = loop)


I'll make a demo tomorrow or eventually, but it isn't urgent for me at all, yet. Problem is that I always have to make a demo, which takes some time off the project. I don't want to release even the host files at the moment. Well, actually, now that I think about it, it doesn't really matter all that much right now, as I didn't even code in any hub path or anything, I think. But even so, you wouldn't be able to take a look at the code, and I definitely do not want to release the source code (not yet, at least).
You realize though you're not actually "releasing" the source code. You can make it available via a private URL and only send that to me privately.
I guess. I'm just overly paranoid for no good reason, but I just can't bring myself to do it.
In response to Kamuna
It's Lummox, you can feel relatively safe. :P
He has a broken copy of pondera and I am not worried about it.
(going to open source it one day anyway)
I know, but it's just a force of habit and general distrust in human beings >w< Even though I do indeed love to help people.