[PATCH] erofs-utils: lib: gzran: slightly improve the random performance
Gao Xiang
hsiangkao at linux.alibaba.com
Thu Oct 30 14:21:33 AEDT 2025
- Avoid reading overly long compressed data;
- Increase temporary buffer to keep inflight compressed data to 128k.
Cc: Chengyu Zhu <hudsonzhu at tencent.com>
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
lib/gzran.c | 38 ++++++++++++++++++++++++++------------
1 file changed, 26 insertions(+), 12 deletions(-)
diff --git a/lib/gzran.c b/lib/gzran.c
index 1136d04..0238d19 100644
--- a/lib/gzran.c
+++ b/lib/gzran.c
@@ -222,15 +222,24 @@ static ssize_t erofs_gzran_ios_vfpread(struct erofs_vfile *vf, void *buf, size_t
struct erofs_gzran_iostream *ios =
(struct erofs_gzran_iostream *)vf->payload;
struct erofs_gzran_cutpoint *cp = ios->cp;
- u8 src[1 << 14], discard[EROFS_GZRAN_WINSIZE];
- unsigned int bits;
+ u8 src[131072], discard[EROFS_GZRAN_WINSIZE];
+ union {
+ unsigned int bits, i;
+ } u;
bool skip = true;
- u64 inpos;
+ u64 inpos, remin;
z_stream strm;
int ret;
- while (cp < ios->cp + ios->entries - 1 && cp[1].outpos <= offset)
+ if (offset == ~0ULL) {
+ DBG_BUGON(1);
+ return -EIO;
+ }
+
+ while (cp[1].outpos <= offset)
++cp;
+ for (u.i = 1; cp[u.i].outpos < offset + len; ++u.i);
+ remin = (cp[u.i].in_bitpos >> 3) + !!(cp[u.i].in_bitpos & 7);
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
@@ -241,20 +250,21 @@ static ssize_t erofs_gzran_ios_vfpread(struct erofs_vfile *vf, void *buf, size_t
if (ret != Z_OK)
return -EFAULT;
- bits = cp->in_bitpos & 7;
- inpos = (cp->in_bitpos >> 3) - (bits ? 1 : 0);
- ret = erofs_io_pread(ios->vin, src, sizeof(src), inpos);
+ u.bits = cp->in_bitpos & 7;
+ inpos = (cp->in_bitpos >> 3) - (u.bits ? 1 : 0);
+ remin -= inpos;
+ ret = erofs_io_pread(ios->vin, src, min(remin, sizeof(src)), inpos);
if (ret < 0)
return ret;
-
- if (bits) {
- inflatePrime(&strm, bits, src[0] >> (8 - bits));
+ if (u.bits) {
+ inflatePrime(&strm, u.bits, src[0] >> (8 - u.bits));
strm.next_in = src + 1;
strm.avail_in = ret - 1;
} else {
strm.next_in = src;
strm.avail_in = ret;
}
+ remin -= ret;
inpos += ret;
(void)inflateSetDictionary(&strm, cp->window, sizeof(cp->window));
@@ -278,13 +288,15 @@ static ssize_t erofs_gzran_ios_vfpread(struct erofs_vfile *vf, void *buf, size_t
/* uncompress until avail_out filled, or end of stream */
do {
if (!strm.avail_in) {
- ret = erofs_io_pread(ios->vin, src, sizeof(src),
+ ret = erofs_io_pread(ios->vin, src,
+ min(remin, sizeof(src)),
inpos);
if (ret < 0)
return ret;
if (!ret)
return -EIO;
inpos += ret;
+ remin -= ret;
strm.avail_in = ret;
strm.next_in = src;
}
@@ -343,7 +355,7 @@ struct erofs_vfile *erofs_gzran_zinfo_open(struct erofs_vfile *vin,
goto err_ios;
}
- ios->cp = malloc(sizeof(*ios->cp) * ios->entries);
+ ios->cp = malloc(sizeof(*ios->cp) * (ios->entries + 1));
if (!ios->cp) {
ret = -ENOMEM;
goto err_ios;
@@ -364,6 +376,8 @@ struct erofs_vfile *erofs_gzran_zinfo_open(struct erofs_vfile *vin,
ios->cp[i].outpos = le64_to_cpu(c->out);
memcpy(ios->cp[i].window, c->window, sizeof(c->window));
}
+ ios->cp[i].in_bitpos = -1;
+ ios->cp[i].outpos = ~0ULL;
ios->vin = vin;
vf->ops = &erofs_gzran_ios_vfops;
return vf;
--
2.43.5
More information about the Linux-erofs
mailing list