From: hno <> Date: Thu, 14 Feb 2002 02:34:01 +0000 (+0000) Subject: Generic buffer allocator on top of the MEM_X_BUF memory pools. Simplifies X-Git-Tag: SQUID_3_0_PRE1~1188 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1eb41ae81a71724ea3a49b6a88fd2b9622d3975a;p=thirdparty%2Fsquid.git Generic buffer allocator on top of the MEM_X_BUF memory pools. Simplifies many parts of the code. --- diff --git a/src/MemBuf.cc b/src/MemBuf.cc index d131f70641..237f11c944 100644 --- a/src/MemBuf.cc +++ b/src/MemBuf.cc @@ -1,6 +1,6 @@ /* - * $Id: MemBuf.cc,v 1.28 2001/04/20 21:26:22 hno Exp $ + * $Id: MemBuf.cc,v 1.29 2002/02/13 19:34:02 hno Exp $ * * DEBUG: section 59 auto-growing Memory Buffer with printf * AUTHOR: Alex Rousskov @@ -131,7 +131,7 @@ memBufInit(MemBuf * mb, mb_size_t szInit, mb_size_t szMax) mb->size = 0; mb->max_capacity = szMax; mb->capacity = 0; - mb->freefunc = NULL; + mb->stolen = 0; memBufGrow(mb, szInit); } @@ -145,10 +145,9 @@ memBufClean(MemBuf * mb) { assert(mb); assert(mb->buf); - assert(mb->freefunc); /* not frozen */ + assert(!mb->stolen); /* not frozen */ - (*mb->freefunc) (mb->buf); /* free */ - mb->freefunc = NULL; /* freeze */ + memFreeBuf(mb->capacity, mb->buf); mb->buf = NULL; mb->size = mb->capacity = 0; } @@ -163,7 +162,7 @@ memBufReset(MemBuf * mb) if (memBufIsNull(mb)) { memBufDefInit(mb); } else { - assert(mb->freefunc); /* not frozen */ + assert(!mb->stolen); /* not frozen */ /* reset */ memset(mb->buf, 0, mb->capacity); mb->size = 0; @@ -188,7 +187,7 @@ memBufAppend(MemBuf * mb, const char *buf, mb_size_t sz) { assert(mb && buf && sz >= 0); assert(mb->buf); - assert(mb->freefunc); /* not frozen */ + assert(!mb->stolen); /* not frozen */ if (sz > 0) { if (mb->size + sz > mb->capacity) @@ -231,7 +230,7 @@ memBufVPrintf(MemBuf * mb, const char *fmt, va_list vargs) int sz = 0; assert(mb && fmt); assert(mb->buf); - assert(mb->freefunc); /* not frozen */ + assert(!mb->stolen); /* not frozen */ /* assert in Grow should quit first, but we do not want to have a scary infinite loop */ while (mb->capacity <= mb->max_capacity) { mb_size_t free_space = mb->capacity - mb->size; @@ -269,10 +268,10 @@ memBufFreeFunc(MemBuf * mb) FREE *ff; assert(mb); assert(mb->buf); - assert(mb->freefunc); /* not frozen */ + assert(!mb->stolen); /* not frozen */ - ff = mb->freefunc; - mb->freefunc = NULL; /* freeze */ + ff = memFreeBufFunc((size_t)mb->capacity); + mb->stolen = 1; /* freeze */ return ff; } @@ -280,79 +279,34 @@ memBufFreeFunc(MemBuf * mb) static void memBufGrow(MemBuf * mb, mb_size_t min_cap) { - mb_size_t new_cap; - MemBuf old_mb; + size_t new_cap; + size_t buf_cap; assert(mb); + assert(!mb->stolen); assert(mb->capacity < min_cap); /* determine next capacity */ - new_cap = mb->capacity; - if (new_cap > 0) - while (new_cap < min_cap) - new_cap *= 2; /* double */ - else - new_cap = min_cap; + if (min_cap > 64*1024) { + new_cap = 64*1024; + while (new_cap < (size_t)min_cap) + new_cap += 64*1024; /* increase in reasonable steps */ + } else { + new_cap = (size_t)min_cap; + } /* last chance to fit before we assert(!overflow) */ - if (new_cap > mb->max_capacity) - new_cap = mb->max_capacity; - - assert(new_cap <= mb->max_capacity); /* no overflow */ - assert(new_cap > mb->capacity); /* progress */ - - old_mb = *mb; - - /* allocate new memory */ - switch (new_cap) { - case 2048: - mb->buf = memAllocate(MEM_2K_BUF); - mb->freefunc = &memFree2K; - break; - case 4096: - mb->buf = memAllocate(MEM_4K_BUF); - mb->freefunc = &memFree4K; - break; - case 8192: - mb->buf = memAllocate(MEM_8K_BUF); - mb->freefunc = &memFree8K; - break; - case 16384: - mb->buf = memAllocate(MEM_16K_BUF); - mb->freefunc = &memFree16K; - break; - case 32768: - mb->buf = memAllocate(MEM_32K_BUF); - mb->freefunc = &memFree32K; - break; - case 65536: - mb->buf = memAllocate(MEM_64K_BUF); - mb->freefunc = &memFree64K; - break; - default: - /* recycle if old buffer was not "pool"ed */ - if (old_mb.freefunc == &xfree) { - mb->buf = xrealloc(old_mb.buf, new_cap); - old_mb.buf = NULL; - old_mb.freefunc = NULL; - /* init tail, just in case */ - memset(mb->buf + mb->size, 0, new_cap - mb->size); - } else { - mb->buf = xcalloc(1, new_cap); - mb->freefunc = &xfree; - } - } + if (new_cap > (size_t)mb->max_capacity) + new_cap = (size_t)mb->max_capacity; - /* copy and free old buffer if needed */ - if (old_mb.buf && old_mb.freefunc) { - xmemcpy(mb->buf, old_mb.buf, old_mb.size); - (*old_mb.freefunc) (old_mb.buf); - } else { - assert(!old_mb.buf && !old_mb.freefunc); - } + assert(new_cap <= (size_t)mb->max_capacity); /* no overflow */ + assert(new_cap > (size_t)mb->capacity); /* progress */ + + buf_cap = (size_t)mb->capacity; + mb->buf = memReallocBuf(mb->buf, new_cap, &buf_cap); /* done */ - mb->capacity = new_cap; + mb->capacity = (mb_size_t)buf_cap; } diff --git a/src/client_side.cc b/src/client_side.cc index 9369036fee..ba5721dfef 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side.cc,v 1.561 2001/12/12 23:44:18 hno Exp $ + * $Id: client_side.cc,v 1.562 2002/02/13 19:34:01 hno Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -868,11 +868,7 @@ connStateFree(int fd, void *data) authenticateAuthUserRequestUnlock(connState->auth_user_request); connState->auth_user_request = NULL; authenticateOnCloseConnection(connState); - if (connState->in.size == CLIENT_REQ_BUF_SZ) - memFree(connState->in.buf, MEM_CLIENT_REQ_BUF); - else - safe_free(connState->in.buf); - /* XXX account connState->in.buf */ + memFreeBuf(connState->in.size, connState->in.buf); pconnHistCount(0, connState->nrequests); cbdataFree(connState); #ifdef _SQUID_LINUX_ @@ -2722,7 +2718,6 @@ clientReadRequest(int fd, void *data) int parser_return_code = 0; request_t *request = NULL; int size; - void *p; method_t method; clientHttpRequest *http = NULL; clientHttpRequest **H = NULL; @@ -2734,15 +2729,7 @@ clientReadRequest(int fd, void *data) commSetSelect(fd, COMM_SELECT_READ, clientReadRequest, conn, 0); if (len == 0) { /* Grow the request memory area to accomodate for a large request */ - conn->in.size += CLIENT_REQ_BUF_SZ; - if (conn->in.size == 2 * CLIENT_REQ_BUF_SZ) { - p = conn->in.buf; /* get rid of fixed size Pooled buffer */ - conn->in.buf = xcalloc(2, CLIENT_REQ_BUF_SZ); - xmemcpy(conn->in.buf, p, CLIENT_REQ_BUF_SZ); - memFree(p, MEM_CLIENT_REQ_BUF); - } else - conn->in.buf = xrealloc(conn->in.buf, conn->in.size); - /* XXX account conn->in.buf */ + conn->in.buf = memReallocBuf(conn->in.buf, conn->in.size * 2, &conn->in.size); debug(33, 2) ("growing request buffer: offset=%ld size=%ld\n", (long) conn->in.offset, (long) conn->in.size); len = conn->in.size - conn->in.offset - 1; @@ -3198,9 +3185,7 @@ httpAccept(int sock, void *data) connState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr; connState->me = me; connState->fd = fd; - connState->in.size = CLIENT_REQ_BUF_SZ; - connState->in.buf = memAllocate(MEM_CLIENT_REQ_BUF); - /* XXX account connState->in.buf */ + connState->in.buf = memAllocBuf(CLIENT_REQ_BUF_SZ, &connState->in.size); comm_add_close_handler(fd, connStateFree, connState); if (Config.onoff.log_fqdn) fqdncache_gethostbyaddr(peer.sin_addr, FQDN_LOOKUP_IF_MISS); @@ -3313,8 +3298,7 @@ httpsAccept(int sock, void *data) connState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr; connState->me = me; connState->fd = fd; - connState->in.size = CLIENT_REQ_BUF_SZ; - connState->in.buf = memAllocate(MEM_CLIENT_REQ_BUF); + connState->in.buf = memAllocBuf(CLIENT_REQ_BUF_SZ, &connState->in.size); /* XXX account connState->in.buf */ comm_add_close_handler(fd, connStateFree, connState); if (Config.onoff.log_fqdn) diff --git a/src/enums.h b/src/enums.h index 97734ce3a0..0cab6b20a5 100644 --- a/src/enums.h +++ b/src/enums.h @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.203 2001/12/21 09:47:34 hno Exp $ + * $Id: enums.h,v 1.204 2002/02/13 19:34:01 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -611,7 +611,6 @@ typedef enum { MEM_EVENT, MEM_TLV, MEM_SWAP_LOG_DATA, - MEM_CLIENT_REQ_BUF, MEM_MAX } mem_type; diff --git a/src/ftp.cc b/src/ftp.cc index 3c647f4814..be0aecc49b 100644 --- a/src/ftp.cc +++ b/src/ftp.cc @@ -1,6 +1,6 @@ /* - * $Id: ftp.cc,v 1.316 2001/11/09 07:05:00 hno Exp $ + * $Id: ftp.cc,v 1.317 2002/02/13 19:34:02 hno Exp $ * * DEBUG: section 9 File Transfer Protocol (FTP) * AUTHOR: Harvest Derived @@ -112,7 +112,6 @@ typedef struct _Ftpdata { char *buf; size_t size; off_t offset; - FREE *freefunc; wordlist *message; char *last_command; char *last_reply; @@ -123,7 +122,6 @@ typedef struct _Ftpdata { char *buf; size_t size; off_t offset; - FREE *freefunc; char *host; u_short port; } data; @@ -274,21 +272,15 @@ ftpStateFree(int fdnotused, void *data) storeUnlockObject(ftpState->entry); if (ftpState->reply_hdr) { memFree(ftpState->reply_hdr, MEM_8K_BUF); - /* this seems unnecessary, but people report SEGV's - * when freeing memory in this function */ ftpState->reply_hdr = NULL; } requestUnlink(ftpState->request); if (ftpState->ctrl.buf) { - ftpState->ctrl.freefunc(ftpState->ctrl.buf); - /* this seems unnecessary, but people report SEGV's - * when freeing memory in this function */ + memFreeBuf(ftpState->ctrl.size, ftpState->ctrl.buf); ftpState->ctrl.buf = NULL; } if (ftpState->data.buf) { - ftpState->data.freefunc(ftpState->data.buf); - /* this seems unnecessary, but people report SEGV's - * when freeing memory in this function */ + memFreeBuf(ftpState->data.size, ftpState->data.buf); ftpState->data.buf = NULL; } if (ftpState->pathcomps) @@ -1094,13 +1086,9 @@ ftpStart(FwdState * fwd) ftpState->user, ftpState->password); ftpState->state = BEGIN; ftpState->ctrl.last_command = xstrdup("Connect to server"); - ftpState->ctrl.buf = memAllocate(MEM_4K_BUF); - ftpState->ctrl.freefunc = memFree4K; - ftpState->ctrl.size = 4096; + ftpState->ctrl.buf = memAllocBuf(4096, &ftpState->ctrl.size); ftpState->ctrl.offset = 0; - ftpState->data.buf = xmalloc(SQUID_TCP_SO_RCVBUF); - ftpState->data.size = SQUID_TCP_SO_RCVBUF; - ftpState->data.freefunc = xfree; + ftpState->data.buf = memAllocBuf(SQUID_TCP_SO_RCVBUF, &ftpState->data.size); ftpScheduleReadControlReply(ftpState, 0); } @@ -1282,7 +1270,6 @@ ftpReadControlReply(int fd, void *data) static void ftpHandleControlReply(FtpStateData * ftpState) { - char *oldbuf; wordlist **W; int bytes_used = 0; wordlistDestroy(&ftpState->ctrl.message); @@ -1291,12 +1278,7 @@ ftpHandleControlReply(FtpStateData * ftpState) if (ftpState->ctrl.message == NULL) { /* didn't get complete reply yet */ if (ftpState->ctrl.offset == ftpState->ctrl.size) { - oldbuf = ftpState->ctrl.buf; - ftpState->ctrl.buf = xcalloc(ftpState->ctrl.size << 1, 1); - xmemcpy(ftpState->ctrl.buf, oldbuf, ftpState->ctrl.size); - ftpState->ctrl.size <<= 1; - ftpState->ctrl.freefunc(oldbuf); - ftpState->ctrl.freefunc = xfree; + ftpState->ctrl.buf = memReallocBuf(ftpState->ctrl.buf, ftpState->ctrl.size << 1, &ftpState->ctrl.size); } ftpScheduleReadControlReply(ftpState, 0); return; diff --git a/src/mem.cc b/src/mem.cc index e8fa6b9775..f2da9c69de 100644 --- a/src/mem.cc +++ b/src/mem.cc @@ -1,6 +1,6 @@ /* - * $Id: mem.cc,v 1.60 2002/02/13 17:22:36 hno Exp $ + * $Id: mem.cc,v 1.61 2002/02/13 19:34:02 hno Exp $ * * DEBUG: section 13 High Level Memory Pool Management * AUTHOR: Harvest Derived @@ -62,6 +62,8 @@ static struct { static MemMeter StrCountMeter; static MemMeter StrVolumeMeter; +static MemMeter HugeBufCountMeter; +static MemMeter HugeBufVolumeMeter; /* local routines */ @@ -92,6 +94,15 @@ memStringStats(StoreEntry * sentry) "Other Strings", xpercentInt(StrCountMeter.level - pooled_count, StrCountMeter.level), xpercentInt(StrVolumeMeter.level - pooled_volume, StrVolumeMeter.level)); + storeAppendPrintf(sentry, "\n"); +} + +static void +memBufStats(StoreEntry *sentry) +{ + storeAppendPrintf(sentry, "Large buffers: %d (%d KB)\n", + HugeBufCountMeter.level, + HugeBufVolumeMeter.level / 1024); } static void @@ -100,6 +111,7 @@ memStats(StoreEntry * sentry) storeBuffer(sentry); memReport(sentry); memStringStats(sentry); + memBufStats(sentry); storeBufferFlush(sentry); } @@ -173,6 +185,86 @@ memFreeString(size_t size, void *buf) pool ? memPoolFree(pool, buf) : xfree(buf); } +/* Find the best fit MEM_X_BUF type */ +static mem_type +memFindBufSizeType(size_t net_size, size_t * gross_size) +{ + mem_type type; + size_t size; + if (net_size <= 2*1024) { + type = MEM_2K_BUF; + size = 2*1024; + } else if (net_size <= 4*1024) { + type = MEM_4K_BUF; + size = 4*1024; + } else if (net_size <= 8*1024) { + type = MEM_8K_BUF; + size = 8*1024; + } else if (net_size <= 16*1024) { + type = MEM_16K_BUF; + size = 16*1024; + } else if (net_size <= 32*1024) { + type = MEM_32K_BUF; + size = 32*1024; + } else if (net_size <= 64*1024) { + type = MEM_64K_BUF; + size = 64*1024; + } else { + type = MEM_NONE; + size = net_size; + } + if (gross_size) + *gross_size = size; + return type; +} + +/* allocate a variable size buffer using best-fit pool */ +void * +memAllocBuf(size_t net_size, size_t * gross_size) +{ + mem_type type = memFindBufSizeType(net_size, gross_size); + if (type != MEM_NONE) + return memAllocate(type); + else { + memMeterInc(HugeBufCountMeter); + memMeterAdd(HugeBufVolumeMeter, *gross_size); + return xcalloc(1, net_size); + } +} + +/* resize a variable sized buffer using best-fit pool */ +void * +memReallocBuf(void *oldbuf, size_t net_size, size_t * gross_size) +{ + /* XXX This can be optimized on very large buffers to use realloc() */ + int new_gross_size; + void *newbuf = memAllocBuf(net_size, &new_gross_size); + if (oldbuf) { + int data_size = *gross_size; + if (data_size > net_size) + data_size = net_size; + memcpy(newbuf, oldbuf, data_size); + memFreeBuf(*gross_size, oldbuf); + } + *gross_size = new_gross_size; + return newbuf; +} + +/* free buffer allocated with memAllocBuf() */ +void +memFreeBuf(size_t size, void *buf) +{ + mem_type type = memFindBufSizeType(size, NULL); + if (type != MEM_NONE) + memFree(buf, type); + else { + xfree(buf); + memMeterDec(HugeBufCountMeter); + memMeterDel(HugeBufVolumeMeter, size); + } +} + + void memInit(void) { @@ -240,7 +332,6 @@ memInit(void) memDataInit(MEM_HELPER_STATEFUL_REQUEST, "helper_stateful_request", sizeof(helper_stateful_request), 0); memDataInit(MEM_TLV, "storeSwapTLV", sizeof(tlv), 0); - memDataInit(MEM_CLIENT_REQ_BUF, "clientRequestBuffer", CLIENT_REQ_BUF_SZ, 0); memDataInit(MEM_SWAP_LOG_DATA, "storeSwapLogData", sizeof(storeSwapLogData), 0); /* init string pools */ @@ -284,7 +375,7 @@ memInUse(mem_type type) /* ick */ -void +static void memFree2K(void *p) { memFree(p, MEM_2K_BUF); @@ -302,20 +393,44 @@ memFree8K(void *p) memFree(p, MEM_8K_BUF); } -void +static void memFree16K(void *p) { memFree(p, MEM_16K_BUF); } -void +static void memFree32K(void *p) { memFree(p, MEM_32K_BUF); } -void +static void memFree64K(void *p) { memFree(p, MEM_64K_BUF); } + +FREE * +memFreeBufFunc(size_t size) +{ + switch(size) + { + case 2*1024: + return memFree2K; + case 4*1024: + return memFree4K; + case 8*1024: + return memFree8K; + case 16*1024: + return memFree16K; + case 32*1024: + return memFree32K; + case 64*1024: + return memFree64K; + default: + memMeterDec(HugeBufCountMeter); + memMeterDel(HugeBufVolumeMeter, size); + return xfree; + } +} diff --git a/src/protos.h b/src/protos.h index 737114c9ad..6ef763503e 100644 --- a/src/protos.h +++ b/src/protos.h @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.424 2002/02/13 17:22:36 hno Exp $ + * $Id: protos.h,v 1.425 2002/02/13 19:34:02 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -840,14 +840,14 @@ extern void memCleanModule(void); extern void memConfigure(void); extern void *memAllocate(mem_type); extern void *memAllocString(size_t net_size, size_t * gross_size); +extern void *memAllocBuf(size_t net_size, size_t * gross_size); +extern void *memReallocBuf(void *buf, size_t net_size, size_t * gross_size); extern void memFree(void *, int type); -extern void memFreeString(size_t size, void *); -extern void memFree2K(void *); extern void memFree4K(void *); extern void memFree8K(void *); -extern void memFree16K(void *); -extern void memFree32K(void *); -extern void memFree64K(void *); +extern void memFreeString(size_t size, void *); +extern void memFreeBuf(size_t size, void *); +extern FREE *memFreeBufFunc(size_t size); extern int memInUse(mem_type); extern size_t memTotalAllocated(void); extern void memDataInit(mem_type, const char *, size_t, int); diff --git a/src/structs.h b/src/structs.h index 0151ca9963..5885ddf021 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.408 2001/12/01 18:03:10 hno Exp $ + * $Id: structs.h,v 1.409 2002/02/13 19:34:02 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -814,7 +814,7 @@ struct _MemBuf { /* private, stay away; use interface function instead */ mb_size_t max_capacity; /* when grows: assert(new_capacity <= max_capacity) */ mb_size_t capacity; /* allocated space */ - FREE *freefunc; /* what to use to free the buffer, NULL after memBufFreeFunc() is called */ + unsigned stolen:1; /* the buffer has been stolen for use by someone else */ }; /* see Packer.c for description */