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 1741b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko#include "base/time_utils.h" 18a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe#include "space_test.h" 19a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe#include "large_object_space.h" 20a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 21a7433515114ae725c3427cd510f76b84107170a1Andreas Gampenamespace art { 22a7433515114ae725c3427cd510f76b84107170a1Andreas Gampenamespace gc { 23a7433515114ae725c3427cd510f76b84107170a1Andreas Gampenamespace space { 24a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 25a7433515114ae725c3427cd510f76b84107170a1Andreas Gampeclass LargeObjectSpaceTest : public SpaceTest { 26a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe public: 27a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe void LargeObjectTest(); 28b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe 29b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe static constexpr size_t kNumThreads = 10; 30b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe static constexpr size_t kNumIterations = 1000; 31b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe void RaceTest(); 32a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe}; 33a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 34a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 35a7433515114ae725c3427cd510f76b84107170a1Andreas Gampevoid LargeObjectSpaceTest::LargeObjectTest() { 36a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe size_t rand_seed = 0; 378f23620d45399286564986d2541cda761b3fe0acMathieu Chartier Thread* const self = Thread::Current(); 38a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe for (size_t i = 0; i < 2; ++i) { 39a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe LargeObjectSpace* los = nullptr; 40a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe if (i == 0) { 41a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe los = space::LargeObjectMapSpace::Create("large object space"); 42a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe } else { 43a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe los = space::FreeListSpace::Create("large object space", nullptr, 128 * MB); 44a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe } 45a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 46a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe static const size_t num_allocations = 64; 47a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe static const size_t max_allocation_size = 0x100000; 48700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::vector<std::pair<mirror::Object*, size_t>> requests; 49a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 50a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe for (size_t phase = 0; phase < 2; ++phase) { 51a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe while (requests.size() < num_allocations) { 52a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe size_t request_size = test_rand(&rand_seed) % max_allocation_size; 53a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe size_t allocation_size = 0; 544460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi size_t bytes_tl_bulk_allocated; 558f23620d45399286564986d2541cda761b3fe0acMathieu Chartier mirror::Object* obj = los->Alloc(self, request_size, &allocation_size, nullptr, 568f23620d45399286564986d2541cda761b3fe0acMathieu Chartier &bytes_tl_bulk_allocated); 57a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe ASSERT_TRUE(obj != nullptr); 586fac447555dc94a935b78198479cce645c837b89Ian Rogers ASSERT_EQ(allocation_size, los->AllocationSize(obj, nullptr)); 59a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe ASSERT_GE(allocation_size, request_size); 604460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi ASSERT_EQ(allocation_size, bytes_tl_bulk_allocated); 61a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe // Fill in our magic value. 6213735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t magic = (request_size & 0xFF) | 1; 63a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe memset(obj, magic, request_size); 64a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe requests.push_back(std::make_pair(obj, request_size)); 65a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe } 66a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 67a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe // "Randomly" shuffle the requests. 68a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe for (size_t k = 0; k < 10; ++k) { 69a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe for (size_t j = 0; j < requests.size(); ++j) { 70a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe std::swap(requests[j], requests[test_rand(&rand_seed) % requests.size()]); 71a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe } 72a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe } 73a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 748f23620d45399286564986d2541cda761b3fe0acMathieu Chartier // Check the zygote flag for the first phase. 758f23620d45399286564986d2541cda761b3fe0acMathieu Chartier if (phase == 0) { 768f23620d45399286564986d2541cda761b3fe0acMathieu Chartier for (const auto& pair : requests) { 778f23620d45399286564986d2541cda761b3fe0acMathieu Chartier mirror::Object* obj = pair.first; 788f23620d45399286564986d2541cda761b3fe0acMathieu Chartier ASSERT_FALSE(los->IsZygoteLargeObject(self, obj)); 798f23620d45399286564986d2541cda761b3fe0acMathieu Chartier } 808f23620d45399286564986d2541cda761b3fe0acMathieu Chartier los->SetAllLargeObjectsAsZygoteObjects(self); 818f23620d45399286564986d2541cda761b3fe0acMathieu Chartier for (const auto& pair : requests) { 828f23620d45399286564986d2541cda761b3fe0acMathieu Chartier mirror::Object* obj = pair.first; 838f23620d45399286564986d2541cda761b3fe0acMathieu Chartier ASSERT_TRUE(los->IsZygoteLargeObject(self, obj)); 848f23620d45399286564986d2541cda761b3fe0acMathieu Chartier } 858f23620d45399286564986d2541cda761b3fe0acMathieu Chartier } 868f23620d45399286564986d2541cda761b3fe0acMathieu Chartier 87a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe // Free 1 / 2 the allocations the first phase, and all the second phase. 888f23620d45399286564986d2541cda761b3fe0acMathieu Chartier size_t limit = phase == 0 ? requests.size() / 2 : 0; 89a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe while (requests.size() > limit) { 90a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe mirror::Object* obj = requests.back().first; 91a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe size_t request_size = requests.back().second; 92a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe requests.pop_back(); 9313735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t magic = (request_size & 0xFF) | 1; 94a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe for (size_t k = 0; k < request_size; ++k) { 9513735955f39b3b304c37d2b2840663c131262c18Ian Rogers ASSERT_EQ(reinterpret_cast<const uint8_t*>(obj)[k], magic); 96a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe } 97a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe ASSERT_GE(los->Free(Thread::Current(), obj), request_size); 98a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe } 99a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe } 100af4edbd2b77fef0eee3827eb30cc1a0e8e6efeb1Mathieu Chartier // Test that dump doesn't crash. 101af4edbd2b77fef0eee3827eb30cc1a0e8e6efeb1Mathieu Chartier los->Dump(LOG(INFO)); 102a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 1034460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi size_t bytes_allocated = 0, bytes_tl_bulk_allocated; 104a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe // Checks that the coalescing works. 1058f23620d45399286564986d2541cda761b3fe0acMathieu Chartier mirror::Object* obj = los->Alloc(self, 100 * MB, &bytes_allocated, nullptr, 1064460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi &bytes_tl_bulk_allocated); 107a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe EXPECT_TRUE(obj != nullptr); 108a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe los->Free(Thread::Current(), obj); 109a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 110a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe EXPECT_EQ(0U, los->GetBytesAllocated()); 111a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe EXPECT_EQ(0U, los->GetObjectsAllocated()); 112a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe delete los; 113a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe } 114a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe} 115a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 116b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampeclass AllocRaceTask : public Task { 117b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe public: 118b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe AllocRaceTask(size_t id, size_t iterations, size_t size, LargeObjectSpace* los) : 119b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe id_(id), iterations_(iterations), size_(size), los_(los) {} 120b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe 121b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe void Run(Thread* self) { 122b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe for (size_t i = 0; i < iterations_ ; ++i) { 1234460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi size_t alloc_size, bytes_tl_bulk_allocated; 1244460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi mirror::Object* ptr = los_->Alloc(self, size_, &alloc_size, nullptr, 1254460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi &bytes_tl_bulk_allocated); 126b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe 127b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe NanoSleep((id_ + 3) * 1000); // (3+id) mu s 128b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe 129b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe los_->Free(self, ptr); 130b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe } 131b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe } 132b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe 133b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe virtual void Finalize() { 134b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe delete this; 135b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe } 136b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe 137b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe private: 138b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe size_t id_; 139b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe size_t iterations_; 140b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe size_t size_; 141b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe LargeObjectSpace* los_; 142b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe}; 143b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe 144b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampevoid LargeObjectSpaceTest::RaceTest() { 145b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe for (size_t los_type = 0; los_type < 2; ++los_type) { 146b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe LargeObjectSpace* los = nullptr; 147b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe if (los_type == 0) { 148b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe los = space::LargeObjectMapSpace::Create("large object space"); 149b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe } else { 150b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe los = space::FreeListSpace::Create("large object space", nullptr, 128 * MB); 151b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe } 152b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe 153b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe Thread* self = Thread::Current(); 154b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe ThreadPool thread_pool("Large object space test thread pool", kNumThreads); 155b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe for (size_t i = 0; i < kNumThreads; ++i) { 156b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe thread_pool.AddTask(self, new AllocRaceTask(i, kNumIterations, 16 * KB, los)); 157b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe } 158b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe 159b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe thread_pool.StartWorkers(self); 160b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe 161b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe thread_pool.Wait(self, true, false); 162b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe 163b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe delete los; 164b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe } 165b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe} 166a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 167a7433515114ae725c3427cd510f76b84107170a1Andreas GampeTEST_F(LargeObjectSpaceTest, LargeObjectTest) { 168a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe LargeObjectTest(); 169a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe} 170a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe 171b870823dd181571e10ecda58a6b5660e62bb18beAndreas GampeTEST_F(LargeObjectSpaceTest, RaceTest) { 172b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe RaceTest(); 173b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe} 174b870823dd181571e10ecda58a6b5660e62bb18beAndreas Gampe 175a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe} // namespace space 176a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe} // namespace gc 177a7433515114ae725c3427cd510f76b84107170a1Andreas Gampe} // namespace art 178