Here's a heavier-weight but pool-free and potentially faster alternative
to Brian's proposal for your benchmarking enjoyment.... :)
--------------------------------------------------------------
Cliff Woolley
[EMAIL PROTECTED]
Charlottesville, VA
? config.nice-prefork
? config.nice-worker
Index: include/http_core.h
===================================================================
RCS file: /home/cvs/httpd-2.0/include/http_core.h,v
retrieving revision 1.64
diff -u -d -r1.64 http_core.h
--- include/http_core.h 20 Mar 2002 02:05:42 -0000 1.64
+++ include/http_core.h 31 Mar 2002 17:47:36 -0000
@@ -129,9 +129,9 @@
#define SATISFY_ANY 1
#define SATISFY_NOSPEC 2
-/* Make sure we don't write less than 8192 bytes at any one time.
+/* Make sure we don't write less than 8000 bytes at any one time.
*/
-#define AP_MIN_BYTES_TO_WRITE 8192
+#define AP_MIN_BYTES_TO_WRITE 8000
/**
* Retrieve the value of Options for this request
Index: srclib/apr/include/apr_allocator.h
===================================================================
RCS file: /home/cvs/apr/include/apr_allocator.h,v
retrieving revision 1.2
diff -u -d -r1.2 apr_allocator.h
--- srclib/apr/include/apr_allocator.h 18 Mar 2002 16:24:54 -0000 1.2
+++ srclib/apr/include/apr_allocator.h 31 Mar 2002 17:47:37 -0000
@@ -85,6 +85,15 @@
/** the structure which holds information about the allocation */
typedef struct apr_memnode_t apr_memnode_t;
+struct apr_memnode_t {
+ apr_memnode_t *next;
+ apr_uint32_t index;
+ char *first_avail;
+ char *endp;
+};
+
+#define APR_MEMNODE_T_SIZE APR_ALIGN_DEFAULT(sizeof(apr_memnode_t))
+
/**
* Create a new allocator
* @param allocator The allocator we have just created.
Index: srclib/apr/memory/unix/apr_pools.c
===================================================================
RCS file: /home/cvs/apr/memory/unix/apr_pools.c,v
retrieving revision 1.164
diff -u -d -r1.164 apr_pools.c
--- srclib/apr/memory/unix/apr_pools.c 31 Mar 2002 10:12:21 -0000 1.164
+++ srclib/apr/memory/unix/apr_pools.c 31 Mar 2002 17:47:37 -0000
@@ -77,19 +77,6 @@
/*
- * XXX: Memory node struct, move to private header file
- */
-struct apr_memnode_t {
- apr_memnode_t *next;
- apr_uint32_t index;
- char *first_avail;
- char *endp;
-};
-
-#define SIZEOF_MEMNODE_T APR_ALIGN_DEFAULT(sizeof(apr_memnode_t))
-
-
-/*
* Magic numbers
*/
@@ -189,7 +176,7 @@
/* Round up the block size to the next boundary, but always
* allocate at least a certain size (MIN_ALLOC).
*/
- size = APR_ALIGN(size + SIZEOF_MEMNODE_T, BOUNDARY_SIZE);
+ size = APR_ALIGN(size + APR_MEMNODE_T_SIZE, BOUNDARY_SIZE);
if (size < MIN_ALLOC)
size = MIN_ALLOC;
@@ -247,7 +234,7 @@
#endif /* APR_HAS_THREADS */
node->next = NULL;
- node->first_avail = (char *)node + SIZEOF_MEMNODE_T;
+ node->first_avail = (char *)node + APR_MEMNODE_T_SIZE;
return node;
}
@@ -283,7 +270,7 @@
#endif /* APR_HAS_THREADS */
node->next = NULL;
- node->first_avail = (char *)node + SIZEOF_MEMNODE_T;
+ node->first_avail = (char *)node + APR_MEMNODE_T_SIZE;
return node;
}
@@ -302,7 +289,7 @@
node->next = NULL;
node->index = index;
- node->first_avail = (char *)node + SIZEOF_MEMNODE_T;
+ node->first_avail = (char *)node + APR_MEMNODE_T_SIZE;
node->endp = (char *)node + size;
return node;
@@ -721,7 +708,7 @@
allocator = parent->allocator;
if ((node = apr_allocator_alloc(allocator,
- MIN_ALLOC - SIZEOF_MEMNODE_T)) == NULL) {
+ MIN_ALLOC - APR_MEMNODE_T_SIZE)) == NULL) {
if (abort_fn)
abort_fn(APR_ENOMEM);
Index: srclib/apr-util/buckets/apr_buckets_alloc.c
===================================================================
RCS file: /home/cvs/apr-util/buckets/apr_buckets_alloc.c,v
retrieving revision 1.4
diff -u -d -r1.4 apr_buckets_alloc.c
--- srclib/apr-util/buckets/apr_buckets_alloc.c 30 Mar 2002 12:43:07 -0000
1.4
+++ srclib/apr-util/buckets/apr_buckets_alloc.c 31 Mar 2002 17:47:37 -0000
@@ -52,32 +52,98 @@
* <http://www.apache.org/>.
*/
-#include <stdlib.h>
#include "apr_buckets.h"
+#include "apr_allocator.h"
-/*
- * XXX: this file will be filled in later
- */
+#define ALLOC_AMT (8192 - APR_MEMNODE_T_SIZE)
+typedef struct node_header_t {
+ apr_size_t size;
+ apr_bucket_alloc_t *alloc;
+ apr_memnode_t *memnode;
+ struct node_header_t *next;
+} node_header_t;
+
+#define SIZEOF_NODE_HEADER_T APR_ALIGN_DEFAULT(sizeof(node_header_t))
+
+/** A list of free memory from which new buckets or private bucket
+ * structures can be allocated.
+ */
struct apr_bucket_alloc_t {
- int x; /* temporary... some compilers trigger an error on empty structure
defs */
+ apr_allocator_t *allocator;
+ node_header_t *freelist;
+ apr_memnode_t *blocks;
};
APU_DECLARE(apr_bucket_alloc_t *) apr_bucket_alloc_create(apr_pool_t *p)
{
- return (apr_bucket_alloc_t *)0xFECCFECC;
+ apr_allocator_t *allocator;
+ apr_bucket_alloc_t *list;
+ apr_memnode_t *block;
+
+ apr_allocator_create(&allocator);
+ block = apr_allocator_alloc(allocator, ALLOC_AMT);
+ list = (apr_bucket_alloc_t *)block->first_avail;
+ list->allocator = allocator;
+ list->freelist = NULL;
+ list->blocks = block;
+ block->first_avail += APR_ALIGN_DEFAULT(sizeof(*list));
+ return list;
}
APU_DECLARE(void) apr_bucket_alloc_destroy(apr_bucket_alloc_t *list)
{
+ apr_allocator_free(list->allocator, list->blocks);
+ apr_allocator_destroy(list->allocator);
}
APU_DECLARE(void *) apr_bucket_alloc(apr_size_t size, apr_bucket_alloc_t *list)
{
- return malloc(size);
+ node_header_t *node;
+ apr_memnode_t *active = list->blocks;
+ char *endp;
+
+ size += SIZEOF_NODE_HEADER_T;
+ if (size <= APR_BUCKET_ALLOC_SIZE) {
+ if (list->freelist) {
+ node = list->freelist;
+ list->freelist = node->next;
+ }
+ else {
+ endp = active->first_avail + APR_BUCKET_ALLOC_SIZE;
+ if (endp >= active->endp) {
+ list->blocks = apr_allocator_alloc(list->allocator, ALLOC_AMT);
+ list->blocks->next = active;
+ active = list->blocks;
+ endp = active->first_avail + APR_BUCKET_ALLOC_SIZE;
+ }
+ node = (node_header_t *)active->first_avail;
+ node->alloc = list;
+ node->memnode = active;
+ node->size = APR_BUCKET_ALLOC_SIZE;
+ active->first_avail = endp;
+ }
+ }
+ else {
+ apr_memnode_t *memnode = apr_allocator_alloc(list->allocator, size);
+ node = (node_header_t *)memnode->first_avail;
+ node->alloc = list;
+ node->memnode = memnode;
+ node->size = size;
+ }
+ return ((char *)node) + SIZEOF_NODE_HEADER_T;
}
-APU_DECLARE(void) apr_bucket_free(void *block)
+APU_DECLARE(void) apr_bucket_free(void *mem)
{
- free(block);
+ node_header_t *node = (node_header_t *)((char *)mem -
SIZEOF_NODE_HEADER_T);
+ apr_bucket_alloc_t *list = node->alloc;
+
+ if (node->size == APR_BUCKET_ALLOC_SIZE) {
+ node->next = list->freelist;
+ list->freelist = node;
+ }
+ else {
+ apr_allocator_free(list->allocator, node->memnode);
+ }
}
Index: srclib/apr-util/include/apr_buckets.h
===================================================================
RCS file: /home/cvs/apr-util/include/apr_buckets.h,v
retrieving revision 1.133
diff -u -d -r1.133 apr_buckets.h
--- srclib/apr-util/include/apr_buckets.h 29 Mar 2002 08:12:08 -0000
1.133
+++ srclib/apr-util/include/apr_buckets.h 31 Mar 2002 17:47:37 -0000
@@ -84,8 +84,8 @@
* @{
*/
-/** default bucket buffer size */
-#define APR_BUCKET_BUFF_SIZE 8192
+/** default bucket buffer size - 8KB minus room for memory allocator headers */
+#define APR_BUCKET_BUFF_SIZE 8000
typedef enum {
APR_BLOCK_READ, /* block until data becomes available */
@@ -613,6 +613,28 @@
* be created while reading from this file bucket */
apr_pool_t *readpool;
};
+
+typedef union apr_bucket_structs apr_bucket_structs;
+/**
+ * A union of all bucket structures so we know what
+ * the max size is.
+ */
+union apr_bucket_structs {
+ apr_bucket b;
+ apr_bucket_heap heap;
+ apr_bucket_pool pool;
+#if APR_HAS_MMAP
+ apr_bucket_mmap mmap;
+#endif
+ apr_bucket_file file;
+};
+
+/**
+ * The amount that apr_bucket_alloc() should allocate in the common case.
+ * Note: this is twice as big as apr_bucket_structs to allow breathing
+ * room for third-party bucket types and the bucket allocator.
+ */
+#define APR_BUCKET_ALLOC_SIZE APR_ALIGN_DEFAULT(2*sizeof(apr_bucket_structs))
/* ***** Bucket Brigade Functions ***** */
/**