[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r10006: Keep a freelist of unused 4k buffer chunks, rather than wast (in tor/trunk: . src/common src/or)
- To: or-cvs@xxxxxxxxxxxxx
- Subject: [or-cvs] r10006: Keep a freelist of unused 4k buffer chunks, rather than wast (in tor/trunk: . src/common src/or)
- From: nickm@xxxxxxxx
- Date: Mon, 23 Apr 2007 10:42:31 -0400 (EDT)
- Delivered-to: archiver@seul.org
- Delivered-to: or-cvs-outgoing@seul.org
- Delivered-to: or-cvs@seul.org
- Delivery-date: Mon, 23 Apr 2007 10:42:40 -0400
- Reply-to: or-talk@xxxxxxxxxxxxx
- Sender: owner-or-cvs@xxxxxxxxxxxxx
Author: nickm
Date: 2007-04-23 10:42:27 -0400 (Mon, 23 Apr 2007)
New Revision: 10006
Modified:
tor/trunk/
tor/trunk/ChangeLog
tor/trunk/src/common/mempool.c
tor/trunk/src/or/buffers.c
Log:
r12499@catbus: nickm | 2007-04-23 10:42:23 -0400
Keep a freelist of unused 4k buffer chunks, rather than wasting 8k for every inactive connection_t.
Property changes on: tor/trunk
___________________________________________________________________
svk:merge ticket from /tor/trunk [r12499] on 8246c3cf-6607-4228-993b-4d95d33730f1
Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog 2007-04-23 04:10:52 UTC (rev 10005)
+++ tor/trunk/ChangeLog 2007-04-23 14:42:27 UTC (rev 10006)
@@ -26,6 +26,8 @@
internally and transfer the data in-process. This saves two
sockets per anonymous directory connection (at the client and at
the server), and avoids the nasty Windows socketpair() workaround.
+ - Keep unused 4k buffers on a free list, rather than wasting 8k for every
+ single inactive connection_t.
o Minor features (build):
- Make autoconf search for libevent, openssl, and zlib consistently.
Modified: tor/trunk/src/common/mempool.c
===================================================================
--- tor/trunk/src/common/mempool.c 2007-04-23 04:10:52 UTC (rev 10005)
+++ tor/trunk/src/common/mempool.c 2007-04-23 14:42:27 UTC (rev 10006)
@@ -377,7 +377,7 @@
}
/** If there are more than <b>n</b> empty chunks in <b>pool</b>, free the
- * exces ones that have been empty for the longest. (If <b>n</b> is less
+ * excess ones that have been empty for the longest. (If <b>n</b> is less
* than zero, free only empty chunks that were not used since the last
* call to mp_pool_clean(), leaving only -<b>n</b>.) */
void
Modified: tor/trunk/src/or/buffers.c
===================================================================
--- tor/trunk/src/or/buffers.c 2007-04-23 04:10:52 UTC (rev 10005)
+++ tor/trunk/src/or/buffers.c 2007-04-23 14:42:27 UTC (rev 10006)
@@ -158,6 +158,57 @@
}
}
+/** DOCDOC */
+static char *free_mem_list = NULL;
+static int free_mem_list_len = 0;
+/*XXXX020 Actually remove stuff from freelist when it gets too big */
+
+/** DOCDOC */
+static void
+add_buf_mem_to_freelist(buf_t *buf)
+{
+ char *mem;
+
+ tor_assert(buf->len == MIN_LAZY_SHRINK_SIZE);
+ tor_assert(buf->datalen == 0);
+ tor_assert(buf->mem);
+
+ mem = RAW_MEM(buf->mem);
+ buf->len = buf->memsize = 0;
+ buf->mem = buf->cur = NULL;
+
+ *(char**)mem = free_mem_list;
+ free_mem_list = mem;
+ ++free_mem_list_len;
+ log_info(LD_GENERAL, "Add buf mem to freelist. Freelist has %d entries.",
+ free_mem_list_len);
+}
+
+/** DOCDOC */
+static void
+buf_get_initial_mem(buf_t *buf)
+{
+ char *mem;
+ tor_assert(!buf->mem);
+
+ if (free_mem_list) {
+ mem = free_mem_list;
+ free_mem_list = *(char**)mem;
+ --free_mem_list_len;
+ log_info(LD_GENERAL, "Got buf mem from freelist. Freelist has %d entries.",
+ free_mem_list_len);
+ } else {
+ log_info(LD_GENERAL, "Freelist empty; allocating another chunk.");
+ tor_assert(free_mem_list_len == 0);
+ mem = tor_malloc(ALLOC_LEN(MIN_LAZY_SHRINK_SIZE));
+ }
+ buf->mem = GUARDED_MEM(mem);
+ SET_GUARDS(buf->mem, MIN_LAZY_SHRINK_SIZE);
+ buf->len = MIN_LAZY_SHRINK_SIZE;
+ buf->memsize = ALLOC_LEN(MIN_LAZY_SHRINK_SIZE);
+ buf->cur = buf->mem;
+}
+
/** Change a buffer's capacity. <b>new_capacity</b> must be \>=
* buf->datalen. */
static void
@@ -205,6 +256,7 @@
}
}
+#if 0
/* XXX Some play code to throw away old buffers sometimes rather
* than constantly reallocing them; just in case this is our memory
* problem. It looks for now like it isn't, so disabled. -RD */
@@ -217,9 +269,23 @@
oldmem = RAW_MEM(buf->mem);
tor_free(oldmem);
buf->mem = buf->cur = newmem;
+ } else { /* ... */ }
+#endif
+
+ if (buf->len == 0 && new_capacity <= MIN_LAZY_SHRINK_SIZE) {
+ new_capacity = MIN_LAZY_SHRINK_SIZE;
+ tor_assert(!buf->mem);
+ buf_get_initial_mem(buf);
} else {
- buf->mem = GUARDED_MEM(tor_realloc(RAW_MEM(buf->mem),
- ALLOC_LEN(new_capacity)));
+ char *raw;
+ if (buf->mem)
+ raw = tor_realloc(RAW_MEM(buf->mem), ALLOC_LEN(new_capacity));
+ else {
+ log_info(LD_GENERAL, "Jumping straight from 0 bytes to %d",
+ (int)new_capacity);
+ raw = tor_malloc(ALLOC_LEN(new_capacity));
+ }
+ buf->mem = GUARDED_MEM(raw);
SET_GUARDS(buf->mem, new_capacity);
buf->cur = buf->mem+offset;
}
@@ -239,7 +305,8 @@
(size_t)(buf->len-offset));
buf->cur += new_capacity-buf->len;
}
- buf->memsize = buf->len = new_capacity;
+ buf->len = new_capacity;
+ buf->memsize = ALLOC_LEN(buf->len);
#ifdef CHECK_AFTER_RESIZE
assert_buf_ok(buf);
@@ -292,6 +359,11 @@
size_t new_len;
new_len = buf->len;
+ if (buf->datalen == 0 && buf->highwater == 0 &&
+ buf->len == MIN_LAZY_SHRINK_SIZE) {
+ add_buf_mem_to_freelist(buf);
+ return;
+ }
while (buf->highwater < (new_len>>2) && new_len > MIN_LAZY_SHRINK_SIZE*2)
new_len >>= 1;
@@ -328,16 +400,22 @@
return 0;
}
-/** Create and return a new buf with capacity <b>size</b>. */
+/** Create and return a new buf with capacity <b>size</b>.
+ * (Used for testing). */
buf_t *
buf_new_with_capacity(size_t size)
{
buf_t *buf;
buf = tor_malloc_zero(sizeof(buf_t));
buf->magic = BUFFER_MAGIC;
- buf->cur = buf->mem = GUARDED_MEM(tor_malloc(ALLOC_LEN(size)));
- SET_GUARDS(buf->mem, size);
- buf->len = buf->memsize = size;
+ if (size == MIN_LAZY_SHRINK_SIZE) {
+ buf_get_initial_mem(buf);
+ } else {
+ buf->cur = buf->mem = GUARDED_MEM(tor_malloc(ALLOC_LEN(size)));
+ SET_GUARDS(buf->mem, size);
+ buf->len = size;
+ buf->memsize = ALLOC_LEN(size);
+ }
assert_buf_ok(buf);
return buf;
@@ -356,7 +434,7 @@
{
buf->datalen = 0;
buf->cur = buf->mem;
- buf->len = buf->memsize;
+ /* buf->len = buf->memsize; bad. */
}
/** Return the number of bytes stored in <b>buf</b> */
@@ -389,8 +467,12 @@
char *oldmem;
assert_buf_ok(buf);
buf->magic = 0xDEADBEEF;
- oldmem = RAW_MEM(buf->mem);
- tor_free(oldmem);
+ if (buf->len == MIN_LAZY_SHRINK_SIZE) {
+ add_buf_mem_to_freelist(buf);
+ } else {
+ oldmem = RAW_MEM(buf->mem);
+ tor_free(oldmem);
+ }
tor_free(buf);
}
@@ -1405,14 +1487,24 @@
{
tor_assert(buf);
tor_assert(buf->magic == BUFFER_MAGIC);
- tor_assert(buf->mem);
tor_assert(buf->highwater <= buf->len);
tor_assert(buf->datalen <= buf->highwater);
+
+ if (buf->mem) {
+ tor_assert(buf->cur >= buf->mem);
+ tor_assert(buf->cur < buf->mem+buf->len);
+ tor_assert(buf->memsize == ALLOC_LEN(buf->len));
+ } else {
+ tor_assert(!buf->cur);
+ tor_assert(!buf->len);
+ tor_assert(!buf->memsize);
+ }
+
#ifdef SENTINELS
- {
+ if (buf->mem) {
uint32_t u32 = get_uint32(buf->mem - 4);
tor_assert(u32 == START_MAGIC);
- u32 = get_uint32(buf->mem + buf->memsize);
+ u32 = get_uint32(buf->mem + buf->memsize - 8);
tor_assert(u32 == END_MAGIC);
}
#endif