Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(492)

Side by Side Diff: base/memory/discardable_memory_allocator_unittest.cc

Issue 25293002: Add DiscardableMemoryAllocator to work around FD limit issue. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Shorten critical section + add unit test Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "build/build_config.h"
6
7 #include "base/logging.h"
8 #include "base/memory/discardable_memory.h"
9 #include "base/memory/discardable_memory_allocator.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 #if defined(OS_ANDROID)
14 #include <sys/types.h>
15 #include <unistd.h>
16
17 #include <fstream>
18 #include <iostream>
19 #include <string>
20 #include <vector>
21
22 #include "base/strings/string_number_conversions.h"
23 #include "base/strings/string_split.h"
24 #include "base/strings/stringprintf.h"
25 #endif
26
27 namespace base {
28 namespace {
29
30 const char kAllocatorName[] = "allocator-for-testing";
31 const size_t kPageSize = 4096;
32
33 scoped_ptr<DiscardableMemoryAllocator> CreateAllocator() {
34 return DiscardableMemoryAllocator::Create(kAllocatorName);
35 }
36
37 void WriteToDiscardableMemory(DiscardableMemory* memory) {
38 DCHECK_EQ(0U, memory->size() % sizeof(int));
39 // Write to the first and the last pages only to avoid paging in up to 64
40 // MBytes.
41 static_cast<int*>(memory->Memory())[0] = 1;
42 static_cast<int*>(memory->Memory())[memory->size() / sizeof(int) - 1] = 1;
43 }
44
45 TEST(DiscardableMemoryAllocatorTest, Basic) {
46 const scoped_ptr<DiscardableMemoryAllocator> allocator(CreateAllocator());
47 ASSERT_TRUE(allocator);
48 scoped_ptr<DiscardableMemory> memory(allocator->Allocate(128 * sizeof(int)));
49 ASSERT_TRUE(memory);
50 WriteToDiscardableMemory(memory.get());
51 }
52
53 TEST(DiscardableMemoryAllocatorTest, LargeAllocation) {
54 const scoped_ptr<DiscardableMemoryAllocator> allocator(CreateAllocator());
55 ASSERT_TRUE(allocator);
56 scoped_ptr<DiscardableMemory> memory(allocator->Allocate(64 * 1024 * 1024));
57 ASSERT_TRUE(memory);
58 WriteToDiscardableMemory(memory.get());
59 }
60
61 TEST(DiscardableMemoryAllocatorTest, ChunksArePageAligned) {
62 const scoped_ptr<DiscardableMemoryAllocator> allocator(CreateAllocator());
63 ASSERT_TRUE(allocator);
64 scoped_ptr<DiscardableMemory> memory(allocator->Allocate(kPageSize));
65 ASSERT_TRUE(memory);
66 EXPECT_EQ(0U, reinterpret_cast<uint64_t>(memory->Memory()) % kPageSize);
67 WriteToDiscardableMemory(memory.get());
68 }
69
70 TEST(DiscardableMemoryAllocatorTest, SizeAlignmentIsImplementationDetail) {
71 const scoped_ptr<DiscardableMemoryAllocator> allocator(CreateAllocator());
72 ASSERT_TRUE(allocator);
73 const size_t requested_size = kPageSize + 1; // Rounded up to 2 * kPageSize.
74 scoped_ptr<DiscardableMemory> memory(allocator->Allocate(requested_size));
75 ASSERT_TRUE(memory);
76 EXPECT_EQ(requested_size, memory->size());
77 }
78
79 TEST(DiscardableMemoryAllocatorTest, AllocateFreeAllocate) {
80 const scoped_ptr<DiscardableMemoryAllocator> allocator(CreateAllocator());
81 ASSERT_TRUE(allocator);
82 scoped_ptr<DiscardableMemory> memory(allocator->Allocate(kPageSize));
83 ASSERT_TRUE(memory);
84 void* const address = memory->Memory();
85 memory->Unlock(); // Tests that the recycled chunk is being locked correctly.
86 memory.reset();
87 memory = allocator->Allocate(kPageSize);
88 ASSERT_TRUE(memory);
89 // The previously freed chunk should be reused.
90 EXPECT_EQ(address, memory->Memory());
91 WriteToDiscardableMemory(memory.get());
92 }
93
94 TEST(DiscardableMemoryAllocatorTest, UseMultipleAshmemRegions) {
95 const scoped_ptr<DiscardableMemoryAllocator> allocator(CreateAllocator());
96 ASSERT_TRUE(allocator);
97 const size_t kAshmemRegionSize = 32 * 1024 * 1024;
98 // Leave one page untouched at the end of the ashmem region.
99 scoped_ptr<DiscardableMemory> memory1(
100 allocator->Allocate(kAshmemRegionSize - kPageSize));
101 ASSERT_TRUE(memory1);
102 WriteToDiscardableMemory(memory1.get());
103
104 scoped_ptr<DiscardableMemory> memory2(
105 allocator->Allocate(kAshmemRegionSize));
106 ASSERT_TRUE(memory2);
107 WriteToDiscardableMemory(memory2.get());
108 // The last page of the first ashmem region should be used for this
109 // allocation.
110 scoped_ptr<DiscardableMemory> memory3(
111 allocator->Allocate(kPageSize));
112 ASSERT_TRUE(memory3);
113 WriteToDiscardableMemory(memory3.get());
114 EXPECT_EQ(memory3->Memory(),
115 static_cast<char*>(memory1->Memory()) + memory1->size());
116 }
117
118 TEST(DiscardableMemoryAllocatorTest, ThreadSafeAllocator) {
119 const scoped_ptr<DiscardableMemoryAllocator> allocator(
120 DiscardableMemoryAllocator::CreateThreadSafeInstance(kAllocatorName));
121 ASSERT_TRUE(allocator);
122 scoped_ptr<DiscardableMemory> memory(allocator->Allocate(kPageSize));
123 ASSERT_TRUE(memory);
124 WriteToDiscardableMemory(memory.get());
125 memory.reset(allocator->Allocate(kPageSize).release());
126 ASSERT_TRUE(memory);
127 WriteToDiscardableMemory(memory.get());
128 }
129
130 #if defined(OS_ANDROID)
131
132 // Returns -1 if an error happened during parsing.
133 int GetAllocatorDirtyMemoryInKBytes() {
134 const std::string smaps_path = StringPrintf("/proc/%d/smaps", getpid());
135 std::ifstream stream(smaps_path.c_str());
136 if (!stream.good())
137 return -1;
138 std::vector<std::string> lines;
139 for (std::string line; std::getline(stream, line); lines.push_back(line));
140 int dirty_kbytes = 0;
141 for (std::vector<std::string>::const_iterator it = lines.begin();
142 it != lines.end(); ++it) {
143 if (it->find(kAllocatorName) == std::string::npos)
144 continue;
145 const std::string& private_dirty_line = it[7];
146 if (private_dirty_line.find("Private_Dirty") == std::string::npos)
147 return -1;
148 std::vector<std::string> tokens;
149 SplitString(private_dirty_line, ' ', &tokens);
150 if (tokens.size() < 3U)
151 return -1;
152 int size;
153 if (!base::StringToInt(tokens[tokens.size() - 2], &size))
154 return -1;
155 dirty_kbytes += size;
156 it += 6;
157 }
158 return dirty_kbytes;
159 }
160
161 TEST(DiscardableMemoryAllocatorTest, PagesAreCommittedLazily) {
162 const scoped_ptr<DiscardableMemoryAllocator> allocator(CreateAllocator());
163 ASSERT_TRUE(allocator);
164 scoped_ptr<DiscardableMemory> memory(allocator->Allocate(2 * 4096));
165 ASSERT_TRUE(memory);
166 EXPECT_EQ(0, GetAllocatorDirtyMemoryInKBytes());
167 static_cast<char*>(memory->Memory())[0] = 'a';
168 EXPECT_EQ(4, GetAllocatorDirtyMemoryInKBytes());
169 // Write to the second page.
170 static_cast<char*>(memory->Memory())[kPageSize] = 'b';
171 EXPECT_EQ(8, GetAllocatorDirtyMemoryInKBytes());
172 }
173
174 TEST(DiscardableMemoryAllocatorTest, FreeChunksAreNotCommitted) {
175 const scoped_ptr<DiscardableMemoryAllocator> allocator(CreateAllocator());
176 ASSERT_TRUE(allocator);
177 EXPECT_EQ(0, GetAllocatorDirtyMemoryInKBytes());
178 scoped_ptr<DiscardableMemory> memory(allocator->Allocate(kPageSize));
179 ASSERT_TRUE(memory);
180 WriteToDiscardableMemory(memory.get());
181 EXPECT_EQ(4, GetAllocatorDirtyMemoryInKBytes());
182 memory.reset();
183 EXPECT_EQ(0, GetAllocatorDirtyMemoryInKBytes());
184 }
185
186 #endif // OS_ANDROID
187
188 } // namespace
189 } // namespace base
OLDNEW
« no previous file with comments | « base/memory/discardable_memory_allocator_android.cc ('k') | base/memory/discardable_memory_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698