Common sources of excessive RAM usage?

MysticalMist

Well-known member
So I'm in the midst of optimizing and debugging my project and I realized (albeit I should've caught onto this sooner rather than later) that my game has used a concerning amount of RAM (aka almost 1.5G) and there's not even that many entities or data that would would warrant that kind of stress on the engine. I'm correcting code and I will say I have at least taken care of some overlapping/excessive scripts but I can't help but feel like I'm missing some more painfully obvious things. What would anyone else suggest?

I was able to reduce the usage to at least roughly 807,800 to 819,800 kb on average, but that's still dangerously concerning from what I can tell.
 
@Kratus, @DCurrent, so how would the sprite be drawn once the mp hits 100 and the hp is less than half the max? I only ask since the drawsprite function doesn't work with the global variable.

I feel like I need to rewrite my script completely somehow but I'll admit I'm currently struggling that at the moment. I feel unsure as to how to properly use the oncreate/ondestroy functions in this context.

I have this in my main in the updated.c alongside the rest of the functions/code:

Code:
 if(getglobalvar("superbar") == NULL ()){
    setglobalvar("superbar", loadsprite("data/sprites/frame5.png"));
}

Whereas my player.c draw script looks like this currently:
Code:
//SUPER MOVE INDICATOR
void self = getlocalvar("self");
int mp = getentityproperty(self, "mp");
int hp = getentityproperty(self, "health");
int hpmax = getentityproperty(self, "maxhealth");
void sample = loadsample("data/sounds/superready.wav");
int executed = getlocalvar("executed");

if (executed == NULL()) {
    executed = 0;
}

if (openborvariant("in_level")) {
    int index = getentityproperty(self, "playerindex");
    int mpx;
 
    if (index == 1) {
        mpx = 265;
    } else if (index == 2) {
        mpx = 400;
    } else if (index == 3) {
        mpx = 570;
    } else {
        mpx = 10;
    }
    if (mp == 100 && hp < (hpmax/2)) {

      void Frame1 = getglobalvar("Frame1");
      void Frame2 = getglobalvar("Frame2");
      void Frame3 = getglobalvar("Frame3");
      void Frame4 = getglobalvar("Frame4");
      void Frame5 = getglobalvar("Frame5");
      void Frame6 = getglobalvar("Frame6");
 drawstring(mpx, 50, 2, "SUPER MOVE READY (D > F > Unique)", 100);
 //drawsprite("superbar", mpx-20, 50, 9999); this is obviously incorrect but you get the idea at least lol

}

    if (mp == 100 && executed == 0 && hp < (hpmax/2)) {
        // Play the sound sample
        playsample(sample, 0, 200, 200, 100, 0);

        // Mark as executed to prevent looping
        executed = 1;

    } else if (mp < 100) {
        // Reset executed state if mp drops below 100
        executed = 0;
    }

    // Save the executed state
    setlocalvar("executed", executed);
}
 
@Kratus, @DCurrent, so how would the sprite be drawn once the mp hits 100 and the hp is less than half the max? I only ask since the drawsprite function doesn't work with the global variable.

I feel like I need to rewrite my script completely somehow but I'll admit I'm currently struggling that at the moment. I feel unsure as to how to properly use the oncreate/ondestroy functions in this context.

I have this in my main in the updated.c alongside the rest of the functions/code:

Code:
 if(getglobalvar("superbar") == NULL ()){
    setglobalvar("superbar", loadsprite("data/sprites/frame5.png"));
}

Whereas my player.c draw script looks like this currently:
Code:
//SUPER MOVE INDICATOR
void self = getlocalvar("self");
int mp = getentityproperty(self, "mp");
int hp = getentityproperty(self, "health");
int hpmax = getentityproperty(self, "maxhealth");
void sample = loadsample("data/sounds/superready.wav");
int executed = getlocalvar("executed");

if (executed == NULL()) {
    executed = 0;
}

if (openborvariant("in_level")) {
    int index = getentityproperty(self, "playerindex");
    int mpx;
 
    if (index == 1) {
        mpx = 265;
    } else if (index == 2) {
        mpx = 400;
    } else if (index == 3) {
        mpx = 570;
    } else {
        mpx = 10;
    }
    if (mp == 100 && hp < (hpmax/2)) {

      void Frame1 = getglobalvar("Frame1");
      void Frame2 = getglobalvar("Frame2");
      void Frame3 = getglobalvar("Frame3");
      void Frame4 = getglobalvar("Frame4");
      void Frame5 = getglobalvar("Frame5");
      void Frame6 = getglobalvar("Frame6");
 drawstring(mpx, 50, 2, "SUPER MOVE READY (D > F > Unique)", 100);
 //drawsprite("superbar", mpx-20, 50, 9999); this is obviously incorrect but you get the idea at least lol

}

    if (mp == 100 && executed == 0 && hp < (hpmax/2)) {
        // Play the sound sample
        playsample(sample, 0, 200, 200, 100, 0);

        // Mark as executed to prevent looping
        executed = 1;

    } else if (mp < 100) {
        // Reset executed state if mp drops below 100
        executed = 0;
    }

    // Save the executed state
    setlocalvar("executed", executed);
}
I suggest looking at the SOR2X codes, if I'm not wrong the sprites used for mp management are working the way you need.
 
I suggest looking at the SOR2X codes, if I'm not wrong the sprites used for mp management are working the way you need.

Going off what I saw, here's what I did.

In my updated.c, here's what I added:
Code:
 if(getglobalvar("superbar") == NULL ()){
 setglobalvar("superbar", loadsprite("data/sprites/frame5.png"));
}

In my player ondrawscript, here's where it is called:
Code:
if (openborvariant("in_level")) {
    int index = getentityproperty(self, "playerindex");
    int mpx;
 
    if (index == 1) {
        mpx = 265;
    } else if (index == 2) {
        mpx = 400;
    } else if (index == 3) {
        mpx = 570;
    } else {
        mpx = 10;
    }
    if (mp == 100 && hp < (hpmax/2)) {

      void Frame1 = getglobalvar("Frame1");
      void Frame2 = getglobalvar("Frame2");
      void Frame3 = getglobalvar("Frame3");
      void Frame4 = getglobalvar("Frame4");
      void Frame5 = getglobalvar("Frame5");
      void Frame6 = getglobalvar("Frame6");
 drawstring(mpx, 50, 2, "SUPER MOVE READY (D > F > Unique)", 100);
 drawsprite(getglobalvar("superbar"), mpx-20, 50, 9999); //this line

}

    if (mp == 100 && executed == 0 && hp < (hpmax/2)) {
        // Play the sound sample
        playsample(sample, 0, 200, 200, 100, 0);

        // Mark as executed to prevent looping
        executed = 1;

    } else if (mp < 100) {
        // Reset executed state if mp drops below 100
        executed = 0;
    }

    // Save the executed state
    setlocalvar("executed", executed);
}

}

It seems to be working as intended, however the log shows that only one script is unfree (this one) and the ram usage does incrementally go up by a small, yet noticeable amount. I tried certain ways to free the variable just in case, but I've yet to find one that didn't crash or go back to blowing up the RAM usage.

P.S., I'm assuming this is not the best either, seeing as how a lot of examples I've seen of good ram usage is around roughly 150,000 kb, how big of a problem would this be? 1744250307047.png
 
In my updated.c, here's what I added:

Instead of doing that, why not declaring that in update.c 's oncreate() section? like this:
C:
void oncreate()
{
  void SBar = loadsprite("data/sprites/frame5.png");

  setglobalvar("superbar", SBar);
}

No need to check if it has been loaded before or not since oncreate() is only run once.

however the log shows that only one script is unfree (this one)

You do that in ondestroy() section with these scripts:
C:
void ondestroy(){
    void SBar = getglobalvar("superbar");

   free(SBar);

    setglobalvar("superbar", NULL());
}

HTH
 
Instead of doing that, why not declaring that in update.c 's oncreate() section? like this:
C:
void oncreate()
{
  void SBar = loadsprite("data/sprites/frame5.png");

  setglobalvar("superbar", SBar);
}

No need to check if it has been loaded before or not since oncreate() is only run once.



You do that in ondestroy() section with these scripts:
C:
void ondestroy(){
    void SBar = getglobalvar("superbar");

   free(SBar);

    setglobalvar("superbar", NULL());
}

HTH

Seemed to do the trick! Thanks!

I'm still going to have to look around the rest of the scripts in my project since I can't help but get a nagging feeling in the back of my head that it can/should be lower.
 
P.S., I'm assuming this is not the best either, seeing as how a lot of examples I've seen of good ram usage is around roughly 150,000 kb, how big of a problem would this be?
1744250307047.png
Considering that you started at 1.5gb, 169mb was a good reduction.

No need to check if it has been loaded before or not since oncreate() is only run once.
@MysticalMist

The @Bloodbane's tip is good, but don't forget that if you use clearglobalvar() somewhere, the oncreate() will not run again and the variable stays cleared. You can bypass it by clearing specific variables manually instead of using clearglobalvar().
The ondestroy() is fine since you are closing the game.
 
I'm still going to have to look around the rest of the scripts in my project since I can't help but get a nagging feeling in the back of my head that it can/should be lower.
Extra tip: Check your script library to look for duplicated entries. As an example, it's common to see games with a lot of spawn01 repeated countless times in different files. Instead, create one and use the #import directive.

The same goes for small entities used for special effects. Sometimes it's better to have an unique entity with multiple animations instead of having multiple entities with one animation (will depend on the palette size too). Plus always try to create reusable entities that may fit for different situations.
 
I have not even started playing my game yet. It started at the title screen and the memory was already rocket high.
I only have 2 sprites for non-animation background.

as I went through went the boss rush mode, it went up to like 1.7 to 2 gb...
well, all my sprites are in 1080p.
I may have to remove more sprites and some of FX models have "load", will have to change to "know" and work around it....

1744461664108.png

Update:
I just removed the set of FX sprites that have alot of stuff in them, the memory consumption went down to 500-600!
Heavy sprites do eat a lot of memory!
I will continue to hunt down heavy sprites to reduce further memory consumption
 
Last edited:
Back
Top Bottom