Home | History | Annotate | Download | only in space
      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 
     20 namespace art {
     21 namespace gc {
     22 namespace space {
     23 
     24 class 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 
     34 void 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 
     98 class 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 
    125 void 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 
    148 TEST_F(LargeObjectSpaceTest, LargeObjectTest) {
    149   LargeObjectTest();
    150 }
    151 
    152 TEST_F(LargeObjectSpaceTest, RaceTest) {
    153   RaceTest();
    154 }
    155 
    156 }  // namespace space
    157 }  // namespace gc
    158 }  // namespace art
    159