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