New region alloc

upfront: This is not the segment allocation, which uses parts of the busy
obj region allocation, and is mostly motivated by how much data we need
to have in RAM at minimum.

For the region allocation, we have conflicting goals:

- To keep the log short, we want to use the least number of regions
- To reduce fragmentation, we want to use the largest possible
  allocations
- To use space efficiently, we want to split regions into power of
  two allocations.

Also, for chunked encoding, we do not have an upper limit of
how much space we are going to need, so we have to use the
estimate provided by fellow_busy_obj_getspace(). It can not
guess more than objsize_max.

The new region alloc algorithm takes this compromise:

- For the base case that we ran out of available regions (220), we
  allocate all we need without cramming.
- Otherwise if we need less than a chunk, we request it
- Otherwise if we know the size, we round down to a power of two
- Otherwise we round up

We then allow any cramming down to the chunk size, because that
is what our LRU reservation uses.
parent 7200ef50
......@@ -1863,10 +1863,6 @@ fellow_busy_region_alloc(struct fellow_busy *fbo, size_t size, int8_t cram)
fc = fbo->fc;
CHECK_OBJ_NOTNULL(fc, FELLOW_CACHE_MAGIC);
/* stop cramming if we run out of regions */
if (fbo->nregion < FCO_MAX_REGIONS - FCO_REGIONS_RESERVE)
cram = 0;
assert(fbo->nregion < FCO_MAX_REGIONS);
fdr = &fbo->region[fbo->nregion];
......@@ -2011,7 +2007,9 @@ fellow_busy_body_seg_alloc(struct fellow_busy *fbo,
struct fellow_body_region *fbr;
struct buddy_off_extent *fdr;
struct fellow_cache *fc;
unsigned chunkbits;
size_t spc;
int8_t cram;
CHECK_OBJ_NOTNULL(fbo, FELLOW_BUSY_MAGIC);
CHECK_OBJ_NOTNULL(fds, FELLOW_DISK_SEG_MAGIC);
......@@ -2025,13 +2023,37 @@ fellow_busy_body_seg_alloc(struct fellow_busy *fbo,
fdr = fbr->reg;
if (fdr == NULL || fbr->len == fdr->size) {
cram = fbo->fc->tune->cram;
chunkbits = fbo->fc->tune->chunk_exponent;
memset(fbr, 0, sizeof *fbr);
assert(fbo->sz_estimate > fbo->sz_dskalloc);
spc = fbo->sz_estimate - fbo->sz_dskalloc;
fdr = fellow_busy_region_alloc(fbo, spc, fc->tune->cram);
if (fbo->nregion >= FCO_MAX_REGIONS - FCO_REGIONS_RESERVE)
// out of regions: keep spc, no cram
cram = 0;
else if (fbo->grown == 0 && (spc >> chunkbits) == 0)
// c-l or initial chunked - keep small req
(void)spc;
else if (fbo->grown == 0)
// known size -> round down
spc = (size_t)1 << log2down(spc);
else
// size unknown -> round up
spc = (size_t)1 << log2up(spc);
/* for allocation larger than chunk size, always allow
* cram down to chunk size, but do split pages (INT8_MIN)
*/
if (cram > 0 && spc >= (size_t)1 << chunkbits) {
assert(fbo->fc->tune->chunk_exponent <= INT8_MAX);
cram = buddy_cramlimit_bits(spc, INT8_MIN,
(int8_t)fbo->fc->tune->chunk_exponent);
}
fdr = fellow_busy_region_alloc(fbo, spc, cram);
if (fdr == NULL)
return (0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment