Carpet

Carpet

2M Downloads

Memory leak with display_title for header and footer? (HUDController)

replaceitem opened this issue · 4 comments

commented

I have a script on my server that continuously (every tick) updates the player list header and footer, and the server reaches memory limit (in my case 8gb) within a couple hours.

Carpet version: 1.17-1.4.40-v210608

I managed to get a heap dump file (.hprop) from the server with all memory being used.
It confirmed that the HUDController is using 52% of memory. Here is a screenshot of it opened in eclipse memory analyzer:

memory analyzed

I could upload the heap dump file somewhere, but its 6gb, so if that would help debugging i could do that.

I tried spotting the cause myself, but im not an expert in memory stuff so i wasn't successfull.

Here is the script that most likely is causing it:

__config() -> (
  m(l('stay_loaded', true),l('scope', 'global'))
);


global_evmotd = format('#00CCFF ════════▶ ');
global_evmotd += format('b#91F78C East');
global_evmotd += format('b#45C142 Valley ');
global_evmotd += format('#FFFF00 - ');
global_evmotd += format('#FF4400 1.17 ');
global_evmotd += format('#CC33FF SMP');


__on_tick() -> (

    if(tick_time() % 40 == 0,
        motd = global_evmotd;
        motd += '\n';
        motd += reduce(map(sort_key(player('all'),_~'player_type'=='fake'),_~'display_name'),_a += _ + ' ',format(' '));
        set_motd(motd);
    );


    if(tick_time() % 4 == 0,
        ticksum = 0;
        for(last_tick_times(),
            ticksum += _;
        );
        global_mspt = ticksum / length(last_tick_times());
    );


    if((tick_time() % 1) == 0,
        headerHue = tick_time()%360;
        headerGlossIndex = (floor(time()/60)%40)-10;
        header = [];
        header += ' \n';
        title = 'EastValley';
        title = split(title);
        for(title,
            if(abs(_i-headerGlossIndex) < 3,
                c = '#' + convert_color([headerHue,abs(_i-headerGlossIndex)/3*255,255],'hsb','hex');
            ,
                if(_i < 4,
                    c = '#' + convert_color([headerHue,255,190],'hsb','hex');
                ,
                    c = '#' + convert_color([headerHue,255,255],'hsb','hex');
                );
            );
            put(header,null,str('b%s %s',c,_));
        );

        header += ' \n';

        header = format(header);

        //CALCULATE MSPT

        hue = constrain(map_num(global_mspt,0,100,180,0),0,180);

        c = 0;
        for(player('all'),
            c+=(_~'player_type'!='fake');
        );

        footer = format(str('#44FF44 MSPT: '));
        footer += format(str('%s %.2f','#' + convert_color([hue,255,255],'hsb','hex'),global_mspt));
        maxmem = system_info('java_max_memory');
        mem = system_info('java_used_memory');
        hue = constrain(map_num(mem,0,maxmem,180,0),0,180);
        footer += format('#44FF44 \nMEM: ');
        footer += format(str('%s %.2fgb','#' + convert_color([hue,255,255],'hsb','hex'),mem*0.000000001));
        cpu = system_info('java_system_cpu_load');
        footer += format('#44FF44 \nCPU: ');
        hue = constrain(map_num(cpu,0,1,180,0),0,180);
        footer += format(str('%s %.2f%%','#' + convert_color([hue,255,255],'hsb','hex'),cpu*100));

        display_title(player('all'),'player_list_header',header);
        display_title(player('all'),'player_list_footer',footer);
  )
);


map_num(value,start1,stop1,start2,stop2) -> start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
constrain(v,a,b) -> (
    min = min(a,b);
    max = max(a,b);
    max(min,min(v,max));
);
commented

convert_color - unknown function ;p

commented

Is it possible that couple hundred player show up and loggs out in that timeframe?

commented

Oh yeah, convert_color is from my extension.
And there are maybe max 15 different players online in that time.

Thanks for fixing!

commented

Could also use a WeakHashMap for better performance (?) given that is ticked, in case it becomes a bottleneck at some point (and would be a bit simpler I guess), though the way you changed seems like it shouldn't cause any.

Sorry about that, totally forgot that players don't share the same instance after reconnecting.