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);

Reply via email to