So we’re having an issue on a production mud with a clear memory leak in the current version of FluffOS. I’ll be honest - I’m not sure where to begin to try to help track it down, but coming here for a bit of guidance in figuring it out.
Reproducing is very, very easy - taking any large directory with this config/setup - loading everything / then destructing it doesn’t seem to free up memory. mud_status(0) and (1) seems to clear up, but the memory usage server side keeps climbing slowly.
After about 15 days or so, we hit about 16G of ram on the process and the kernel kills it off.
Boot time memory usage on the system usually is around the 20-100 meg range. After 2ish days of uptime, here’s where we stand:
system memory info:
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
1205 bing 20 0 1742M 997M 10828 S 0.7 12.7 43:03.81 /OBFUSCATED/bin/driver /OBFUSCATED/bin/config
mud_status(0)
Sentences: 15156 606240
Objects: 4197 3711152
Prog blocks: 1833 3027160
Arrays: 44942 4134560
Classes: 6086 576848
Mappings: 14201 3437144
Mappings(nodes): 41641
Interactives: 4 9376
Memory used(bytes): 29504
All strings: 94381 2254559 + 2330680 overhead
call out: 10 640 (load_factor 0.078740)
--------
Total: 20117863
mud_status(1)
current working directory: /OBFUSCATED/lib
add_message statistics
------------------------------
Calls to add_message: 1136568 Packets: 1136568 Average packet size: 96.62 bytes
Hash table of living objects:
-----------------------------
242 living named objects, average search length: 0.54
Apply lookup cache information
-------------------------------
% cache hits: 28.48
total lookup: 1492552388
cache hits: 425044657
cache size (bytes w/o overhead): 8319168
Object name hash table status:
------------------------------
Elements: 3899
Memory(bytes): 31192
Bucket count: 10273
Load factor: 0.379539
Heart beat information:
-----------------------
Number of objects with heart beat: 582.
All strings:
------------------------- Strings Bytes
All strings: 102190 2513647 + 2518096 overhead
Total asked for 338039 6182490
Space actually required/total string bytes 81%
Searches: 1823321741 Average search length: -1.046
Call out information:
---------------------
Number of allocated call outs: 11, 704 bytes.
Current handle map bucket: 127
Current handle map load_factor: 0.086614
Current object map bucket: 5087
Current object map load_factor: 0.082563
Number of garbage entry in object map: 409
Boot log:
========================================================================
Full Command Line: /OBFUSCATED/bin/driver /OBFUSCATED/bin/config
Boot Time: Sat Feb 13 08:03:59 2021
Version: fluffos v2019.20201121-27-g1aaafdcc (Linux/x86-64)
jemalloc Version: 5.2.1-0-gea6b3e973b477b8061e0076bb257dbd7f3faa756
ICU Version: 67.1
Backtrace support: libdw.
Core Dump: No, Max FD: 65535.
========================================================================
Final Debug Level: 0
Processing config file: /OBFUSCATED/config
maximum local variables: invalid new value, resetting to default.
New Debug log location: "log/debug.log".
Initializing internal stuff ....
Event backend in use: epoll
==== Runtime Config Table ====
time to clean up : 3600 # default: 600
time to reset : 1800 # default: 900
time to swap : 2700 # default: 300
evaluator stack size : 65536
inherit chain size : 30
maximum evaluation cost : 300000000 # default: 30000000
maximum local variables : 64
maximum call depth : 150
maximum array size : 15000
maximum buffer size : 400000
maximum mapping size : 15000 # default: 150000
maximum string length : 200000
maximum bits in a bitfield : 1200 # default: 12000
maximum byte transfer : 200000
maximum read file size : 200000
hash table size : 7001
object table size : 1501
living hash table size : 256
gametick msec : 100 # default: 1000
heartbeat interval msec : 2000 # default: 1000
sane explode string : 0 # default: 1
reversible explode string : 0
sane sorting : 1
warn tab : 0
wombles : 1 # default: 0
call other type check : 0
call other warn : 1 # default: 0
mudlib error handler : 1
no resets : 0
lazy resets : 1 # default: 0
randomized resets : 0 # default: 1
no ansi : 1
strip before process input : 1
this_player in call_out : 1
trace : 0 # default: 1
trace code : 0
interactive catch tell : 0
receive snoop : 0 # default: 1
snoop shadowed : 0
reverse defer : 0
has console : 1
noninteractive stderr write : 1 # default: 0
trap crashes : 1
old type behavior : 0
old range behavior : 0
warn old range behavior : 1
suppress argument warnings : 1
enable_commands call init : 0 # default: 1
sprintf add_justified ignore ANSI colors : 1
call_out(0) nest level : 10000 # default: 1000
trace lpc execution context : 0
trace lpc instructions : 0
enable mxp : 0
enable gmcp : 0
enable zmp : 0
enable mssp : 1
==============================
==== LPC Predefines ====
#define FLUFFOS
#define HAS_DEBUG_LEVEL
#define HAS_ED
#define HAS_PRINTF
#define MAX_FLOAT 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
#define MAX_INT 9223372036854775807
#define MIN_FLOAT 0.000000
#define MIN_INT -9223372036854775808
#define MUDOS
#define MUD_NAME "Dawn"
#define SIZEOFINT 8
#define __ARCH__ "Linux/x86-64"
#define __ARGUMENTS_IN_TRACEBACK__
#define __ARRAY_STATS__
#define __AUTO_SETEUID__
#define __AUTO_TRUST_BACKBONE__
#define __CACHE_STATS__
#define __CALLOUT_HANDLES__
#define __CALL_OTHER_WARN__
#define __CFG_COMPILER_STACK_SIZE__ 600
#define __CFG_EVALUATOR_STACK_SIZE__ 65536
#define __CFG_LIVING_HASH_SIZE__ 256
#define __CFG_MAX_CALL_DEPTH__ 150
#define __CFG_MAX_GLOBAL_VARIABLES__ 65536
#define __CLASS_STATS__
#define __COMMAND_BUF_SIZE__ 2000
#define __COMPILER__ "/usr/bin/c++"
#define __CXXFLAGS__ "Broken"
#define __DEBUG_MACRO__
#define __DEFAULT_DB__ 1
#define __DEFAULT_PRAGMAS__ PRAGMA_WARNINGS + PRAGMA_ERROR_CONTEXT + PRAGMA_OPTIMIZE
#define __DSLIB__
#define __ED_INDENT_SPACES__ 4
#define __ED_TAB_WIDTH__ 8
#define __GET_CHAR_IS_BUFFERED__
#define __HAS_CONSOLE__
#define __HAVE_DIRENT_H__ 1
#define __HAVE_JEMALLOC__ 1
#define __HAVE_SIGNAL_H__ 1
#define __HAVE_SYS_RESOURCE_H__ 1
#define __HAVE_SYS_STAT_H__ 1
#define __HAVE_SYS_TIME_H__ 1
#define __HAVE_TIME_H__ 1
#define __LARGEST_PRINTABLE_STRING__ 65535
#define __LARGE_STRING_SIZE__ 1000
#define __LAZY_RESETS__
#define __LOCALS_IN_TRACEBACK__
#define __MAX_SAVE_SVALUE_DEPTH__ 100
#define __MUDLIB_ERROR_HANDLER__
#define __NONINTERACTIVE_STDERR_WRITE__
#define __NO_LIGHT__
#define __OLD_ED__
#define __PACKAGES_PACKAGES_H__
#define __PACKAGE_ASYNC__
#define __PACKAGE_COMPRESS__
#define __PACKAGE_CONTRIB__
#define __PACKAGE_CORE__
#define __PACKAGE_CRYPTO__
#define __PACKAGE_DB__
#define __PACKAGE_DEVELOP__
#define __PACKAGE_MATH__
#define __PACKAGE_MATRIX__
#define __PACKAGE_MUDLIB_STATS__
#define __PACKAGE_OPS__
#define __PACKAGE_PARSER__
#define __PACKAGE_PCRE__
#define __PACKAGE_SHA1__
#define __PACKAGE_SOCKETS__
#define __PACKAGE_TRIM__
#define __PACKAGE_UIDS__
#define __PARSE_DEBUG__
#define __PORT__ 3000
#define __PROJECT_VERSION__ "fluffos v2019.20201121-27-g1aaafdcc"
#define __REF_RESERVED_WORD__
#define __RESTRICTED_ED__
#define __SANE_SORTING__
#define __SAVE_EXTENSION__ ".o"
#define __SAVE_GZ_EXTENSION__ ".o.gz"
#define __SMALL_STRING_SIZE__ 100
#define __STRING_STATS__
#define __STRUCT_CLASS__
#define __STRUCT_STRUCT__
#define __SUPPRESS_ARGUMENT_WARNINGS__
#define __THIS_PLAYER_IN_CALL_OUT__
#define __TIME_WITH_SYS_TIME__ 1
#define __TRAP_CRASHES__
#define __USE_32BIT_ADDRESSES__
#define __USE_MYSQL__ 1
#define __VERSION__ "fluffos v2019.20201121-27-g1aaafdcc"
#define __WARN_OLD_RANGE_BEHAVIOR__
#define __WOMBLES__
========================
Config File:
name : Dawn
port number : 3000
mudlib directory : /OBFUSCATED/lib
log directory : /log
include directories : /include
save binaries directory : /binaries
master file : /secure/master
simulated efun file : /secure/simul_efun
debug log file : debug.log
global include file : <standard.h>
time to clean up : 3600
time to swap : 2700
time to reset : 1800
maximum bits in a bitfield : 1200
maximum local variables : 30
maximum evaluation cost : 300000000
maximum array size : 15000
maximum buffer size : 400000
maximum mapping size : 15000
inherit chain size : 30
maximum string length : 200000
maximum read file size : 200000
maximum byte transfer : 200000
hash table size : 7001
object table size : 1501
default fail message : What?
default error message : A terrible breach in the fabric of space has occurred.
gametick msec : 100
heartbeat interval msec : 2000
sane explode string : 0
reversible explode string : 0
sane sorting : 1
warn tab : 0
wombles : 1
call other type check : 0
call other warn : 1
mudlib error handler : 1
no resets : 0
lazy resets : 1
randomized resets : 0
no ansi : 1
strip before process input: 1
this_player in call_out : 1
trace : 0
trace code : 0
interactive catch tell : 0
receive snoop : 0
snoop shadowed : 0
reverse defer : 0
has console : 1
noninteractive stderr write : 1
trap crashes : 1
old type behavior : 0
old range behavior : 0
warn old range behavior : 1
suppress argument warnings : 1
enable_commands call init : 0
sprintf add_justified ignore ANSI colors : 1
call_out(0) nest level : 10000
# maximum users : 40
# evaluator stack size : 1000
# compiler stack size : 200
# maximum call depth : 30
# living hash table size : 100