Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6456)

Unified Diff: Source/wtf/PartitionAllocTest.cpp

Issue 26196002: Improve partitionAlloc's resistance to fragmentation. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/wtf/PartitionAlloc.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/wtf/PartitionAllocTest.cpp
diff --git a/Source/wtf/PartitionAllocTest.cpp b/Source/wtf/PartitionAllocTest.cpp
index 80a1fd137247018f2909b76806606b62a6622e91..f7f9f55b11568663ab272aa287d3db7a0633b2e2 100644
--- a/Source/wtf/PartitionAllocTest.cpp
+++ b/Source/wtf/PartitionAllocTest.cpp
@@ -218,20 +218,30 @@ TEST(WTF_PartitionAlloc, PageTransitions)
WTF::PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx];
WTF::PartitionPageHeader* page1 = GetFullPage(kTestAllocSize);
+ EXPECT_EQ(page1, bucket->currPage);
+ EXPECT_EQ(page1, page1->next);
+ EXPECT_EQ(page1, page1->prev);
WTF::PartitionPageHeader* page2 = GetFullPage(kTestAllocSize);
EXPECT_EQ(page2, bucket->currPage);
- EXPECT_EQ(page1, page2->next);
- EXPECT_EQ(page1, page2->prev);
+ EXPECT_EQ(page2, page2->next);
+ EXPECT_EQ(page2, page2->prev);
+
+ // Bounce page1 back into the non-full list then fill it up again.
+ char* ptr = reinterpret_cast<char*>(page1) + sizeof(WTF::PartitionPageHeader);
+ partitionFree(ptr);
+ (void) partitionAlloc(allocator.root(), kTestAllocSize);
+ EXPECT_EQ(page1, bucket->currPage);
+
// Allocating another page at this point should cause us to scan over page1
// (which is both full and NOT our current page), and evict it from the
// freelist. Older code had a O(n^2) condition due to failure to do this.
WTF::PartitionPageHeader* page3 = GetFullPage(kTestAllocSize);
EXPECT_EQ(page3, bucket->currPage);
- EXPECT_EQ(page2, page3->next);
- EXPECT_EQ(page3, page2->next);
+ EXPECT_EQ(page3, page3->next);
+ EXPECT_EQ(page3, page3->next);
// Work out a pointer into page2 and free it.
- char* ptr = reinterpret_cast<char*>(page2) + sizeof(WTF::PartitionPageHeader);
+ ptr = reinterpret_cast<char*>(page2) + sizeof(WTF::PartitionPageHeader);
partitionFree(ptr);
// Trying to allocate at this time should cause us to cycle around to page2
// and find the recently freed slot.
@@ -469,10 +479,16 @@ TEST(WTF_PartitionAlloc, PartialPageFreelists)
WTF::PartitionPageHeader* page2 = reinterpret_cast<WTF::PartitionPageHeader*>(reinterpret_cast<size_t>(ptr4) & WTF::kPartitionPageBaseMask);
EXPECT_EQ(1, page2->numAllocatedSlots);
+ // Churn things a little whilst there's a partial page freelist.
+ partitionFree(ptr);
+ ptr = partitionAlloc(allocator.root(), bigSize);
+ void* ptr5 = partitionAlloc(allocator.root(), bigSize);
+
partitionFree(ptr);
partitionFree(ptr2);
partitionFree(ptr3);
partitionFree(ptr4);
+ partitionFree(ptr5);
EXPECT_TRUE(bucket->freePages);
EXPECT_EQ(page, bucket->freePages->page);
EXPECT_TRUE(page2->freelistHead);
@@ -529,6 +545,42 @@ TEST(WTF_PartitionAlloc, PartialPageFreelists)
TestShutdown();
}
+// Test some of the fragmentation-resistant properties of the allocator.
+TEST(WTF_PartitionAlloc, PageRefilling)
+{
+ TestSetup();
+ size_t bucketIdx = kTestAllocSize >> WTF::kBucketShift;
+ WTF::PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx];
+
+ // Grab two full pages and a non-full page.
+ WTF::PartitionPageHeader* page1 = GetFullPage(kTestAllocSize);
+ WTF::PartitionPageHeader* page2 = GetFullPage(kTestAllocSize);
+ void* ptr = partitionAlloc(allocator.root(), kTestAllocSize);
+ EXPECT_TRUE(ptr);
+ EXPECT_NE(page1, bucket->currPage);
+ EXPECT_NE(page2, bucket->currPage);
+ WTF::PartitionPageHeader* page = reinterpret_cast<WTF::PartitionPageHeader*>(reinterpret_cast<size_t>(ptr) & WTF::kPartitionPageBaseMask);
+ EXPECT_EQ(1, page->numAllocatedSlots);
+
+ // Work out a pointer into page2 and free it; and then page1 and free it.
+ char* ptr2 = reinterpret_cast<char*>(page1) + sizeof(WTF::PartitionPageHeader);
+ partitionFree(ptr2);
+ ptr2 = reinterpret_cast<char*>(page2) + sizeof(WTF::PartitionPageHeader);
+ partitionFree(ptr2);
+
+ // If we perform two allocations from the same bucket now, we expect to
+ // refill both the nearly full pages.
+ (void) partitionAlloc(allocator.root(), kTestAllocSize);
+ (void) partitionAlloc(allocator.root(), kTestAllocSize);
+ EXPECT_EQ(1, page->numAllocatedSlots);
+
+ FreeFullPage(page2, kTestAllocSize);
+ FreeFullPage(page1, kTestAllocSize);
+ partitionFree(ptr);
+
+ TestShutdown();
+}
+
#if OS(POSIX)
// Test correct handling if our mapping collides with another.
« no previous file with comments | « Source/wtf/PartitionAlloc.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698