The attached patch is the next set of proposed changes to the memory
management routines, with the copy-on-write logic removed.

Performance numbers on my 166-MHz Pentium (linux 2.2.18) for 5000-generation
life.pasm are:
Current CVS - 50.41 generations/second
With this patch - 57.40
With COW & string_append - 65.43

The main features are:
Revised 'live' marking system with removal of mark_X_unused functions
Initial framework for dynamic allocation algorithms
Incorporation of the free pools into the standard buffer header pool, to
avoid special handling in compact_buffer_pool

Details
The 'live' flag is now only valid during a DOD run. It is cleared when an
object is created and again at the end of the DOD run. This means that the
overhead of a separate pass through the pools to clear the flag at the start
of a DOD run is eliminated. For PMCs, the next_for_GC field is treated in
the same way - initialised to NULL in new_pmc_header, and reset to NULL in
free_unused_PMCs.
The 'on_free_list' flag is used instead to identify live buffers during
memory compaction.

The initial allocation for each pool has been reduced from 128 to 16, this
is obviously an arbitrary number, but only once we have a large set of
benchmarks will be able to calculate the best 'average' values. However,
each time a new allocation is required, the number of units allocated is
increased; controlled by parameters currently defined at the top of
resources.c. Again, these numbers just seemed reasonable in some very simple
tests, and need more tuning.
Also, instead of waiting for a pool to be empty before refilling it, each
pool has a replenishment level, at which a new block will be allocated.
These replenishment levels currently start at half the original pool size,
and increase with every allocation, but at a slower rate. This helps reduce
the thrashing that can otherwise occur when the pool oscillates between
empty and almost empty.
These rules are mainly to introduce the concept of dynamic response,
hopefully suggestions/implementations of better algorithms will follow in
due course.

The free pool buffer headers were being held as independent Buffer
structures within the Resource_Pool; this meant that they had to be
separately handled in compact_buffer_pool, which looked a mess, and made it
easy to forget things. They are now held as pointers, and allocated through
the normal procedure, except for the first one. The normal buffer pool's
free pool header is first allocated from system memory, so that the pool can
be initialised. Then, a new buffer header is allocated in the standard way,
and takes over from the initial one, which is returned to the system.
This change required the addition of an 'immune' flag for buffers. I suspect
that Steve's recent changes, which make variable-sized buffer headers
simple, will allow other internal structures to be handled using the buffer
mechanism, and so the immune flag could be generally useful anyway.

[Steve - it seems to me that the 'normal' buffer pool should just be
replaced by the size 0 pool in your new system?  I would think twice about
incorporating strings, as that might complicate COW, if it ever happens.]

--
Peter Gibbs
EmKel Systems


Attachment: combined.patch
Description: Binary data

Reply via email to