From nobody Thu Apr 9 08:14:58 2026 Received: from mta22.hihonor.com (mta22.honor.com [81.70.192.198]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68E013A452A; Tue, 10 Mar 2026 03:11:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=81.70.192.198 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773112279; cv=none; b=pHyIjM3vocjs0ZlycTttPiw+mJuDZUF3+pjKLbpjKIhc1jxZ+cPe756Anfwh/ER9LdhsuTfIE/uXlQVG46G1jH65G4LDYs+lnTGA5Ll4dD2kJE3uZD6Htjhslhi8RDWqznCDn2JLb1p2DxbF3ij/24VdHD+D8YsPcPWEGB/G03A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773112279; c=relaxed/simple; bh=FrTNU9QqEgBesd8LSr5+k82rHCLewAx1intBK2YmK6g=; h=From:To:CC:Subject:Date:Message-ID:Content-Type:MIME-Version; b=HBLphpP8DclvwlTm6Bp7ZYlT4FDV3z/EsRlIe5paAGYxCXumnTMJ7EwragsB3wVcui9O6aV8KrjxHEqV2ugWt5ZhzGdAs/sWTnsU2XeqSOhqTFYelCpXPn2dee9blZSN7YHejasmjnfIPa8R6OJMy3xtp21Voj5PVeOMVtz6v5M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=honor.com; spf=pass smtp.mailfrom=honor.com; dkim=pass (1024-bit key) header.d=honor.com header.i=@honor.com header.b=O6hIAe4b; arc=none smtp.client-ip=81.70.192.198 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=honor.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=honor.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=honor.com header.i=@honor.com header.b="O6hIAe4b" dkim-signature: v=1; a=rsa-sha256; d=honor.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=To:From; bh=FrTNU9QqEgBesd8LSr5+k82rHCLewAx1intBK2YmK6g=; b=O6hIAe4bM3UFlR0SP9ukVwhhb4+Cobwzxc3oWuB0dcL2U17AC8vuEtixh/aHNpXoJaEhJTUnX BLFbkqtpreB2+0as7q1thbpRHf2P91auLJ0kLFxVeoAjP9EyoA3rAuSBdYXDrtgVXI5XFDhe7fr wtNIzE8LKTjCvEDu1Bf7ewM= Received: from w012.hihonor.com (unknown [10.68.27.189]) by mta22.hihonor.com (SkyGuard) with ESMTPS id 4fVJKR5nmnzYlkpW; Tue, 10 Mar 2026 10:50:51 +0800 (CST) Received: from a001.hihonor.com (10.68.28.182) by w012.hihonor.com (10.68.27.189) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.27; Tue, 10 Mar 2026 10:54:21 +0800 Received: from a008.hihonor.com (10.68.30.56) by a001.hihonor.com (10.68.28.182) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.27; Tue, 10 Mar 2026 10:54:21 +0800 Received: from a008.hihonor.com ([fe80::b6bf:fc6a:207:6851]) by a008.hihonor.com ([fe80::b6bf:fc6a:207:6851%6]) with mapi id 15.02.2562.027; Tue, 10 Mar 2026 10:54:21 +0800 From: gao xu To: Sergey Senozhatsky CC: Minchan Kim , Jens Axboe , "linux-block@vger.kernel.org" , "linux-kernel@vger.kernel.org" , Andrew Morton , "surenb@google.com" , zhouxiaolong Subject: zram: Optimize LZ4 dictionary compression performance Thread-Topic: zram: Optimize LZ4 dictionary compression performance Thread-Index: AdywM2pDLIO0gp5TQXuJ4OQmnHDBWQ== Date: Tue, 10 Mar 2026 02:54:20 +0000 Message-ID: Accept-Language: zh-CN, en-US Content-Language: zh-CN X-MS-Has-Attach: X-MS-TNEF-Correlator: Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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; }; =20 +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 =3D NULL; } =20 static int lz4_setup_params(struct zcomp_params *params) { + struct lz4_drv *drv; + if (params->level =3D=3D ZCOMP_PARAM_NOT_SET) params->level =3D LZ4_ACCELERATION_DEFAULT; =20 + drv =3D kzalloc_obj(drv, GFP_KERNEL); + if (!drv) + return -ENOMEM; + + drv->dict_gen =3D 0; + drv->base_c_valid =3D false; + + params->drv_data =3D drv; + return 0; } =20 @@ -67,10 +88,32 @@ static int lz4_create(struct zcomp_params *params, stru= ct zcomp_ctx *ctx) return -ENOMEM; } =20 +static int lz4_build_base_cstream(struct zcomp_params *params) +{ + struct lz4_drv *drv =3D params->drv_data; + int ret; + + if (!params->dict || !params->dict_sz) + return -EINVAL; + + memset(&drv->base_cstream, 0, sizeof(drv->base_cstream)); + + ret =3D LZ4_loadDict(&drv->base_cstream, + params->dict, params->dict_sz); + if (ret !=3D params->dict_sz) + return -EINVAL; + + drv->dict_gen =3D params->dict_gen; + drv->base_c_valid =3D true; + + return 0; +} + static int lz4_compress(struct zcomp_params *params, struct zcomp_ctx *ctx, struct zcomp_req *req) { struct lz4_ctx *zctx =3D ctx->context; + struct lz4_drv *drv =3D params->drv_data; int ret; =20 if (!zctx->cstrm) { @@ -78,10 +121,16 @@ static int lz4_compress(struct zcomp_params *params, s= truct 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 !=3D params->dict_gen) { + ret =3D lz4_build_base_cstream(params); + if (ret) + return ret; + } + /* Cstrm needs to be reset */ - ret =3D LZ4_loadDict(zctx->cstrm, params->dict, params->dict_sz); - if (ret !=3D params->dict_sz) - return -EINVAL; + memcpy(zctx->cstrm, &drv->base_cstream, + sizeof(*zctx->cstrm)); ret =3D 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 p= rio, s32 level, zram->params[prio].dict_sz =3D sz; zram->params[prio].level =3D level; zram->params[prio].deflate.winbits =3D deflate_params->winbits; + zram->params[prio].dict_gen++; return 0; } =20 --