sunder2.1a/clan/
sunder2.1a/class/
sunder2.1a/class/bak/
sunder2.1a/doc/ideas/
sunder2.1a/gods/
sunder2.1a/i3/
sunder2.1a/log/
sunder2.1a/msgbase/
sunder2.1a/player/
sunder2.1a/src/o/
sunder2.1a/time/
SunderMud 2
----------- 
File Updated: June 23, 2002
By:           Lotherius (elfren@blkbox.com)

This file is based primarily upon the original document by:
    Furey	mec@shell.portal.com
    Hatchet	hatchet@uclink.berkeley.edu
    Kahn	michael@uclink.berkeley.edu
Updated for SunderMud 2.0

=== Memory Management Overview

SunderMud contains the following memory regions: run file memory; stack; string
space; and permanent space. String space is managed by Erwin's SSM, or
Shared String Manager. Please read the README.SSM file for information on
that.

Estimated Memory Usage:

Here's the simple version:

  PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME COMMAND
23215 mud       15   0  4976 4972   776 S     0.0  2.5   0:04 sundermud

That's about 75 strings and perms, the rest is the executable code and stack
space.
	
=== Saving Memory

I've done a lot of work to try to save memory in SunderMud 2. Part of this
is a feeling of guilt over having made so many memory leaks on my own in the
past, that I feel I have to not only fix them but go one farther and reduce
memory usage in every way I can, without sacrificing flexibility.

One way to do this is to make sure things not needed by mobs aren't located
in the CHAR_DATA structure, but rather in the PC_DATA structure. I can't
begin to remember how many things I moved out of one to the other, and I
know there are more.

Another is to not create static structures of [MAX_WHATEVER] size if you
don't plan on using them. I've been guilty of it in the past, and I think
there might be a few left in the code, but it is best to avoid it.

With the memlog feature, you can see where most space is being allocated,
and where in some cases, it's going and not being returned. With this
weapon, you should be able to keep a handle on your memory usage.

=== String Space and fread_string()

At boot time, the function fread_string() is used to read in ~-delimited
strings from area files.  These strings are stored into string space.  After
all of the area files are read in, string space is read-only for the duration
of the program.

String space is allocated once on bootup and is not expandable.  As
distributed, SunderMud 2 uses ~2000k of string space.  You can lower or raise
this number by editing the value of 'MAX_CHUNKS' in merc.h

Duplicate strings are stored only once into string space; hashing is used to
achieve this.  The hash code for a string is simply its length.  Each string in
string space is prefaced with a backpointer to the previous string with the
same hash code.  (Aliasing through a union is needed to read and write these
pointers, because they can start at any byte boundary, and thus are
misaligned).

When fread_string() reads a new string, it creates the string at the end of
string space.  It then finds the first hash pointer for that length and follows
the thread of hash pointers, looking for an already existing string with the
same contents.  Strings in the hash chain are checked newest-first, which
benefits from the usual construction of area files, where duplicates are
usually duplicates of something seen recently.

If fread_string() finds that the new string is a duplicate, it simply discards
the new string and returns a pointer to the existing string.  If the string is
new, it leaves it at the end of string space, fills in the new hash pointers,
and returns the new string.

After area-file loading is over, fread_string is also used to read player
files.  In this case, new strings are not appended to string space, but instead
are simply handed to str_dup().  Thus the amount of string space used is fixed
at area-file loading time.

The functions str_dup() and free_string() take advantage of string space.  If a
string being duplicated is in string space, str_dup() simply returns the same
pointer, and increases its internal counters.

If a string being freed is in string space, free_string() will:

1)  look for it in overflow and if it is there free the memory.
2)  look for it in string space and mark it as free to be defragged
    and reused.
	
This strategy not only saves megabytes of memory through string
re-use, but also saves processor time as well.

Thus a cheap method is needed for deciding whether a given string is in string
space.  This is one reason why strings are stored in one contiguous region of
size MAX_STRING.  (The hash chains, however, would still work with
noncontiguous allocation, and do not require it).

Collecting all strings into one region has another advantage: locality of
reference.  Most strings are unused most of the time.  Because they are not
interspersed with other dynamically allocated memory, a virtual memory
operating system can page out almost all of the string space without affecting
performance.

After boot time the unused end of string space is wasted.  This amounts to
about 200k in Sunder 2.  On a VM system (one that pages virtual memory, rather 
than requiring everything to remain in RAM such as a Real-Time OS might do) 
this space is unused space is paged out quickly, so it doesn't hurt to leave it 
alone. Most Unix-type OS's, including Linux, do this. 

The Shared String Manager will use any of this free space for new strings
that are generated, if any, during the operation of the game.

It is recommended you keep your "slack" string space in the range of around
100k to 200k to allow maximum flexibility while not using too much memory.
The String Manager can survive using "Overflow" and will be able to continue
allocating memory, but the performance of the game will suffer greatly if
strings are allowed to overflow often. Therefore it is recommended if your
string usage increases past the limit, to increase MAX_CHUNKS in merc.h
until you have free string space available.

The most common times you'll need to increase MAX_STRING is when you add new
areas - these use a lot of string space.


=== Permanent space

This space holds everything else: all of the area file non-string data; all of
the created mobiles and objects; descriptor and player character structures;
you name it.

This space is dynamically allocated from calloc() in large blocks, which are
carved up and handed out as needed by alloc_perm().  As distributed, Merc 2.1
uses about 1024k of permanent space.

Unlike string space, permanent space grows on demand; alloc_perm() calloc's and
carves up as many blocks as needed as the game runs.

You can adjust the block size by changing MAX_PERM_BLOCK in 'db.c'.  Adjustment
will have only a minor effect on space and time usage.  If you port Merc to a 
new system with a 64k or 32k limit on calloc() size, you could simply change
MAX_PERM_BLOCK to the largest calloc'able block on your system.

Merc never calls free() to return memory.  Instead, memory is recycled for
future use.  This has two advantages: it's faster to recycle a block than to
call free(), and it's faster to allocate a block from a free list than to
allocate one from calloc() or alloc_perm().  Most of the structure types have
their own free lists: char_free, obj_free, affect_free, et cetera.

Variable-sized blocks don't fit the per-structure-type free-list model.  The
functions alloc_mem() and free_mem() manage blocks of arbitrary size.  They
actually work by maintaining fixed-size lists for just a few supported sizes
and rounding requests up to a supported size.  This is extremely fast; because
there are so few variable-sized blocks, the space penalty is inconsequential.