[Gs-code-review] Make memory manager scan all chunks
L. Peter Deutsch
ghost at aladdin.com
Thu Feb 21 19:56:33 PST 2002
Log entry:
Fix: Makes the standard memory manager scan all chunks, not just the
currently open one, for available free space. This is a long-planned,
long-overdue improvement that can improve memory utilization
dramatically.
Index: src/gsalloc.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gsalloc.c,v
retrieving revision 1.13
diff -C2 -r1.13 gsalloc.c
*** src/gsalloc.c 21 Feb 2002 22:24:52 -0000 1.13
--- src/gsalloc.c 22 Feb 2002 03:49:21 -0000
***************
*** 27,30 ****
--- 27,39 ----
/*
+ * Define whether to try consolidating space before adding a new chunk.
+ * The default is not to do this, because it is computationally
+ * expensive and doesn't seem to help much. However, this is done for
+ * "controlled" spaces whether or not the #define is in effect.
+ */
+ /*#define CONSOLIDATE_BEFORE_ADDING_CHUNK */
+
+
+ /*
* This allocator produces tracing messages of the form
* [aNMOTS]...
***************
*** 92,96 ****
/*
! * Define flags for the alloc_obj, which implements all but the fastest
* case of allocation.
*/
--- 101,105 ----
/*
! * Define the flags for alloc_obj, which implements all but the fastest
* case of allocation.
*/
***************
*** 808,813 ****
gs_ref_memory_t * const imem = (gs_ref_memory_t *)mem;
byte *str;
! top:if (imem->cc.ctop - imem->cc.cbot > nbytes) {
if_debug4('A', "[a%d:+> ]%s(%u) = 0x%lx\n",
alloc_trace_space(imem), client_name_string(cname), nbytes,
--- 817,833 ----
gs_ref_memory_t * const imem = (gs_ref_memory_t *)mem;
byte *str;
+ /*
+ * Cycle through the chunks at the current save level, starting
+ * with the currently open one.
+ */
+ chunk_t *cp_orig = imem->pcc;
! if (cp_orig == 0) {
! /* Open an arbitrary chunk. */
! cp_orig = imem->pcc = imem->cfirst;
! alloc_open_chunk(imem);
! }
! top:
! if (imem->cc.ctop - imem->cc.cbot > nbytes) {
if_debug4('A', "[a%d:+> ]%s(%u) = 0x%lx\n",
alloc_trace_space(imem), client_name_string(cname), nbytes,
***************
*** 817,820 ****
--- 837,852 ----
return str;
}
+ /* Try the next chunk. */
+ {
+ chunk_t *cp = imem->cc.cnext;
+
+ alloc_close_chunk(imem);
+ if (cp == 0)
+ cp = imem->cfirst;
+ imem->pcc = cp;
+ alloc_open_chunk(imem);
+ if (cp != cp_orig)
+ goto top;
+ }
if (nbytes > string_space_quanta(max_uint - sizeof(chunk_head_t)) *
string_data_quantum
***************
*** 1079,1116 ****
ptr->o_alone = 1;
ptr->o_size = lsize;
- } else if (lsize > max_freelist_size && (flags & ALLOC_DIRECT) &&
- (ptr = large_freelist_alloc(mem, lsize)) != 0) {
- /* We hadn't checked the large block freelist yet. */
- --ptr; /* must point to header */
- goto done;
} else {
uint asize = obj_size_round((uint) lsize);
! bool consolidate = mem->is_controlled;
! bool allocate_success = true;
! while (mem->cc.ctop -
! (byte *) (ptr = (obj_header_t *) mem->cc.cbot)
! <= asize + sizeof(obj_header_t)) {
! if (consolidate) {
/* Try consolidating free space. */
gs_consolidate_free((gs_memory_t *)mem);
! consolidate = false;
! continue;
! } else {
! /* Add another chunk. */
! chunk_t *cp =
! alloc_add_chunk(mem, (ulong)mem->chunk_size, "chunk");
!
! if (cp == 0) {
! allocate_success = false;
break;
}
}
}
/*
! * If no success, try to scavenge from low free memory. This is only
! * enabled for controlled memory (currently only async renderer)
! * because it's too much work to prevent it from examining outer
! * save levels in the general case.
*/
if (allocate_success)
--- 1111,1210 ----
ptr->o_alone = 1;
ptr->o_size = lsize;
} else {
+ /*
+ * Cycle through the chunks at the current save level, starting
+ * with the currently open one.
+ */
+ chunk_t *cp_orig = mem->pcc;
uint asize = obj_size_round((uint) lsize);
! bool allocate_success = false;
!
! if (lsize > max_freelist_size && (flags & ALLOC_DIRECT)) {
! /* We haven't checked the large block freelist yet. */
! if ((ptr = large_freelist_alloc(mem, lsize)) != 0) {
! --ptr; /* must point to header */
! goto done;
! }
! }
!
! if (cp_orig == 0) {
! /* Open an arbitrary chunk. */
! cp_orig = mem->pcc = mem->cfirst;
! alloc_open_chunk(mem);
! }
! #define CAN_ALLOC_AT_END(cp)\
! ((cp)->ctop - (byte *) (ptr = (obj_header_t *) (cp)->cbot)\
! > asize + sizeof(obj_header_t))
!
! do {
! if (CAN_ALLOC_AT_END(&mem->cc)) {
! allocate_success = true;
! break;
! } else if (mem->is_controlled) {
/* Try consolidating free space. */
gs_consolidate_free((gs_memory_t *)mem);
! if (CAN_ALLOC_AT_END(&mem->cc)) {
! allocate_success = true;
break;
}
}
+ /* No luck, go on to the next chunk. */
+ {
+ chunk_t *cp = mem->cc.cnext;
+
+ alloc_close_chunk(mem);
+ if (cp == 0)
+ cp = mem->cfirst;
+ mem->pcc = cp;
+ alloc_open_chunk(mem);
+ }
+ } while (mem->pcc != cp_orig);
+
+ #ifdef CONSOLIDATE_BEFORE_ADDING_CHUNK
+ if (!allocate_success) {
+ /*
+ * Try consolidating free space before giving up.
+ * It's not clear this is a good idea, since it requires quite
+ * a lot of computation and doesn't seem to improve things much.
+ */
+ if (!mem->is_controlled) { /* already did this if controlled */
+ chunk_t *cp = cp_orig;
+
+ alloc_close_chunk(mem);
+ do {
+ consolidate_chunk_free(cp, mem);
+ if (CAN_ALLOC_AT_END(cp)) {
+ mem->pcc = cp;
+ alloc_open_chunk(mem);
+ allocate_success = true;
+ break;
+ }
+ if ((cp = cp->cnext) == 0)
+ cp = mem->cfirst;
+ } while (cp != cp_orig);
+ }
+ }
+ #endif
+
+ #undef CAN_ALLOC_AT_END
+
+ if (!allocate_success) {
+ /* Add another chunk. */
+ chunk_t *cp =
+ alloc_add_chunk(mem, (ulong)mem->chunk_size, "chunk");
+
+ if (cp) {
+ /* mem->pcc == cp, mem->cc == *mem->pcc. */
+ ptr = (obj_header_t *)cp->cbot;
+ allocate_success = true;
+ }
}
+
/*
! * If no success, try to scavenge from low free memory. This is
! * only enabled for controlled memory (currently only async
! * renderer) because it's too much work to prevent it from
! * examining outer save levels in the general case.
*/
if (allocate_success)
--
L. Peter Deutsch | Aladdin Enterprises | 203 Santa Margarita Ave.
ghost at aladdin.com | http://www.aladdin.com | Menlo Park, CA 94025
The future of software is at http://www.opensource.org
More information about the gs-code-review
mailing list