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