[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 5/5] Lazily construct slab objects



From: Paul Durrant <pdurrant@xxxxxxxxxx>

To avoid a large overhead in both time and potemtially space when a new slab
is created, only construct objects as they are allocated. When they are freed
we keep them constructed to increase the chance of finding an already-
constructed object during subsequent allocations.

Signed-off-by: Paul Durrant <pdurrant@xxxxxxxxxx>
---
 src/xenbus/cache.c | 65 ++++++++++++++++++++++++++++++----------------
 1 file changed, 42 insertions(+), 23 deletions(-)

diff --git a/src/xenbus/cache.c b/src/xenbus/cache.c
index 681698743e9e..b1d3fe55320f 100644
--- a/src/xenbus/cache.c
+++ b/src/xenbus/cache.c
@@ -66,6 +66,7 @@ typedef struct _XENBUS_CACHE_SLAB {
     ULONG               Magic;
     PXENBUS_CACHE       Cache;
     LIST_ENTRY          ListEntry;
+    PXENBUS_CACHE_MASK  Constructed;
     PXENBUS_CACHE_MASK  Allocated;
     UCHAR               Buffer[1];
 } XENBUS_CACHE_SLAB, *PXENBUS_CACHE_SLAB;
@@ -394,7 +395,6 @@ CacheCreateSlab(
     PXENBUS_CACHE_SLAB  Slab;
     ULONG               NumberOfBytes;
     ULONG               Count;
-    LONG                Index;
     LONG                SlabCount;
     NTSTATUS            status;
 
@@ -422,17 +422,13 @@ CacheCreateSlab(
     Slab->Magic = XENBUS_CACHE_SLAB_MAGIC;
     Slab->Cache = Cache;
 
-    Slab->Allocated = CacheMaskCreate(Count);
-    if (Slab->Allocated == NULL)
+    Slab->Constructed = CacheMaskCreate(Count);
+    if (Slab->Constructed == NULL)
         goto fail3;
 
-    for (Index = 0; Index < (LONG)CacheMaskSize(Slab->Allocated); Index++) {
-        PVOID Object = (PVOID)&Slab->Buffer[Index * Cache->Size];
-
-        status = __CacheCtor(Cache, Object);
-        if (!NT_SUCCESS(status))
-            goto fail4;
-    }
+    Slab->Allocated = CacheMaskCreate(Count);
+    if (Slab->Allocated == NULL)
+        goto fail4;
 
     CacheInsertSlab(Cache, Slab);
     Cache->Count += Count;
@@ -446,13 +442,7 @@ CacheCreateSlab(
 fail4:
     Error("fail4\n");
 
-    while (--Index >= 0) {
-        PVOID Object = (PVOID)&Slab->Buffer[Index * Cache->Size];
-
-        __CacheDtor(Cache, Object);
-    }
-
-    CacheMaskDestroy(Slab->Allocated);
+    CacheMaskDestroy(Slab->Constructed);
 
 fail3:
     Error("fail3\n");
@@ -496,13 +486,17 @@ CacheDestroySlab(
     while (--Index >= 0) {
         PVOID Object = (PVOID)&Slab->Buffer[Index * Cache->Size];
 
-        __CacheDtor(Cache, Object);
+        if (__CacheMaskTest(Slab->Constructed, Index)) {
+            __CacheDtor(Cache, Object);
+            __CacheMaskClear(Slab->Constructed, Index);
+        }
     }
 
     ASSERT(Cache->CurrentSlabs != 0);
     InterlockedDecrement(&Cache->CurrentSlabs);
 
     CacheMaskDestroy(Slab->Allocated);
+    CacheMaskDestroy(Slab->Constructed);
     __CacheFree(Slab);
 }
 
@@ -515,29 +509,54 @@ CacheGetObjectFromSlab(
     PXENBUS_CACHE           Cache;
     ULONG                   Index;
     PVOID                   Object;
+    NTSTATUS                status;
 
     Cache = Slab->Cache;
 
     ASSERT(CacheMaskCount(Slab->Allocated) <= CacheMaskSize(Slab->Allocated));
+
+    status = STATUS_NO_MEMORY;
     if (CacheMaskCount(Slab->Allocated) == CacheMaskSize(Slab->Allocated))
-           return NULL;
+           goto fail1;
+
+    //
+    // If there are unallocated but constructed objects then look for one of 
those,
+    // otherwise look for a free unconstructed object. (NOTE: The 
'Constructed' mask
+    // should always be contiguous).
+    //
+    Index = (CacheMaskCount(Slab->Allocated) < 
CacheMaskCount(Slab->Constructed)) ?
+        0 : CacheMaskCount(Slab->Constructed);
 
-    Index = 0;
     while (Index < CacheMaskSize(Slab->Allocated)) {
         if (!__CacheMaskTest(Slab->Allocated, Index))
             break;
 
         Index++;
     }
-    BUG_ON(Index >= CacheMaskSize(Slab->Allocated));
-
-    __CacheMaskSet(Slab->Allocated, Index);
 
     Object = (PVOID)&Slab->Buffer[Index * Cache->Size];
     ASSERT3U(Index, ==, (ULONG)((PUCHAR)Object - &Slab->Buffer[0]) /
              Cache->Size);
 
+    if (!__CacheMaskTest(Slab->Constructed, Index)) {
+        status = __CacheCtor(Cache, Object);
+        if (!NT_SUCCESS(status))
+            goto fail2;
+
+        __CacheMaskSet(Slab->Constructed, Index);
+    }
+
+    __CacheMaskSet(Slab->Allocated, Index);
+
     return Object;
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return NULL;
 }
 
 // Must be called with lock held
-- 
2.25.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.