< prev index next >

test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp

Print this page

  9  *
 10  * This code is distributed in the hope that it will be useful, but WITHOUT
 11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  *
 24  */
 25 
 26 #include "precompiled.hpp"
 27 #include "memory/metaspace/chunkManager.hpp"
 28 #include "memory/metaspace/counters.hpp"

 29 #include "memory/metaspace/metaspaceArena.hpp"
 30 #include "memory/metaspace/metaspaceArenaGrowthPolicy.hpp"

 31 #include "memory/metaspace/metaspaceSettings.hpp"
 32 #include "memory/metaspace/metaspaceStatistics.hpp"
 33 #include "runtime/mutexLocker.hpp"
 34 #include "utilities/debug.hpp"
 35 #include "utilities/globalDefinitions.hpp"
 36 //#define LOG_PLEASE
 37 #include "metaspaceGtestCommon.hpp"
 38 #include "metaspaceGtestContexts.hpp"
 39 #include "metaspaceGtestSparseArray.hpp"
 40 
 41 using metaspace::AllocationAlignmentByteSize;
 42 using metaspace::ArenaGrowthPolicy;
 43 using metaspace::ChunkManager;
 44 using metaspace::IntCounter;
 45 using metaspace::MemRangeCounter;

 46 using metaspace::MetaspaceArena;

 47 using metaspace::SizeAtomicCounter;
 48 using metaspace::ArenaStats;
 49 using metaspace::InUseChunkStats;
 50 
 51 // Little randomness helper
 52 static bool fifty_fifty() {
 53   return IntRange(100).random_value() < 50;
 54 }
 55 
 56 // A MetaspaceArenaTestBed contains a single MetaspaceArena and its lock.
 57 // It keeps track of allocations done from this MetaspaceArena.
 58 class MetaspaceArenaTestBed : public CHeapObj<mtInternal> {
 59 
 60   MetaspaceArena* _arena;
 61 
 62   const SizeRange _allocation_range;
 63   size_t _size_of_last_failed_allocation;
 64 
 65   // We keep track of all allocations done thru the MetaspaceArena to
 66   // later check for overwriters.

109     // - if +MetaspaceGuardAllocations, guard costs
110 
111     // Since what we deallocated may have been given back to us in a following allocation,
112     // we only know fore sure we allocated what we did not give back.
113     const size_t at_least_allocated = _alloc_count.total_size() - _dealloc_count.total_size();
114 
115     // At most we allocated this:
116     const size_t max_word_overhead_per_alloc =
117         4 + (metaspace::Settings::use_allocation_guard() ? 4 : 0);
118     const size_t at_most_allocated = _alloc_count.total_size() + max_word_overhead_per_alloc * _alloc_count.count();
119 
120     ASSERT_LE(at_least_allocated, in_use_stats._used_words - stats._free_blocks_word_size);
121     ASSERT_GE(at_most_allocated, in_use_stats._used_words - stats._free_blocks_word_size);
122 
123   }
124 
125 public:
126 
127   MetaspaceArena* arena() { return _arena; }
128 
129   MetaspaceArenaTestBed(ChunkManager* cm, const ArenaGrowthPolicy* alloc_sequence,
130                         SizeAtomicCounter* used_words_counter, SizeRange allocation_range) :
131     _arena(nullptr),
132     _allocation_range(allocation_range),
133     _size_of_last_failed_allocation(0),
134     _allocations(nullptr),
135     _alloc_count(),
136     _dealloc_count()
137   {
138     _arena = new MetaspaceArena(cm, alloc_sequence, used_words_counter, "gtest-MetaspaceArenaTestBed-sm");
139   }
140 
141   ~MetaspaceArenaTestBed() {
142 
143     verify_arena_statistics();
144 
145     allocation_t* a = _allocations;
146     while (a != nullptr) {
147       allocation_t* b = a->next;
148       a->verify();
149       FREE_C_HEAP_OBJ(a);
150       a = b;
151     }
152 
153     DEBUG_ONLY(_arena->verify();)
154 
155     // Delete MetaspaceArena. That should clean up all metaspace.
156     delete _arena;
157 
158   }
159 
160   size_t words_allocated() const        { return _alloc_count.total_size(); }
161   int num_allocations() const           { return _alloc_count.count(); }
162 
163   size_t size_of_last_failed_allocation() const { return _size_of_last_failed_allocation; }
164 
165   // Allocate a random amount. Return false if the allocation failed.
166   bool checked_random_allocate() {
167     size_t word_size = 1 + _allocation_range.random_value();
168     MetaWord* p = _arena->allocate(word_size);
169     if (p != nullptr) {
170       EXPECT_TRUE(is_aligned(p, AllocationAlignmentByteSize));







171 
172       allocation_t* a = NEW_C_HEAP_OBJ(allocation_t, mtInternal);
173       a->word_size = word_size;
174       a->p = p;
175       a->mark();
176       a->next = _allocations;
177       _allocations = a;
178       _alloc_count.add(word_size);
179       if ((_alloc_count.count() % 20) == 0) {
180         verify_arena_statistics();
181         DEBUG_ONLY(_arena->verify();)
182       }
183       return true;
184     } else {
185       _size_of_last_failed_allocation = word_size;
186     }
187     return false;
188   }
189 
190   // Deallocate a random allocation
191   void checked_random_deallocate() {
192     allocation_t* a = _allocations;
193     while (a && a->p != nullptr && os::random() % 10 != 0) {
194       a = a->next;
195     }
196     if (a != nullptr && a->p != nullptr) {
197       a->verify();
198       _arena->deallocate(a->p, a->word_size);
199       _dealloc_count.add(a->word_size);
200       a->p = nullptr; a->word_size = 0;
201       if ((_dealloc_count.count() % 20) == 0) {
202         verify_arena_statistics();
203         DEBUG_ONLY(_arena->verify();)
204       }
205     }
206   }
207 
208 }; // End: MetaspaceArenaTestBed
209 
210 class MetaspaceArenaTest {
211 
212   MetaspaceGtestContext _context;
213 
214   SizeAtomicCounter _used_words_counter;
215 
216   SparseArray<MetaspaceArenaTestBed*> _testbeds;
217   IntCounter _num_beds;
218 
219   //////// Bed creation, destruction ///////
220 
221   void create_new_test_bed_at(int slotindex, const ArenaGrowthPolicy* growth_policy, SizeRange allocation_range) {
222     DEBUG_ONLY(_testbeds.check_slot_is_null(slotindex));
223     MetaspaceArenaTestBed* bed = new MetaspaceArenaTestBed(&_context.cm(), growth_policy,
224                                                        &_used_words_counter, allocation_range);
225     _testbeds.set_at(slotindex, bed);
226     _num_beds.increment();
227   }
228 
229   void create_random_test_bed_at(int slotindex) {
230     SizeRange allocation_range(1, 100); // randomize too?
231     const ArenaGrowthPolicy* growth_policy = ArenaGrowthPolicy::policy_for_space_type(
232         (fifty_fifty() ? Metaspace::StandardMetaspaceType : Metaspace::ReflectionMetaspaceType),
233          fifty_fifty());
234     create_new_test_bed_at(slotindex, growth_policy, allocation_range);
235    }
236 
237   // Randomly create a random test bed at a random slot, and return its slot index
238   // (returns false if we reached max number of test beds)
239   bool create_random_test_bed() {
240     const int slot = _testbeds.random_null_slot_index();
241     if (slot != -1) {
242       create_random_test_bed_at(slot);
243     }
244     return slot;

  9  *
 10  * This code is distributed in the hope that it will be useful, but WITHOUT
 11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  *
 24  */
 25 
 26 #include "precompiled.hpp"
 27 #include "memory/metaspace/chunkManager.hpp"
 28 #include "memory/metaspace/counters.hpp"
 29 #include "memory/metaspace/metablock.hpp"
 30 #include "memory/metaspace/metaspaceArena.hpp"
 31 #include "memory/metaspace/metaspaceArenaGrowthPolicy.hpp"
 32 #include "memory/metaspace/metaspaceContext.hpp"
 33 #include "memory/metaspace/metaspaceSettings.hpp"
 34 #include "memory/metaspace/metaspaceStatistics.hpp"
 35 #include "runtime/mutexLocker.hpp"
 36 #include "utilities/debug.hpp"
 37 #include "utilities/globalDefinitions.hpp"
 38 //#define LOG_PLEASE
 39 #include "metaspaceGtestCommon.hpp"
 40 #include "metaspaceGtestContexts.hpp"
 41 #include "metaspaceGtestSparseArray.hpp"
 42 
 43 using metaspace::AllocationAlignmentByteSize;
 44 using metaspace::ArenaGrowthPolicy;
 45 using metaspace::ChunkManager;
 46 using metaspace::IntCounter;
 47 using metaspace::MemRangeCounter;
 48 using metaspace::MetaBlock;
 49 using metaspace::MetaspaceArena;
 50 using metaspace::MetaspaceContext;
 51 using metaspace::SizeAtomicCounter;
 52 using metaspace::ArenaStats;
 53 using metaspace::InUseChunkStats;
 54 
 55 // Little randomness helper
 56 static bool fifty_fifty() {
 57   return IntRange(100).random_value() < 50;
 58 }
 59 
 60 // A MetaspaceArenaTestBed contains a single MetaspaceArena and its lock.
 61 // It keeps track of allocations done from this MetaspaceArena.
 62 class MetaspaceArenaTestBed : public CHeapObj<mtInternal> {
 63 
 64   MetaspaceArena* _arena;
 65 
 66   const SizeRange _allocation_range;
 67   size_t _size_of_last_failed_allocation;
 68 
 69   // We keep track of all allocations done thru the MetaspaceArena to
 70   // later check for overwriters.

113     // - if +MetaspaceGuardAllocations, guard costs
114 
115     // Since what we deallocated may have been given back to us in a following allocation,
116     // we only know fore sure we allocated what we did not give back.
117     const size_t at_least_allocated = _alloc_count.total_size() - _dealloc_count.total_size();
118 
119     // At most we allocated this:
120     const size_t max_word_overhead_per_alloc =
121         4 + (metaspace::Settings::use_allocation_guard() ? 4 : 0);
122     const size_t at_most_allocated = _alloc_count.total_size() + max_word_overhead_per_alloc * _alloc_count.count();
123 
124     ASSERT_LE(at_least_allocated, in_use_stats._used_words - stats._free_blocks_word_size);
125     ASSERT_GE(at_most_allocated, in_use_stats._used_words - stats._free_blocks_word_size);
126 
127   }
128 
129 public:
130 
131   MetaspaceArena* arena() { return _arena; }
132 
133   MetaspaceArenaTestBed(MetaspaceContext* context, const ArenaGrowthPolicy* growth_policy,
134                         size_t allocation_alignment_words, SizeRange allocation_range)
135     : _arena(nullptr)
136     , _allocation_range(allocation_range)
137     , _size_of_last_failed_allocation(0)
138     , _allocations(nullptr)


139   {
140     _arena = new MetaspaceArena(context, growth_policy, Metaspace::min_allocation_alignment_words, "gtest-MetaspaceArenaTestBed-sm");
141   }
142 
143   ~MetaspaceArenaTestBed() {
144 
145     verify_arena_statistics();
146 
147     allocation_t* a = _allocations;
148     while (a != nullptr) {
149       allocation_t* b = a->next;
150       a->verify();
151       FREE_C_HEAP_OBJ(a);
152       a = b;
153     }
154 
155     DEBUG_ONLY(_arena->verify();)
156 
157     // Delete MetaspaceArena. That should clean up all metaspace.
158     delete _arena;
159 
160   }
161 
162   size_t words_allocated() const        { return _alloc_count.total_size(); }
163   int num_allocations() const           { return _alloc_count.count(); }
164 
165   size_t size_of_last_failed_allocation() const { return _size_of_last_failed_allocation; }
166 
167   // Allocate a random amount. Return false if the allocation failed.
168   bool checked_random_allocate() {
169     size_t word_size = 1 + _allocation_range.random_value();
170     MetaBlock wastage;
171     MetaBlock bl = _arena->allocate(word_size, wastage);
172     // We only expect wastage if either alignment was not met or the chunk remainder
173     // was not large enough.
174     if (wastage.is_nonempty()) {
175       _arena->deallocate(wastage);
176       wastage.reset();
177     }
178     if (bl.is_nonempty()) {
179       EXPECT_TRUE(is_aligned(bl.base(), AllocationAlignmentByteSize));
180 
181       allocation_t* a = NEW_C_HEAP_OBJ(allocation_t, mtInternal);
182       a->word_size = word_size;
183       a->p = bl.base();
184       a->mark();
185       a->next = _allocations;
186       _allocations = a;
187       _alloc_count.add(word_size);
188       if ((_alloc_count.count() % 20) == 0) {
189         verify_arena_statistics();
190         DEBUG_ONLY(_arena->verify();)
191       }
192       return true;
193     } else {
194       _size_of_last_failed_allocation = word_size;
195     }
196     return false;
197   }
198 
199   // Deallocate a random allocation
200   void checked_random_deallocate() {
201     allocation_t* a = _allocations;
202     while (a && a->p != nullptr && os::random() % 10 != 0) {
203       a = a->next;
204     }
205     if (a != nullptr && a->p != nullptr) {
206       a->verify();
207       _arena->deallocate(MetaBlock(a->p, a->word_size));
208       _dealloc_count.add(a->word_size);
209       a->p = nullptr; a->word_size = 0;
210       if ((_dealloc_count.count() % 20) == 0) {
211         verify_arena_statistics();
212         DEBUG_ONLY(_arena->verify();)
213       }
214     }
215   }
216 
217 }; // End: MetaspaceArenaTestBed
218 
219 class MetaspaceArenaTest {
220 
221   MetaspaceGtestContext _context;
222 
223   SizeAtomicCounter _used_words_counter;
224 
225   SparseArray<MetaspaceArenaTestBed*> _testbeds;
226   IntCounter _num_beds;
227 
228   //////// Bed creation, destruction ///////
229 
230   void create_new_test_bed_at(int slotindex, const ArenaGrowthPolicy* growth_policy, SizeRange allocation_range) {
231     DEBUG_ONLY(_testbeds.check_slot_is_null(slotindex));
232     MetaspaceArenaTestBed* bed = new MetaspaceArenaTestBed(_context.context(), growth_policy,
233         Metaspace::min_allocation_alignment_words, allocation_range);
234     _testbeds.set_at(slotindex, bed);
235     _num_beds.increment();
236   }
237 
238   void create_random_test_bed_at(int slotindex) {
239     SizeRange allocation_range(1, 100); // randomize too?
240     const ArenaGrowthPolicy* growth_policy = ArenaGrowthPolicy::policy_for_space_type(
241         (fifty_fifty() ? Metaspace::StandardMetaspaceType : Metaspace::ReflectionMetaspaceType),
242          fifty_fifty());
243     create_new_test_bed_at(slotindex, growth_policy, allocation_range);
244    }
245 
246   // Randomly create a random test bed at a random slot, and return its slot index
247   // (returns false if we reached max number of test beds)
248   bool create_random_test_bed() {
249     const int slot = _testbeds.random_null_slot_index();
250     if (slot != -1) {
251       create_random_test_bed_at(slot);
252     }
253     return slot;
< prev index next >