*** ./src/interfaces/libpq/fe-exec.c.orig 2005-10-15 11:49:48.000000000 +0900 --- ./src/interfaces/libpq/fe-exec.c 2005-11-23 11:10:23.000000000 +0900 *************** *** 79,88 **** * we need to be able to enlarge it via realloc, and our trivial space * allocator doesn't handle that effectively. (Too bad the FE/BE protocol * doesn't tell us up front how many tuples will be returned.) ! * All other subsidiary storage for a PGresult is kept in PGresult_data blocks ! * of size PGRESULT_DATA_BLOCKSIZE. The overhead at the start of each block ! * is just a link to the next one, if any. Free-space management info is ! * kept in the owning PGresult. * A query returning a small amount of data will thus require three malloc * calls: one for the PGresult, one for the tuples pointer array, and one * PGresult_data block. --- 79,90 ---- * we need to be able to enlarge it via realloc, and our trivial space * allocator doesn't handle that effectively. (Too bad the FE/BE protocol * doesn't tell us up front how many tuples will be returned.) ! * All other subsidiary storage for a PGresult is kept in PGresult_data ! * blocks. The size of first block is PGRESULT_DATA_BLOCKSIZE. And ! * the size of the next block will be doubled until it reaches ! * PGRESULT_MAX_DATA_BLOCKSIZE. ! * The overhead at the start of each block is just a link to the next one, ! * if any. Free-space management info is kept in the owning PGresult. * A query returning a small amount of data will thus require three malloc * calls: one for the PGresult, one for the tuples pointer array, and one * PGresult_data block. *************** *** 94,100 **** * around very long anyway, so some wasted space within one is not a problem. * * Tuning constants for the space allocator are: ! * PGRESULT_DATA_BLOCKSIZE: size of a standard allocation block, in bytes * PGRESULT_ALIGN_BOUNDARY: assumed alignment requirement for binary data * PGRESULT_SEP_ALLOC_THRESHOLD: objects bigger than this are given separate * blocks, instead of being crammed into a regular allocation block. --- 96,105 ---- * around very long anyway, so some wasted space within one is not a problem. * * Tuning constants for the space allocator are: ! * PGRESULT_DATA_BLOCKSIZE: initial size of a standard allocation block, ! * in bytes ! * PGRESULT_MAX_DATA_BLOCKSIZE: maximum size of a standard allocation block, ! * in bytes * PGRESULT_ALIGN_BOUNDARY: assumed alignment requirement for binary data * PGRESULT_SEP_ALLOC_THRESHOLD: objects bigger than this are given separate * blocks, instead of being crammed into a regular allocation block. *************** *** 112,117 **** --- 117,123 ---- */ #define PGRESULT_DATA_BLOCKSIZE 2048 + #define PGRESULT_MAX_DATA_BLOCKSIZE (1024 * 2048) /* 2Mbyte */ #define PGRESULT_ALIGN_BOUNDARY MAXIMUM_ALIGNOF /* from configure */ #define PGRESULT_BLOCK_OVERHEAD Max(sizeof(PGresult_data), PGRESULT_ALIGN_BOUNDARY) #define PGRESULT_SEP_ALLOC_THRESHOLD (PGRESULT_DATA_BLOCKSIZE / 2) *************** *** 149,154 **** --- 155,161 ---- result->errFields = NULL; result->null_field[0] = '\0'; result->curBlock = NULL; + result->nextAllocSize = PGRESULT_DATA_BLOCKSIZE; result->curOffset = 0; result->spaceLeft = 0; *************** *** 200,205 **** --- 207,213 ---- pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary) { char *space; + int alloc_size; PGresult_data *block; if (!res) *************** *** 264,270 **** } /* Otherwise, start a new block. */ ! block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE); if (!block) return NULL; block->next = res->curBlock; --- 272,279 ---- } /* Otherwise, start a new block. */ ! alloc_size = res->nextAllocSize; ! block = (PGresult_data *) malloc(alloc_size); if (!block) return NULL; block->next = res->curBlock; *************** *** 273,290 **** { /* object needs full alignment */ res->curOffset = PGRESULT_BLOCK_OVERHEAD; ! res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - PGRESULT_BLOCK_OVERHEAD; } else { /* we can cram it right after the overhead pointer */ res->curOffset = sizeof(PGresult_data); ! res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - sizeof(PGresult_data); } space = block->space + res->curOffset; res->curOffset += nBytes; res->spaceLeft -= nBytes; return space; } --- 282,304 ---- { /* object needs full alignment */ res->curOffset = PGRESULT_BLOCK_OVERHEAD; ! res->spaceLeft = alloc_size - PGRESULT_BLOCK_OVERHEAD; } else { /* we can cram it right after the overhead pointer */ res->curOffset = sizeof(PGresult_data); ! res->spaceLeft = alloc_size - sizeof(PGresult_data); } space = block->space + res->curOffset; res->curOffset += nBytes; res->spaceLeft -= nBytes; + + /* Set the next allocation size. */ + if(res->nextAllocSize < PGRESULT_MAX_DATA_BLOCKSIZE) { + res->nextAllocSize *= 2; + } return space; } *** ./src/interfaces/libpq/libpq-int.h.orig 2005-10-15 11:49:49.000000000 +0900 --- ./src/interfaces/libpq/libpq-int.h 2005-11-23 10:47:01.000000000 +0900 *************** *** 174,179 **** --- 174,180 ---- * separately malloc'd block, so that we can realloc it. */ PGresult_data *curBlock; /* most recently allocated block */ + int nextAllocSize; /* block size for next allocation */ int curOffset; /* start offset of free space in block */ int spaceLeft; /* number of free bytes remaining in block */ };