More efficient replacement for GetMemoryChunkSpace().
authorRobert Haas <rhaas@postgresql.org>
Mon, 5 May 2014 16:08:06 +0000 (16:08 +0000)
committerRobert Haas <rhaas@postgresql.org>
Mon, 5 May 2014 16:08:06 +0000 (16:08 +0000)
When the allocation size is known, we can can compute the result
directly from that, rather than working it out from the pointer itself.

src/backend/utils/mmgr/sb_alloc.c
src/backend/utils/sort/tuplesort.c
src/include/utils/sb_alloc.h

index 528ee2da92705d44c1c75e1609c86d7e16e1e6a4..ace9e56923ca00aa955c2cca172235589f39dcf0 100644 (file)
@@ -235,7 +235,7 @@ sb_alloc(sb_allocator *a, Size size, int flags)
        }
 
        /* Map allocation to a size class. */
-       if (size <= lengthof(sb_size_class_map) * SB_SIZE_CLASS_MAP_QUANTUM)
+       if (size < lengthof(sb_size_class_map) * SB_SIZE_CLASS_MAP_QUANTUM)
        {
                int     mapidx;
 
@@ -391,6 +391,48 @@ sb_free(void *ptr)
                LWLockRelease(lock);
 }
 
+/*
+ * Return the size of the chunk that will be used to satisfy a given
+ * allocation.
+ */
+Size
+sb_alloc_space(Size size)
+{
+       uint16  size_class;
+
+       /* Large objects allocate full pages. */
+       if (size > sb_size_classes[lengthof(sb_size_classes) - 1])
+               return FPM_PAGE_SIZE * fpm_size_to_pages(size);
+
+       /* Map request size to a size class. */
+       if (size < lengthof(sb_size_class_map) * SB_SIZE_CLASS_MAP_QUANTUM)
+       {
+               int     mapidx;
+
+               mapidx = ((size + SB_SIZE_CLASS_MAP_QUANTUM - 1) /
+                                       SB_SIZE_CLASS_MAP_QUANTUM) - 1;
+               size_class = sb_size_class_map[mapidx];
+       }
+       else
+       {
+               uint16  min = sb_size_class_map[lengthof(sb_size_class_map) - 1];
+               uint16  max = lengthof(sb_size_classes) - 1;
+               while (min < max)
+               {
+                       uint16  mid = (min + max) / 2;
+                       uint16  class_size = sb_size_classes[mid];
+
+                       if (class_size < size)
+                               min = mid + 1;
+                       else
+                               max = mid;
+               }
+               size_class = min;
+       }
+
+       return sb_size_classes[size_class];
+}
+
 /*
  * Return the size of the chunk used to satisfy a given allocation.
  *
index 39d6552737856da1cf65e08601a90a702a85547a..993eef65cd9eb1f0890840ae09d1c0a79fa26e1d 100644 (file)
@@ -3352,7 +3352,7 @@ copytup_index(Tuplesortstate *state, SortTuple *stup, void *tup)
        /* copy the tuple into sort storage */
        newtuple = (IndexTuple) sb_alloc(state->sortallocator, tuplen, 0);
        memcpy(newtuple, tuple, tuplen);
-       USEMEM(state, sb_chunk_space(newtuple));
+       USEMEM(state, sb_alloc_space(tuplen));
        stup->tuple = (void *) newtuple;
        /* set up first-column key value */
        stup->datum1 = index_getattr(newtuple,
index 32d704acd0297b69279079e58a690224c30a0ffe..50ef5c3703c0190a1efb56768d36078d37158917 100644 (file)
@@ -63,12 +63,17 @@ typedef struct sb_allocator
 #define SB_ALLOC_HUGE                          0x0001          /* allow >=1GB */
 #define SB_ALLOC_SOFT_FAIL                     0x0002          /* return NULL if no mem */
 
-/* Exported functions. */
+/* Functions to manipulate allocators. */
 extern sb_allocator *sb_create_private_allocator(void);
+extern void sb_reset_allocator(sb_allocator *a);
+extern void sb_destroy_private_allocator(sb_allocator *);
+
+/* Functions to allocate and free memory. */
 extern void *sb_alloc(sb_allocator *, Size, int flags);
 extern void sb_free(void *ptr);
+
+/* Reporting functions. */
+extern Size sb_alloc_space(Size size);
 extern Size sb_chunk_space(void *ptr);
-extern void sb_reset_allocator(sb_allocator *a);
-extern void sb_destroy_private_allocator(sb_allocator *);
 
 #endif         /* SB_ALLOC_H */