161 log_debug(metaspace)("ChunkManager %s: get chunk: max " CHKLVL_FORMAT " (" SIZE_FORMAT ")," |
161 log_debug(metaspace)("ChunkManager %s: get chunk: max " CHKLVL_FORMAT " (" SIZE_FORMAT ")," |
162 "preferred " CHKLVL_FORMAT " (" SIZE_FORMAT ").", |
162 "preferred " CHKLVL_FORMAT " (" SIZE_FORMAT ").", |
163 _name, max_level, chklvl::word_size_for_level(max_level), |
163 _name, max_level, chklvl::word_size_for_level(max_level), |
164 pref_level, chklvl::word_size_for_level(pref_level)); |
164 pref_level, chklvl::word_size_for_level(pref_level)); |
165 |
165 |
|
166 // When handing a new chunk to the caller, we must balance the need to not let free space go to waste |
|
167 // with the need to keep fragmentation low. |
|
168 // Every request comes with a preferred chunk size and the minimum chunk size, which is the bare minimum |
|
169 // needed to house the metadata allocation which triggered this chunk allocation. |
|
170 // |
|
171 // Ideally, we have a free chunk of the preferred size just laying around and hand that one out. |
|
172 // Realistically, we are often faced with the choice of either taking a larger chunk and split it |
|
173 // or taking a smaller chunk than the preferred size. Both has pros and cons: splitting a larger chunk |
|
174 // reduces the number of large chunks available for large allocations, and, increases fragmentation. |
|
175 // Using a smaller chunk may also increase fragmentation (beside being inefficient at some point) if |
|
176 // e.g. a normal class loader - which lives normally off 64K chunks - eats from the bowl of small chunk |
|
177 // loaders, which prefer 4K or 1K chunks. |
|
178 |
166 // 1) Attempt to find a free chunk of exactly the pref_level level |
179 // 1) Attempt to find a free chunk of exactly the pref_level level |
167 c = remove_first_chunk_at_level(pref_level); |
180 c = remove_first_chunk_at_level(pref_level); |
168 |
181 |
169 // 2) Failing that, we are also willing to accept a chunk half that size, but nothing less for now... |
182 // 2) Failing that, we are also willing to accept a smaller chunk, but only up to a limit |
|
183 // (for now, half the preferred size)... |
170 if (c == NULL && pref_level < max_level) { |
184 if (c == NULL && pref_level < max_level) { |
171 c = remove_first_chunk_at_level(pref_level + 1); |
185 c = remove_first_chunk_at_level(pref_level + 1); |
172 } |
186 } |
173 |
187 |
174 // 3) Failing that, attempt to find a free chunk of larger size and split it to get the ideal size... |
188 // 3) Failing that, attempt to find a free chunk of larger size and split it to the preferred size... |
175 if (c == NULL) { |
189 if (c == NULL) { |
176 for (chklvl_t lvl = pref_level - 1; lvl >= chklvl::ROOT_CHUNK_LEVEL; lvl --) { |
190 for (chklvl_t lvl = pref_level - 1; lvl >= chklvl::ROOT_CHUNK_LEVEL; lvl --) { |
177 c = remove_first_chunk_at_level(lvl); |
191 c = remove_first_chunk_at_level(lvl); |
178 if (c != NULL) { |
192 if (c != NULL) { |
179 // Split chunk; add splinters to freelist |
193 // Split chunk; add splinters to freelist |
181 break; |
195 break; |
182 } |
196 } |
183 } |
197 } |
184 } |
198 } |
185 |
199 |
186 // 4) Failing that, before we start allocating a new root chunk, lets really scrape the barrel. Any |
200 // 4) Failing that, before we give up and get a new root chunk, lets really scrape the barrel. Any |
187 // smaller chunk is acceptable provided it fits the minimal size.... |
201 // smaller chunk is acceptable now... |
188 if (c == NULL) { |
202 if (c == NULL) { |
189 for (chklvl_t lvl = pref_level + 1; lvl <= max_level; lvl ++) { |
203 for (chklvl_t lvl = pref_level + 2; lvl <= max_level; lvl ++) { |
190 c = remove_first_chunk_at_level(lvl); |
204 c = remove_first_chunk_at_level(lvl); |
191 if (c != NULL) { |
205 if (c != NULL) { |
192 break; |
206 break; |
193 } |
207 } |
194 } |
208 } |
195 } |
209 } |
196 |
210 |
197 // 4) Failing that, attempt to allocate a new root chunk from the connected virtual space. |
211 // 5) Failing all that, allocate a new root chunk from the connected virtual space. |
198 if (c == NULL) { |
212 if (c == NULL) { |
199 |
213 |
200 // Tracing |
214 // Tracing |
201 log_debug(metaspace)("ChunkManager %s: need new root chunk.", _name); |
215 log_debug(metaspace)("ChunkManager %s: need new root chunk.", _name); |
202 |
216 |