|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |