Skip to content

Commit

Permalink
zio_compress: introduce compress_threshold
Browse files Browse the repository at this point in the history
Now default compression is lz4, which can stop
compression process by itself on incompressible data.
If there are additional size checks -
we will only make our compressratio worse.

New usable compression thresholds are:
- less than BPE_PAYLOAD_SIZE (embedded_data feature);
- at least one saved sector.

Old 12.5% threshold is left to minimize affect
on existing user expectations of CPU utilization.

If data wasn't compressed - it will be saved as
ZIO_COMPRESS_OFF, so if we really need to recompress
data without ashift info and check anything -
we can just compress it with zero threshold.
So, we don't need a new feature flag here!

Signed-off-by: George Melikov <[email protected]>
  • Loading branch information
gmelikov committed Feb 23, 2024
1 parent af4da5c commit a92226f
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 23 deletions.
3 changes: 2 additions & 1 deletion include/sys/zio_compress.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* Copyright (c) 2019, Klara Inc.
* Use is subject to license terms.
* Copyright (c) 2015, 2016 by Delphix. All rights reserved.
* Copyright (c) 2021 by George Melikov. All rights reserved.
*/

#ifndef _SYS_ZIO_COMPRESS_H
Expand Down Expand Up @@ -184,7 +185,7 @@ extern int lz4_decompress_zfs(void *src, void *dst, size_t s_len, size_t d_len,
* Compress and decompress data if necessary.
*/
extern size_t zio_compress_data(enum zio_compress c, abd_t *src, void **dst,
size_t s_len, uint8_t level);
size_t s_len, uint8_t level, int compress_threshold);
extern int zio_decompress_data(enum zio_compress c, abd_t *src, void *dst,
size_t s_len, size_t d_len, uint8_t *level);
extern int zio_decompress_data_buf(enum zio_compress c, void *src, void *dst,
Expand Down
26 changes: 18 additions & 8 deletions man/man7/zfsprops.7
Original file line number Diff line number Diff line change
Expand Up @@ -917,14 +917,24 @@ zeroes (the NUL byte).
When a zero-filled block is detected, it is stored as
a hole and not compressed using the indicated compression algorithm.
.Pp
Any block being compressed must be no larger than 7/8 of its original size
after compression, otherwise the compression will not be considered worthwhile
and the block saved uncompressed.
Note that when the logical block is less than
8 times the disk sector size this effectively reduces the necessary compression
ratio; for example, 8 KiB blocks on disks with 4 KiB disk sectors must compress
to 1/2
or less of their original size.
All blocks are allocated as a whole number of sectors
.Pq chunks of 2^ Ns Sy ashift No bytes , e.g . Sy 512B No or Sy 4KB .
Compression may result in a non-sector-aligned size, which will be rounded up
to a whole number of sectors.
If compression saves less than one whole sector,
the block will be stored uncompressed.
Therefore, blocks whose logical size is a small number of sectors will
experience less compression
(e.g. for
.Sy recordsize Ns = Ns Sy 16K
with
.Sy 4K
sectors, which have 4 sectors per block,
compression needs to save at least 25% to actually save space on disk).
.Pp
There is
.Sy 12.5%
default compression threshold in addition to sector rounding.
.It Xo
.Sy context Ns = Ns Sy none Ns | Ns
.Ar SELinux-User : Ns Ar SELinux-Role : Ns Ar SELinux-Type : Ns Ar Sensitivity-Level
Expand Down
9 changes: 6 additions & 3 deletions module/zfs/arc.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
* Copyright (c) 2019, Klara Inc.
* Copyright (c) 2019, Allan Jude
* Copyright (c) 2020, The FreeBSD Foundation [1]
* Copyright (c) 2021 by George Melikov. All rights reserved.
*
* [1] Portions of this software were developed by Allan Jude
* under sponsorship from the FreeBSD Foundation.
Expand Down Expand Up @@ -1786,7 +1787,7 @@ arc_hdr_authenticate(arc_buf_hdr_t *hdr, spa_t *spa, uint64_t dsobj)
!HDR_COMPRESSION_ENABLED(hdr)) {

csize = zio_compress_data(HDR_GET_COMPRESS(hdr),
hdr->b_l1hdr.b_pabd, &tmpbuf, lsize, hdr->b_complevel);
hdr->b_l1hdr.b_pabd, &tmpbuf, lsize, hdr->b_complevel, 0);
ASSERT3P(tmpbuf, !=, NULL);
ASSERT3U(csize, <=, psize);
abd = abd_get_from_buf(tmpbuf, lsize);
Expand Down Expand Up @@ -8945,7 +8946,7 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
tmp = abd_borrow_buf(cabd, bufsize);

psize = zio_compress_data(compress, to_write, &tmp, size,
hdr->b_complevel);
hdr->b_complevel, 0);

if (psize >= asize) {
psize = HDR_GET_PSIZE(hdr);
Expand All @@ -8957,6 +8958,7 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
abd_zero_off(to_write, psize, asize - psize);
goto encrypt;
}

ASSERT3U(psize, <=, HDR_GET_PSIZE(hdr));
if (psize < asize)
memset((char *)tmp + psize, 0, bufsize - psize);
Expand Down Expand Up @@ -10442,7 +10444,8 @@ l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio, l2arc_write_callback_t *cb)

/* try to compress the buffer */
psize = zio_compress_data(ZIO_COMPRESS_LZ4,
abd_buf->abd, (void **) &tmpbuf, sizeof (*lb), 0);
abd_buf->abd, (void **) &tmpbuf, sizeof (*lb), 0,
1 << dev->l2ad_vdev->vdev_ashift);

/* a log block is never entirely zero */
ASSERT(psize != 0);
Expand Down
5 changes: 3 additions & 2 deletions module/zfs/zio.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* Copyright (c) 2019, Klara Inc.
* Copyright (c) 2019, Allan Jude
* Copyright (c) 2021, Datto, Inc.
* Copyright (c) 2021 by George Melikov. All rights reserved.
*/

#include <sys/sysmacros.h>
Expand Down Expand Up @@ -1849,7 +1850,7 @@ zio_write_compress(zio_t *zio)
!(zio->io_flags & ZIO_FLAG_RAW_COMPRESS)) {
void *cbuf = NULL;
psize = zio_compress_data(compress, zio->io_abd, &cbuf, lsize,
zp->zp_complevel);
zp->zp_complevel, spa->spa_min_alloc);
if (psize == 0) {
compress = ZIO_COMPRESS_OFF;
} else if (psize >= lsize) {
Expand Down Expand Up @@ -1914,7 +1915,7 @@ zio_write_compress(zio_t *zio)
* to a hole.
*/
psize = zio_compress_data(ZIO_COMPRESS_EMPTY,
zio->io_abd, NULL, lsize, zp->zp_complevel);
zio->io_abd, NULL, lsize, zp->zp_complevel, 0);
if (psize == 0 || psize >= lsize)
compress = ZIO_COMPRESS_OFF;
} else if (zio->io_flags & ZIO_FLAG_RAW_COMPRESS &&
Expand Down
27 changes: 18 additions & 9 deletions module/zfs/zio_compress.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,11 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
*/

/*
* Copyright (c) 2013, 2018 by Delphix. All rights reserved.
* Copyright (c) 2019, Klara Inc.
* Copyright (c) 2019, Allan Jude
* Copyright (c) 2021 by George Melikov. All rights reserved.
*/

#include <sys/zfs_context.h>
Expand Down Expand Up @@ -124,9 +120,12 @@ zio_compress_zeroed_cb(void *data, size_t len, void *private)
return (0);
}

/*
* Set compress_threshold=0 for reproducibility of ARC checks.
*/
size_t
zio_compress_data(enum zio_compress c, abd_t *src, void **dst, size_t s_len,
uint8_t level)
uint8_t level, int compress_threshold)
{
size_t c_len, d_len;
uint8_t complevel;
Expand All @@ -145,8 +144,19 @@ zio_compress_data(enum zio_compress c, abd_t *src, void **dst, size_t s_len,
if (c == ZIO_COMPRESS_EMPTY)
return (s_len);

/* Compress at least 12.5% */
d_len = s_len - (s_len >> 3);
/*
* Usable compression thresholds are:
* - less than BPE_PAYLOAD_SIZE (embedded_data feature)
* - at least one saved sector
* - minimun 12.5% should be saved (legacy value)
*/
if (compress_threshold > 0) {
d_len = MAX(BPE_PAYLOAD_SIZE,
s_len - MAX(s_len % compress_threshold, s_len >> 3));
} else {
/* Special case for reproducibility of ARC checks */
d_len = s_len;
}

complevel = ci->ci_level;

Expand Down Expand Up @@ -174,7 +184,6 @@ zio_compress_data(enum zio_compress c, abd_t *src, void **dst, size_t s_len,
if (c_len > d_len)
return (s_len);

ASSERT3U(c_len, <=, d_len);
return (c_len);
}

Expand Down

0 comments on commit a92226f

Please sign in to comment.