SEC: Reduce lock hold times.

Only flush a subset of extents during flushing, and drop the lock while doing
so.
This commit is contained in:
David Goldblatt
2021-01-05 15:52:25 -08:00
committed by David Goldblatt
parent 1944ebbe7f
commit bf448d7a5a
3 changed files with 110 additions and 24 deletions

View File

@@ -8,13 +8,9 @@
* Small extent cache.
*
* This includes some utilities to cache small extents. We have a per-pszind
* bin with its own lock and edata heap (including only extents of that size).
* We don't try to do any coalescing of extents (since it would require
* cross-bin locks). As a result, we need to be careful about fragmentation.
* As a gesture in that direction, we limit the size of caches, apply first-fit
* within the bins, and, when flushing a bin, flush all of its extents rather
* than just those up to some threshold. When we allocate again, we'll get a
* chance to move to better ones.
* bin with its own list of extents of that size. We don't try to do any
* coalescing of extents (since it would in general require cross-shard locks or
* knowledge of the underlying PAI implementation).
*/
/*
@@ -46,6 +42,19 @@ sec_stats_accum(sec_stats_t *dst, sec_stats_t *src) {
dst->bytes += src->bytes;
}
/* A collections of free extents, all of the same size. */
typedef struct sec_bin_s sec_bin_t;
struct sec_bin_s {
/*
* Number of bytes in this particular bin (as opposed to the
* sec_shard_t's bytes_cur. This isn't user visible or reported in
* stats; rather, it allows us to quickly determine the change in the
* centralized counter when flushing.
*/
size_t bytes_cur;
edata_list_active_t freelist;
};
typedef struct sec_shard_s sec_shard_t;
struct sec_shard_s {
/*
@@ -64,8 +73,11 @@ struct sec_shard_s {
* hooks are installed.
*/
bool enabled;
edata_list_active_t freelist[SEC_NPSIZES];
sec_bin_t bins[SEC_NPSIZES];
/* Number of bytes in all bins in the shard. */
size_t bytes_cur;
/* The next pszind to flush in the flush-some pathways. */
pszind_t to_flush_next;
};
typedef struct sec_s sec_t;
@@ -83,6 +95,18 @@ struct sec_s {
* the bins in that shard to be flushed.
*/
size_t bytes_max;
/*
* The number of bytes (in all bins) we flush down to when we exceed
* bytes_cur. We want this to be less than bytes_cur, because
* otherwise we could get into situations where a shard undergoing
* net-deallocation keeps bytes_cur very near to bytes_max, so that
* most deallocations get immediately forwarded to the underlying PAI
* implementation, defeating the point of the SEC.
*
* Currently this is just set to bytes_max / 2, but eventually can be
* configurable.
*/
size_t bytes_after_flush;
/*
* We don't necessarily always use all the shards; requests are