sb_chunk_space
authorRobert Haas <rhaas@postgresql.org>
Mon, 5 May 2014 13:48:06 +0000 (09:48 -0400)
committerRobert Haas <rhaas@postgresql.org>
Mon, 5 May 2014 13:48:06 +0000 (09:48 -0400)
src/backend/utils/mmgr/sb_alloc.c
src/include/utils/sb_alloc.h

index fc2e43d18d854e2eac1dcfb6bc31ed68c2b1222b..b306fc37319d70f7827fa1a415ee546cc800692c 100644 (file)
@@ -25,8 +25,8 @@
  * span itself.  Ordinary superblocks are all of size SB_SUPERBLOCK_SIZE,
  * and size_class indicates the size of object they contain.  Large memory
  * spans contain just enough pages to store the object, and size_class
- * is SB_SPAN_LARGE; ninitialized, nused, and firstfree are all unused, as
- * the whole span consists of a single object.
+ * is SB_SCLASS_SPAN_LARGE; ninitialized, nused, and firstfree are all unused,
+ * as the whole span consists of a single object.
  * 
  * For a "span of spans", the span object is stored "inline".  The allocation
  * is always exactly one page, and the sb_span object is located at the
@@ -306,6 +306,8 @@ sb_free(void *ptr)
                        LWLockAcquire(lock, LW_EXCLUSIVE);
        }
 
+       /* XXX. What about large objects? */
+
        /* Compute the object size. */
        size_class = span->size_class;
        obsize = sb_size_classes[size_class];
@@ -365,6 +367,45 @@ sb_free(void *ptr)
                LWLockRelease(lock);
 }
 
+/*
+ * Return the size of the chunk used to satisfy a given allocation.
+ *
+ * This is roughly an analogue of GetMemoryChunkSpace, but it's hard to make
+ * a precisely fair comparison.  Unlike MemoryContextAlloc/AllocSetAlloc,
+ * there's no bookkeeping overhead associated with any single allocation;
+ * the only thing we can really reflect here is the fact that allocations
+ * will be rounded up to the next larger size class (or, for large allocations,
+ * to a full FPM page).  The storage overhead of the sb_span, sb_map,
+ * sb_region, and FreePageManager structures is typically spread across
+ * enough small allocations to make reflecting those costs here difficult.
+ *
+ * On the other hand, we also hope that the overhead in question is small
+ * enough not to matter.  The system malloc is not without bookkeeping
+ * overhead of its own.
+ */
+Size
+sb_chunk_space(void *ptr)
+{
+       sb_region *region;
+       char   *fpm_base;
+       sb_span *span;
+       Size    pageno;
+       uint16  size_class;
+
+       /* Locate the containing superblock. */
+       region = sb_lookup_region(ptr);
+       fpm_base = fpm_segment_base(region->fpm);
+       pageno = fpm_pointer_to_page(fpm_base, ptr);
+       span = sb_map_get(region->pagemap, pageno);
+
+       /* Work out the size of the allocation. */      
+       size_class = span->size_class;
+       if (span->size_class == SB_SCLASS_SPAN_LARGE)
+               return FPM_PAGE_SIZE * span->npages;
+       else
+               return sb_size_classes[size_class];
+}
+
 /*
  * Free all memory used by an allocator.
  *
index cf303451361f6daf2ca5f768e7a4238c4b0acf63..32d704acd0297b69279079e58a690224c30a0ffe 100644 (file)
@@ -67,6 +67,7 @@ typedef struct sb_allocator
 extern sb_allocator *sb_create_private_allocator(void);
 extern void *sb_alloc(sb_allocator *, Size, int flags);
 extern void sb_free(void *ptr);
+extern Size sb_chunk_space(void *ptr);
 extern void sb_reset_allocator(sb_allocator *a);
 extern void sb_destroy_private_allocator(sb_allocator *);