diff options
author | Serapheim Dimitropoulos <[email protected]> | 2019-07-16 10:11:49 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-07-16 10:11:49 -0700 |
commit | 93e28d661e1d704a9cada86ef2bc4763a6ef3be7 (patch) | |
tree | afd5bcb5fe8bb15e5ddc8b9602320eb6d88e64f3 /man/man5/zfs-module-parameters.5 | |
parent | df834a7ccc6a4bb690f6992273a7345cc56afd6d (diff) |
Log Spacemap Project
= Motivation
At Delphix we've seen a lot of customer systems where fragmentation
is over 75% and random writes take a performance hit because a lot
of time is spend on I/Os that update on-disk space accounting metadata.
Specifically, we seen cases where 20% to 40% of sync time is spend
after sync pass 1 and ~30% of the I/Os on the system is spent updating
spacemaps.
The problem is that these pools have existed long enough that we've
touched almost every metaslab at least once, and random writes
scatter frees across all metaslabs every TXG, thus appending to
their spacemaps and resulting in many I/Os. To give an example,
assuming that every VDEV has 200 metaslabs and our writes fit within
a single spacemap block (generally 4K) we have 200 I/Os. Then if we
assume 2 levels of indirection, we need 400 additional I/Os and
since we are talking about metadata for which we keep 2 extra copies
for redundancy we need to triple that number, leading to a total of
1800 I/Os per VDEV every TXG.
We could try and decrease the number of metaslabs so we have less
I/Os per TXG but then each metaslab would cover a wider range on
disk and thus would take more time to be loaded in memory from disk.
In addition, after it's loaded, it's range tree would consume more
memory.
Another idea would be to just increase the spacemap block size
which would allow us to fit more entries within an I/O block
resulting in fewer I/Os per metaslab and a speedup in loading time.
The problem is still that we don't deal with the number of I/Os
going up as the number of metaslabs is increasing and the fact
is that we generally write a lot to a few metaslabs and a little
to the rest of them. Thus, just increasing the block size would
actually waste bandwidth because we won't be utilizing our bigger
block size.
= About this patch
This patch introduces the Log Spacemap project which provides the
solution to the above problem while taking into account all the
aforementioned tradeoffs. The details on how it achieves that can
be found in the references sections below and in the code (see
Big Theory Statement in spa_log_spacemap.c).
Even though the change is fairly constraint within the metaslab
and lower-level SPA codepaths, there is a side-change that is
user-facing. The change is that VDEV IDs from VDEV holes will no
longer be reused. To give some background and reasoning for this,
when a log device is removed and its VDEV structure was replaced
with a hole (or was compacted; if at the end of the vdev array),
its vdev_id could be reused by devices added after that. Now
with the pool-wide space maps recording the vdev ID, this behavior
can cause problems (e.g. is this entry referring to a segment in
the new vdev or the removed log?). Thus, to simplify things the
ID reuse behavior is gone and now vdev IDs for top-level vdevs
are truly unique within a pool.
= Testing
The illumos implementation of this feature has been used internally
for a year and has been in production for ~6 months. For this patch
specifically there don't seem to be any regressions introduced to
ZTS and I have been running zloop for a week without any related
problems.
= Performance Analysis (Linux Specific)
All performance results and analysis for illumos can be found in
the links of the references. Redoing the same experiments in Linux
gave similar results. Below are the specifics of the Linux run.
After the pool reached stable state the percentage of the time
spent in pass 1 per TXG was 64% on average for the stock bits
while the log spacemap bits stayed at 95% during the experiment
(graph: sdimitro.github.io/img/linux-lsm/PercOfSyncInPassOne.png).
Sync times per TXG were 37.6 seconds on average for the stock
bits and 22.7 seconds for the log spacemap bits (related graph:
sdimitro.github.io/img/linux-lsm/SyncTimePerTXG.png). As a result
the log spacemap bits were able to push more TXGs, which is also
the reason why all graphs quantified per TXG have more entries for
the log spacemap bits.
Another interesting aspect in terms of txg syncs is that the stock
bits had 22% of their TXGs reach sync pass 7, 55% reach sync pass 8,
and 20% reach 9. The log space map bits reached sync pass 4 in 79%
of their TXGs, sync pass 7 in 19%, and sync pass 8 at 1%. This
emphasizes the fact that not only we spend less time on metadata
but we also iterate less times to convergence in spa_sync() dirtying
objects.
[related graphs:
stock- sdimitro.github.io/img/linux-lsm/NumberOfPassesPerTXGStock.png
lsm- sdimitro.github.io/img/linux-lsm/NumberOfPassesPerTXGLSM.png]
Finally, the improvement in IOPs that the userland gains from the
change is approximately 40%. There is a consistent win in IOPS as
you can see from the graphs below but the absolute amount of
improvement that the log spacemap gives varies within each minute
interval.
sdimitro.github.io/img/linux-lsm/StockVsLog3Days.png
sdimitro.github.io/img/linux-lsm/StockVsLog10Hours.png
= Porting to Other Platforms
For people that want to port this commit to other platforms below
is a list of ZoL commits that this patch depends on:
Make zdb results for checkpoint tests consistent
db587941c5ff6dea01932bb78f70db63cf7f38ba
Update vdev_is_spacemap_addressable() for new spacemap encoding
419ba5914552c6185afbe1dd17b3ed4b0d526547
Simplify spa_sync by breaking it up to smaller functions
8dc2197b7b1e4d7ebc1420ea30e51c6541f1d834
Factor metaslab_load_wait() in metaslab_load()
b194fab0fb6caad18711abccaff3c69ad8b3f6d3
Rename range_tree_verify to range_tree_verify_not_present
df72b8bebe0ebac0b20e0750984bad182cb6564a
Change target size of metaslabs from 256GB to 16GB
c853f382db731e15a87512f4ef1101d14d778a55
zdb -L should skip leak detection altogether
21e7cf5da89f55ce98ec1115726b150e19eefe89
vs_alloc can underflow in L2ARC vdevs
7558997d2f808368867ca7e5234e5793446e8f3f
Simplify log vdev removal code
6c926f426a26ffb6d7d8e563e33fc176164175cb
Get rid of space_map_update() for ms_synced_length
425d3237ee88abc53d8522a7139c926d278b4b7f
Introduce auxiliary metaslab histograms
928e8ad47d3478a3d5d01f0dd6ae74a9371af65e
Error path in metaslab_load_impl() forgets to drop ms_sync_lock
8eef997679ba54547f7d361553d21b3291f41ae7
= References
Background, Motivation, and Internals of the Feature
- OpenZFS 2017 Presentation:
youtu.be/jj2IxRkl5bQ
- Slides:
slideshare.net/SerapheimNikolaosDim/zfs-log-spacemaps-project
Flushing Algorithm Internals & Performance Results
(Illumos Specific)
- Blogpost:
sdimitro.github.io/post/zfs-lsm-flushing/
- OpenZFS 2018 Presentation:
youtu.be/x6D2dHRjkxw
- Slides:
slideshare.net/SerapheimNikolaosDim/zfs-log-spacemap-flushing-algorithm
Upstream Delphix Issues:
DLPX-51539, DLPX-59659, DLPX-57783, DLPX-61438, DLPX-41227, DLPX-59320
DLPX-63385
Reviewed-by: Sean Eric Fagan <[email protected]>
Reviewed-by: Matt Ahrens <[email protected]>
Reviewed-by: George Wilson <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Serapheim Dimitropoulos <[email protected]>
Closes #8442
Diffstat (limited to 'man/man5/zfs-module-parameters.5')
-rw-r--r-- | man/man5/zfs-module-parameters.5 | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/man/man5/zfs-module-parameters.5 b/man/man5/zfs-module-parameters.5 index 9462608f9..62245f6a0 100644 --- a/man/man5/zfs-module-parameters.5 +++ b/man/man5/zfs-module-parameters.5 @@ -271,6 +271,17 @@ Default value: \fB16,777,217\fR. .sp .ne 2 .na +\fBzfs_keep_log_spacemaps_at_export\fR (int) +.ad +.RS 12n +Prevent log spacemaps from being destroyed during pool exports and destroys. +.sp +Use \fB1\fR for yes and \fB0\fR for no (default). +.RE + +.sp +.ne 2 +.na \fBzfs_metaslab_segment_weight_enabled\fR (int) .ad .RS 12n @@ -373,6 +384,17 @@ Default value: \fB200\fR. .sp .ne 2 .na +\fBzfs_vdev_default_ms_shift\fR (int) +.ad +.RS 12n +Default limit for metaslab size. +.sp +Default value: \fB29\fR [meaning (1 << 29) = 512MB]. +.RE + +.sp +.ne 2 +.na \fBzfs_vdev_min_ms_count\fR (int) .ad .RS 12n @@ -1232,6 +1254,93 @@ Default value: 20 .sp .ne 2 .na +\fBzfs_unflushed_max_mem_amt\fR (ulong) +.ad +.RS 12n +Upper-bound limit for unflushed metadata changes to be held by the +log spacemap in memory (in bytes). +.sp +Default value: \fB1,073,741,824\fR (1GB). +.RE + +.sp +.ne 2 +.na +\fBzfs_unflushed_max_mem_ppm\fR (ulong) +.ad +.RS 12n +Percentage of the overall system memory that ZFS allows to be used +for unflushed metadata changes by the log spacemap. +(value is calculated over 1000000 for finer granularity). +.sp +Default value: \fB1000\fR (which is divided by 1000000, resulting in +the limit to be \fB0.1\fR% of memory) +.RE + +.sp +.ne 2 +.na +\fBzfs_unflushed_log_block_max\fR (ulong) +.ad +.RS 12n +Describes the maximum number of log spacemap blocks allowed for each pool. +The default value of 262144 means that the space in all the log spacemaps +can add up to no more than 262144 blocks (which means 32GB of logical +space before compression and ditto blocks, assuming that blocksize is +128k). +.sp +This tunable is important because it involves a trade-off between import +time after an unclean export and the frequency of flushing metaslabs. +The higher this number is, the more log blocks we allow when the pool is +active which means that we flush metaslabs less often and thus decrease +the number of I/Os for spacemap updates per TXG. +At the same time though, that means that in the event of an unclean export, +there will be more log spacemap blocks for us to read, inducing overhead +in the import time of the pool. +The lower the number, the amount of flushing increases destroying log +blocks quicker as they become obsolete faster, which leaves less blocks +to be read during import time after a crash. +.sp +Each log spacemap block existing during pool import leads to approximately +one extra logical I/O issued. +This is the reason why this tunable is exposed in terms of blocks rather +than space used. +.sp +Default value: \fB262144\fR (256K). +.RE + +.sp +.ne 2 +.na +\fBzfs_unflushed_log_block_min\fR (ulong) +.ad +.RS 12n +If the number of metaslabs is small and our incoming rate is high, we +could get into a situation that we are flushing all our metaslabs every +TXG. +Thus we always allow at least this many log blocks. +.sp +Default value: \fB1000\fR. +.RE + +.sp +.ne 2 +.na +\fBzfs_unflushed_log_block_pct\fR (ulong) +.ad +.RS 12n +Tunable used to determine the number of blocks that can be used for +the spacemap log, expressed as a percentage of the total number of +metaslabs in the pool. +.sp +Default value: \fB400\fR (read as \fB400\fR% - meaning that the number +of log spacemap blocks are capped at 4 times the number of +metaslabs in the pool). +.RE + +.sp +.ne 2 +.na \fBzfs_unlink_suspend_progress\fR (uint) .ad .RS 12n @@ -1717,6 +1826,10 @@ _ _ 2048 ZFS_DEBUG_TRIM Verify TRIM ranges are always within the allocatable range tree. +_ +4096 ZFS_DEBUG_LOG_SPACEMAP + Verify that the log summary is consistent with the spacemap log + and enable zfs_dbgmsgs for metaslab loading and flushing. .TE .sp * Requires debug build. @@ -1835,6 +1948,29 @@ Default value: \fB50\fR. .sp .ne 2 .na +\fBzfs_max_log_walking\fR (ulong) +.ad +.RS 12n +The number of past TXGs that the flushing algorithm of the log spacemap +feature uses to estimate incoming log blocks. +.sp +Default value: \fB5\fR. +.RE + +.sp +.ne 2 +.na +\fBzfs_max_logsm_summary_length\fR (ulong) +.ad +.RS 12n +Maximum number of rows allowed in the summary of the spacemap log. +.sp +Default value: \fB10\fR. +.RE + +.sp +.ne 2 +.na \fBzfs_max_recordsize\fR (int) .ad .RS 12n @@ -1865,6 +2001,17 @@ Default value: \fB0\fR. .sp .ne 2 .na +\fBzfs_min_metaslabs_to_flush\fR (ulong) +.ad +.RS 12n +Minimum number of metaslabs to flush per dirty TXG +.sp +Default value: \fB1\fR. +.RE + +.sp +.ne 2 +.na \fBzfs_metaslab_fragmentation_threshold\fR (int) .ad .RS 12n |