Hi,
Please find attached patch that adds an option
(APR_ALLOCATOR_USE_WIN32_HEAP) to use dedicated Windows heap for each
apr_allocator_t. Using dedicated heaps for APR allocator should reduce
memory fragmentation for mutli-thread application like Apache HTTPD on
Windows.
Log message:
[[[
* memory/unix/apr_pools
(apr_allocator_t): Add heap member if APR_ALLOCATOR_USE_WIN32_HEAP is defined.
(apr_allocator_create): Create Windows heap if
APR_ALLOCATOR_USE_WIN32_HEAP is defined.
(apr_allocator_destroy): Destroy dedicated heap if
APR_ALLOCATOR_USE_WIN32_HEAP is defined. All unfreed memory
will be destroyed automatically.
(allocator_alloc): Use HeapAlloc if APR_ALLOCATOR_USE_WIN32_HEAP is defined.
(apr_pool_create_unmanaged_ex): Use apr_allocator_create() to create
apr_allocator_t instance if
APR_ALLOCATOR_USE_WIN32_HEAP is defined
]]]
--
Ivan Zhakov
Index: memory/unix/apr_pools.c
===================================================================
--- memory/unix/apr_pools.c (revision 1145609)
+++ memory/unix/apr_pools.c (working copy)
@@ -111,6 +113,10 @@
* slot 19: size 81920
*/
apr_memnode_t *free[MAX_INDEX];
+
+#if APR_ALLOCATOR_USES_WIN32_HEAP
+ HANDLE heap;
+#endif
};
#define SIZEOF_ALLOCATOR_T APR_ALIGN_DEFAULT(sizeof(apr_allocator_t))
@@ -132,6 +138,14 @@
memset(new_allocator, 0, SIZEOF_ALLOCATOR_T);
new_allocator->max_free_index = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
+#if APR_ALLOCATOR_USES_WIN32_HEAP
+ new_allocator->heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
+ if (new_allocator->heap == NULL) {
+ free(new_allocator);
+ return APR_ENOMEM;
+ }
+#endif
+
*allocator = new_allocator;
return APR_SUCCESS;
@@ -139,6 +153,9 @@
APR_DECLARE(void) apr_allocator_destroy(apr_allocator_t *allocator)
{
+#if APR_ALLOCATOR_USES_WIN32_HEAP
+ HeapDestroy(allocator->heap);
+#else
apr_uint32_t index;
apr_memnode_t *node, **ref;
@@ -153,6 +170,7 @@
#endif
}
}
+#endif
free(allocator);
}
@@ -342,7 +360,9 @@
/* If we haven't got a suitable node, malloc a new one
* and initialize it.
*/
-#if APR_ALLOCATOR_USES_MMAP
+#if APR_ALLOCATOR_USES_WIN32_HEAP
+ if ((node = HeapAlloc(allocator->heap, 0, size)) == NULL)
+#elif APR_ALLOCATOR_USES_MMAP
if ((node = mmap(NULL, size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1, 0)) == MAP_FAILED)
#else
@@ -424,7 +444,9 @@
while (freelist != NULL) {
node = freelist;
freelist = node->next;
-#if APR_ALLOCATOR_USES_MMAP
+#if APR_ALLOCATOR_USES_WIN32_HEAP
+ HeapFree(allocator->heap, 0, node);
+#elif APR_ALLOCATOR_USES_MMAP
munmap(node, (node->index+1) << BOUNDARY_INDEX);
#else
free(node);
@@ -968,6 +990,7 @@
if (!apr_pools_initialized)
return APR_ENOPOOL;
if ((pool_allocator = allocator) == NULL) {
+#if !APR_ALLOCATOR_USES_WIN32_HEAP
if ((pool_allocator = malloc(SIZEOF_ALLOCATOR_T)) == NULL) {
if (abort_fn)
abort_fn(APR_ENOMEM);
@@ -976,6 +999,21 @@
}
memset(pool_allocator, 0, SIZEOF_ALLOCATOR_T);
pool_allocator->max_free_index = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
+#else
+ if (apr_allocator_create(&pool_allocator) != APR_SUCCESS) {
+ if (abort_fn)
+ abort_fn(APR_ENOMEM);
+
+ return APR_ENOMEM;
+ }
+ if ((node = allocator_alloc(pool_allocator,
+ MIN_ALLOC - APR_MEMNODE_T_SIZE)) == NULL) {
+ if (abort_fn)
+ abort_fn(APR_ENOMEM);
+
+ return APR_ENOMEM;
+ }
+#endif
}
if ((node = allocator_alloc(pool_allocator,
MIN_ALLOC - APR_MEMNODE_T_SIZE)) == NULL) {
Index: memory/unix/apr_pools.c
===================================================================
--- memory/unix/apr_pools.c (revision 1145597)
+++ memory/unix/apr_pools.c (working copy)
@@ -111,6 +113,10 @@
* slot 19: size 81920
*/
apr_memnode_t *free[MAX_INDEX];
+
+#if APR_ALLOCATOR_USES_WIN32_HEAP
+ HANDLE heap;
+#endif
};
#define SIZEOF_ALLOCATOR_T APR_ALIGN_DEFAULT(sizeof(apr_allocator_t))
@@ -132,6 +138,14 @@
memset(new_allocator, 0, SIZEOF_ALLOCATOR_T);
new_allocator->max_free_index = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
+#if APR_ALLOCATOR_USES_WIN32_HEAP
+ new_allocator->heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
+ if (new_allocator->heap == NULL) {
+ free(new_allocator);
+ return APR_ENOMEM;
+ }
+#endif
+
*allocator = new_allocator;
return APR_SUCCESS;
@@ -139,6 +153,9 @@
APR_DECLARE(void) apr_allocator_destroy(apr_allocator_t *allocator)
{
+#if APR_ALLOCATOR_USES_WIN32_HEAP
+ HeapDestroy(allocator->heap);
+#else
apr_uint32_t index;
apr_memnode_t *node, **ref;
@@ -153,6 +170,7 @@
#endif
}
}
+#endif
free(allocator);
}
@@ -342,7 +360,9 @@
/* If we haven't got a suitable node, malloc a new one
* and initialize it.
*/
-#if APR_ALLOCATOR_USES_MMAP
+#if APR_ALLOCATOR_USES_WIN32_HEAP
+ if ((node = HeapAlloc(allocator->heap, 0, size)) == NULL)
+#elif APR_ALLOCATOR_USES_MMAP
if ((node = mmap(NULL, size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1, 0)) == MAP_FAILED)
#else
@@ -424,7 +444,9 @@
while (freelist != NULL) {
node = freelist;
freelist = node->next;
-#if APR_ALLOCATOR_USES_MMAP
+#if APR_ALLOCATOR_USES_WIN32_HEAP
+ HeapFree(allocator->heap, 0, node);
+#elif APR_ALLOCATOR_USES_MMAP
munmap(node, (node->index+1) << BOUNDARY_INDEX);
#else
free(node);
@@ -959,7 +981,7 @@
if (!apr_pools_initialized)
return APR_ENOPOOL;
if ((pool_allocator = allocator) == NULL) {
-#if !APR_ALLOCATOR_USES_MMAP
+#if !APR_ALLOCATOR_USES_MMAP && !APR_ALLOCATOR_USES_WIN32_HEAP
if ((pool_allocator = malloc(MIN_ALLOC)) == NULL) {
if (abort_fn)
abort_fn(APR_ENOMEM);