From: gao xu <gaoxu2@honor.com>
To: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Minchan Kim <minchan@kernel.org>, Jens Axboe <axboe@kernel.dk>,
"linux-block@vger.kernel.org" <linux-block@vger.kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
"surenb@google.com" <surenb@google.com>,
zhouxiaolong <zhouxiaolong9@honor.com>
Subject: zram: Optimize LZ4 dictionary compression performance
Date: Tue, 10 Mar 2026 02:54:20 +0000 [thread overview]
Message-ID: <ae51966c3cb445e9983230243bb6a5b2@honor.com> (raw)
Calling `LZ4_loadDict()` repeatedly in Zram causes significant overhead
due to its internal dictionary pre-processing. This commit introduces a
template stream mechanism to pre-process the dictionary only once when
the dictionary is initially set or modified. It then efficiently copies
this state for subsequent compressions.
This optimization improves LZ4 dictionary compression performance by
over 50% in Zram I/O tests.
---
drivers/block/zram/backend_lz4.c | 55 ++++++++++++++++++++++++++++++--
drivers/block/zram/zcomp.h | 1 +
drivers/block/zram/zram_drv.c | 1 +
3 files changed, 54 insertions(+), 3 deletions(-)
diff --git a/drivers/block/zram/backend_lz4.c b/drivers/block/zram/backend_lz4.c
index 04e186614..b353f74a8 100644
--- a/drivers/block/zram/backend_lz4.c
+++ b/drivers/block/zram/backend_lz4.c
@@ -12,15 +12,36 @@ struct lz4_ctx {
LZ4_stream_t *cstrm;
};
+struct lz4_drv {
+ /* template compression stream with dictionary */
+ LZ4_stream_t base_cstream;
+ /* dictionary index of the current template */
+ u32 dict_gen;
+ bool base_c_valid;
+};
+
static void lz4_release_params(struct zcomp_params *params)
{
+ kfree(params->drv_data);
+ params->drv_data = NULL;
}
static int lz4_setup_params(struct zcomp_params *params)
{
+ struct lz4_drv *drv;
+
if (params->level == ZCOMP_PARAM_NOT_SET)
params->level = LZ4_ACCELERATION_DEFAULT;
+ drv = kzalloc_obj(drv, GFP_KERNEL);
+ if (!drv)
+ return -ENOMEM;
+
+ drv->dict_gen = 0;
+ drv->base_c_valid = false;
+
+ params->drv_data = drv;
+
return 0;
}
@@ -67,10 +88,32 @@ static int lz4_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
return -ENOMEM;
}
+static int lz4_build_base_cstream(struct zcomp_params *params)
+{
+ struct lz4_drv *drv = params->drv_data;
+ int ret;
+
+ if (!params->dict || !params->dict_sz)
+ return -EINVAL;
+
+ memset(&drv->base_cstream, 0, sizeof(drv->base_cstream));
+
+ ret = LZ4_loadDict(&drv->base_cstream,
+ params->dict, params->dict_sz);
+ if (ret != params->dict_sz)
+ return -EINVAL;
+
+ drv->dict_gen = params->dict_gen;
+ drv->base_c_valid = true;
+
+ return 0;
+}
+
static int lz4_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
struct zcomp_req *req)
{
struct lz4_ctx *zctx = ctx->context;
+ struct lz4_drv *drv = params->drv_data;
int ret;
if (!zctx->cstrm) {
@@ -78,10 +121,16 @@ static int lz4_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
req->dst_len, params->level,
zctx->mem);
} else {
+ /* rebuild base_cstream when the dictionary changes */
+ if (!drv->base_c_valid || drv->dict_gen != params->dict_gen) {
+ ret = lz4_build_base_cstream(params);
+ if (ret)
+ return ret;
+ }
+
/* Cstrm needs to be reset */
- ret = LZ4_loadDict(zctx->cstrm, params->dict, params->dict_sz);
- if (ret != params->dict_sz)
- return -EINVAL;
+ memcpy(zctx->cstrm, &drv->base_cstream,
+ sizeof(*zctx->cstrm));
ret = LZ4_compress_fast_continue(zctx->cstrm, req->src,
req->dst, req->src_len,
req->dst_len, params->level);
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
index eacfd3f7d..5b7ff9fdd 100644
--- a/drivers/block/zram/zcomp.h
+++ b/drivers/block/zram/zcomp.h
@@ -21,6 +21,7 @@ struct zcomp_params {
void *dict;
size_t dict_sz;
s32 level;
+ u32 dict_gen;
union {
struct deflate_params deflate;
};
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index bca33403f..f34f3fa43 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -1709,6 +1709,7 @@ static int comp_params_store(struct zram *zram, u32 prio, s32 level,
zram->params[prio].dict_sz = sz;
zram->params[prio].level = level;
zram->params[prio].deflate.winbits = deflate_params->winbits;
+ zram->params[prio].dict_gen++;
return 0;
}
--
next reply other threads:[~2026-03-10 3:11 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-10 2:54 gao xu [this message]
2026-03-10 5:39 ` zram: Optimize LZ4 dictionary compression performance Sergey Senozhatsky
2026-03-10 6:13 ` Sergey Senozhatsky
2026-03-10 6:22 ` Sergey Senozhatsky
2026-03-10 8:32 ` gao xu
2026-03-11 1:22 ` Sergey Senozhatsky
2026-03-11 2:55 ` gao xu
2026-03-10 6:15 ` Sergey Senozhatsky
2026-03-11 4:00 ` gao xu
2026-03-11 5:22 ` Sergey Senozhatsky
2026-03-11 1:25 ` Sergey Senozhatsky
2026-03-11 2:56 ` gao xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ae51966c3cb445e9983230243bb6a5b2@honor.com \
--to=gaoxu2@honor.com \
--cc=akpm@linux-foundation.org \
--cc=axboe@kernel.dk \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=minchan@kernel.org \
--cc=senozhatsky@chromium.org \
--cc=surenb@google.com \
--cc=zhouxiaolong9@honor.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox