[m-dev.] FYI: cell cache

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Sep 29 20:48:01 AEDT 2000


On 28-Sep-2000, Peter Ross <petdr at miscrit.be> wrote:
> +	( { CanCGC = yes } ->
> +		ml_gen_var(Var, VarLval),
> +		{ String = string__format("MR_cache_cell(%d, MR_strip_tag(",

I would suggest spelling that as `MR_compile_time_GC'
rather than `MR_cache_cell'.

The you can do
	
	#if defined(MR_COMPILE_TIME_GC)
	  #define MR_compile_time_GC(ptr) MR_GC_free(ptr)
	#elif defined(MR_USE_CELL_CACHE)
	  #define MR_compile_time_GC(ptr) MR_cache_cell(ptr)
	#else
	  #define MR_compile_time_GC(ptr) ((void)0)
	#endif

> +++ compiler/mlds_to_c.m	2000/09/28 14:11:06
> @@ -2201,6 +2201,17 @@
>  
>  	mlds_indent(Context, Indent + 1),
>  	mlds_output_lval(Target),
> +	io__write_string(" = MR_get_cached_cell("),
> +	io__write_int(list__length(Args)),
> +	io__write_string(");\n"),
> +	mlds_indent(Context, Indent + 1),
> +	io__write_string("if ("),
> +	mlds_output_lval(Target),
> +	io__write_string(" == (MR_Word) NULL) {\n"),
> +
> +	mlds_indent(Context, Indent + 2),
> +	mlds_output_lval(Target),

Won't that code do the wrong thing in the case when the pointer tag on
the data you're allocating is supposed to be non-zero?
I think that if you get a cache hit, you never set the tag.

Anyway, rather than putting that code here, you could put
it inside MR_new_object().

> Index: runtime/mercury_memory.c
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory.c,v
> retrieving revision 1.19.4.1
> diff -u -r1.19.4.1 mercury_memory.c
> --- runtime/mercury_memory.c	2000/09/25 17:09:11	1.19.4.1
> +++ runtime/mercury_memory.c	2000/09/28 14:11:12
> @@ -330,3 +330,77 @@
>  }
>  
>  /*---------------------------------------------------------------------------*/
> +
> +/*
> +** Compile time garbage collection cache.
> +** When structure reuse infers that a cell dies and is available for reuse,
> +** we insert it into a cache of cells available for reuse.  When allocating
> +** new memory first check if there is a cell already in the cache of the
> +** correct size and use that saving the cost of the GC.
> +**
> +** For an example of when this cache should be a win, just look at the
> +** following very common code.
> +**	
> +**	io__read_char(Result),
> +**	{
> +**		Result => ok(Char) % the ok(_) cell dies.
> +**		...,
> +**	;	
> +**		Result => eof,
> +**		...
> +**	...
> +**	}
> +**
> +** The ok(_) cell is very short lived being generated inside
> +** io__read_char and almost always immediately dieing, now imagine if we
> +** read a few characters in a row, we are going to need to create a new
> +** ok(_) cell for the next character however there is already one in the
> +** cache and hey presto we have a win!
> +*/
> +#define MR_MAX_CACHED_CELL_SIZE	10
> +static void *MR_cell_cache[MR_MAX_CACHED_CELL_SIZE+1];
> +
> +void
> +MR_cell_cache_init(void)
> +{
> +	int i;
> +
> +	for(i = 0; i <= MR_MAX_CACHED_CELL_SIZE; i++) {
> +		MR_cell_cache[i] = (MR_Word) NULL;
> +	}
> +}

You don't actually need to initialize the cells to null --
the C standard guarantees that they will be initialized to null.
So you could just omit this function.

The cast to MR_Word here is not needed.

> +void *
> +MR_get_cached_cell(size_t size)
> +{
> +	void *cell;
> +
> +	/* 
> +	** We never have to worry about the garbage collector freeing
> +	** the cached blocks because there is always at least one reference
> +	** to the cell from the cache!
> +	*/
> +	if (size > MR_MAX_CACHED_CELL_SIZE) {
> +		return (MR_Word) NULL;
> +	} else {
> +		cell = MR_cell_cache[size];
> +		MR_cell_cache[size] = (MR_Word) NULL;
> +		return cell;
> +	}
> +}

The casts to MR_Word here are not needed.

> +++ runtime/mercury_wrapper.c	2000/09/28 14:11:15
> @@ -956,6 +956,7 @@
>  
>  	for (repcounter = 0; repcounter < repeats; repcounter++) {
>  #ifdef MR_HIGHLEVEL_CODE
> +		MR_cell_cache_init();
>  		do_interpreter();
>  #else
>  		debugmsg0("About to call engine\n");

That's not really the right place to call MR_cell_cache_init().
It should be called from mercury_init(), not mercury_runtime_main().
But as noted above you don't really need it anyway.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list