large_object_space_test.cc revision 66e222aa48e6d2fe4c78a1df938364b82bc83e72
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "space_test.h" 18#include "large_object_space.h" 19 20namespace art { 21namespace gc { 22namespace space { 23 24class LargeObjectSpaceTest : public SpaceTest { 25 public: 26 void LargeObjectTest(); 27 28 static constexpr size_t kNumThreads = 10; 29 static constexpr size_t kNumIterations = 1000; 30 void RaceTest(); 31}; 32 33 34void LargeObjectSpaceTest::LargeObjectTest() { 35 size_t rand_seed = 0; 36 for (size_t i = 0; i < 2; ++i) { 37 LargeObjectSpace* los = nullptr; 38 if (i == 0) { 39 los = space::LargeObjectMapSpace::Create("large object space"); 40 } else { 41 los = space::FreeListSpace::Create("large object space", nullptr, 128 * MB); 42 } 43 44 static const size_t num_allocations = 64; 45 static const size_t max_allocation_size = 0x100000; 46 std::vector<std::pair<mirror::Object*, size_t>> requests; 47 48 for (size_t phase = 0; phase < 2; ++phase) { 49 while (requests.size() < num_allocations) { 50 size_t request_size = test_rand(&rand_seed) % max_allocation_size; 51 size_t allocation_size = 0; 52 mirror::Object* obj = los->Alloc(Thread::Current(), request_size, &allocation_size, 53 nullptr); 54 ASSERT_TRUE(obj != nullptr); 55 ASSERT_EQ(allocation_size, los->AllocationSize(obj, nullptr)); 56 ASSERT_GE(allocation_size, request_size); 57 // Fill in our magic value. 58 byte magic = (request_size & 0xFF) | 1; 59 memset(obj, magic, request_size); 60 requests.push_back(std::make_pair(obj, request_size)); 61 } 62 63 // "Randomly" shuffle the requests. 64 for (size_t k = 0; k < 10; ++k) { 65 for (size_t j = 0; j < requests.size(); ++j) { 66 std::swap(requests[j], requests[test_rand(&rand_seed) % requests.size()]); 67 } 68 } 69 70 // Free 1 / 2 the allocations the first phase, and all the second phase. 71 size_t limit = !phase ? requests.size() / 2 : 0; 72 while (requests.size() > limit) { 73 mirror::Object* obj = requests.back().first; 74 size_t request_size = requests.back().second; 75 requests.pop_back(); 76 byte magic = (request_size & 0xFF) | 1; 77 for (size_t k = 0; k < request_size; ++k) { 78 ASSERT_EQ(reinterpret_cast<const byte*>(obj)[k], magic); 79 } 80 ASSERT_GE(los->Free(Thread::Current(), obj), request_size); 81 } 82 } 83 // Test that dump doesn't crash. 84 los->Dump(LOG(INFO)); 85 86 size_t bytes_allocated = 0; 87 // Checks that the coalescing works. 88 mirror::Object* obj = los->Alloc(Thread::Current(), 100 * MB, &bytes_allocated, nullptr); 89 EXPECT_TRUE(obj != nullptr); 90 los->Free(Thread::Current(), obj); 91 92 EXPECT_EQ(0U, los->GetBytesAllocated()); 93 EXPECT_EQ(0U, los->GetObjectsAllocated()); 94 delete los; 95 } 96} 97 98class AllocRaceTask : public Task { 99 public: 100 AllocRaceTask(size_t id, size_t iterations, size_t size, LargeObjectSpace* los) : 101 id_(id), iterations_(iterations), size_(size), los_(los) {} 102 103 void Run(Thread* self) { 104 for (size_t i = 0; i < iterations_ ; ++i) { 105 size_t alloc_size; 106 mirror::Object* ptr = los_->Alloc(self, size_, &alloc_size, nullptr); 107 108 NanoSleep((id_ + 3) * 1000); // (3+id) mu s 109 110 los_->Free(self, ptr); 111 } 112 } 113 114 virtual void Finalize() { 115 delete this; 116 } 117 118 private: 119 size_t id_; 120 size_t iterations_; 121 size_t size_; 122 LargeObjectSpace* los_; 123}; 124 125void LargeObjectSpaceTest::RaceTest() { 126 for (size_t los_type = 0; los_type < 2; ++los_type) { 127 LargeObjectSpace* los = nullptr; 128 if (los_type == 0) { 129 los = space::LargeObjectMapSpace::Create("large object space"); 130 } else { 131 los = space::FreeListSpace::Create("large object space", nullptr, 128 * MB); 132 } 133 134 Thread* self = Thread::Current(); 135 ThreadPool thread_pool("Large object space test thread pool", kNumThreads); 136 for (size_t i = 0; i < kNumThreads; ++i) { 137 thread_pool.AddTask(self, new AllocRaceTask(i, kNumIterations, 16 * KB, los)); 138 } 139 140 thread_pool.StartWorkers(self); 141 142 thread_pool.Wait(self, true, false); 143 144 delete los; 145 } 146} 147 148TEST_F(LargeObjectSpaceTest, LargeObjectTest) { 149 LargeObjectTest(); 150} 151 152TEST_F(LargeObjectSpaceTest, RaceTest) { 153 RaceTest(); 154} 155 156} // namespace space 157} // namespace gc 158} // namespace art 159