Re: [PATCH] erofs: weaken full memory barriers to r/w barriers (update to test data)
Bingwu Zhang <[email protected]> Thu, 30 Jul 2026 17:54:26 +0800
| Newsgroups | org.ozlabs.lists.linux-erofs,org.kernel.vger.linux-kernel |
|---|---|
| Organization | AstraFall |
| Message-ID | <[email protected]> |
On Thursday, July 30, 2026 12:01:20=E2=80=AFPM China Standard Time Bingwu Z= hang wrote: > From: Bingwu Zhang <[email protected]> >=20 > fs/erofs/{xattr.c,zmap.c} both implemented one-time initialization locks > with general memory barriers. >=20 > Weaken these unnecessarily-strong general memory barriers to SMP > (ordering) read/write barriers for better performance on weakly-ordered > architectures. >=20 > Signed-off-by: Bingwu Zhang <[email protected]> > --- > (All test results below are done using QEMU with KVM; guest VM root FS > are mounted with v9fs; test target is an EROFS mounted on a loop device > backed by a file in tmpfs, in attempt to reduce error caused by physical > disks; mkfs flags: --zD=3D1 --all-root -zzstd -E48bit) >=20 > On x86-64, with x86-TSO, a full barrier lowers to a fence instruction and > read/write barriers are just compiler barriers. This patch removes > several fence instructions although they don't affect performance much. >=20 > On weakly-ordered architectures, a full memory barrier could be very > expensive. Thus, on these platforms, this patch saves more performance > than x86-64. >=20 > Test result on x86-64: > (host: AMD Ryzen 7 255 (@ 3.3GHz)) > (guest VM: ArchLinux, test data: linux.git/drivers @ commit fc02acf6ac0c) > Original: > read: IOPS=3D1684, BW=3D6737KiB/s (6899kB/s)(1006MiB/152838msec) > clat (usec): min=3D25, max=3D26293, avg=3D578.58, stdev=3D426.55 > lat (usec): min=3D25, max=3D26293, avg=3D578.70, stdev=3D426.56 > bw ( KiB/s): min=3D 1976, max=3D10904, per=3D100.00%, avg=3D6749.91, > stdev=3D1883.80, samples=3D305 > iops : min=3D 494, max=3D 2726, avg=3D1687.48, stdev=3D470.95, > samples=3D305 >=20 > New: > read: IOPS=3D1687, BW=3D6751KiB/s (6913kB/s)(1006MiB/152513msec) > clat (usec): min=3D25, max=3D19136, avg=3D577.00, stdev=3D425.66 > lat (usec): min=3D25, max=3D19136, avg=3D577.09, stdev=3D425.67 > bw ( KiB/s): min=3D 2192, max=3D11088, per=3D100.00%, avg=3D6770.26 > stdev=3D1870.55, samples=3D304 > iops : min=3D 548, max=3D 2772, avg=3D1692.44, stdev=3D467.65, > samples=3D304 >=20 > IOPS +0.17%, bandwidth +0.20%, max completion latency -27.22% note: this line might be inaccurate, too >=20 To clarify, the test result in the last email may be inaccurate. I repeated tests and got some updated data. This time I remembered to drop page caches between tests. On AArch64, for 4K randread, IOPS and bandwidth +1.5%, time -1.4% for 16K randread, IOPS and bandwidth +1.6%, time -1.5% Sorry for the misleading data in my last email. The data on ARM64 fluctuate= =20 greatly between tests and I was trying to get an average value. On x86-64, for 4K randread, IOPS, bandwidth and time are basically unchanged, while the max clat still -10.5% for unknown reasons (I don't think this pat= ch=20 could change so much on x86) I am not familiar with benchmarking and please let me know if I did anythin= g=20 wrong. Thanks! Best regards, Bingwu Zhang > Test result on ARM64: > (host: HUAWEI Kunpeng 920 @ 2.6GHz, both host & VM are AOSC OS) > (test data: > 1. AOSC OS: aosc-os_base_20260621_arm64.squashfs, /usr/bin directory is > repacked as EROFS. > 2. linux.git at commit fc02acf6ac0c, drivers/ subdirectory > ) > Original: > read: IOPS=3D12.3k, BW=3D47.9MiB/s (50.2MB/s)(1291MiB/26950msec) > clat (nsec): min=3D910, max=3D37500k, avg=3D56026.68, stdev=3D198628.= 59 > lat (nsec): min=3D960, max=3D37500k, avg=3D56167.70, stdev=3D198639.= 09 > bw ( KiB/s): min=3D 3888, max=3D94328, per=3D100.00%, avg=3D49790.64, > stdev=3D31594.09, samples=3D53 > iops : min=3D 972, max=3D23582, avg=3D12447.57, stdev=3D7898.5= 1, > samples=3D53 >=20 > New: > read: IOPS=3D13.8k, BW=3D54.0MiB/s (56.6MB/s)(1315MiB/24375msec) > clat (nsec): min=3D930, max=3D34271k, avg=3D53069.97, stdev=3D145651.= 76 > lat (nsec): min=3D980, max=3D34271k, avg=3D53221.68, stdev=3D145661.= 24 > bw ( KiB/s): min=3D 5843, max=3D95054, per=3D100.00%, avg=3D55988.58, > stdev=3D30477.44, samples=3D48 > iops : min=3D 1460, max=3D23763, avg=3D13997.00, stdev=3D7619.3= 7, > samples=3D48 >=20 > IOPS min +50.20%, avg +12.44% > bandwidth min +50.28%, max +0.76%, avg +12.44% > completion latency max -8.61%, avg -5.27% >=20 > I am not pretty sure why the minimum completion latencies vary so much on > AArch64. Even when I repeat the test with the same kernel without > rebooting/re-mounting, clat min fluctuates randomly, sometimes spiking to > over 1000 and sometimes dropping to as low as 2, but I think this patch > still improves the overall throughput performance. > --- > fs/erofs/xattr.c | 8 ++++---- > fs/erofs/zmap.c | 8 ++++---- > 2 files changed, 8 insertions(+), 8 deletions(-) >=20 > diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c > index df7ea019526d..0b252cfe616a 100644 > --- a/fs/erofs/xattr.c > +++ b/fs/erofs/xattr.c > @@ -44,10 +44,10 @@ static int erofs_init_inode_xattrs(struct inode *inod= e) > /* the most case is that xattrs of this inode are initialized. */ > if (test_bit(EROFS_I_EA_INITED_BIT, &vi->flags)) { > /* > - * paired with smp_mb() at the end of the function to=20 ensure > + * paired with smp_wmb() at the end of the function to=20 ensure > * fields will only be observed after the bit is set. > */ > - smp_mb(); > + smp_rmb(); > return 0; > } > if (wait_on_bit_lock(&vi->flags, EROFS_I_BL_XATTR_BIT,=20 TASK_KILLABLE)) > @@ -111,8 +111,8 @@ static int erofs_init_inode_xattrs(struct inode *inod= e) > vi->xattr_shared_xattrs[i] =3D le32_to_cpu(*xattr_id); > } >=20 > - /* paired with smp_mb() at the beginning of the function. */ > - smp_mb(); > + /* paired with smp_rmb() at the beginning of the function. */ > + smp_wmb(); > set_bit(EROFS_I_EA_INITED_BIT, &vi->flags); > out_unlock: > erofs_put_metabuf(&buf); > diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c > index 5811556a7b71..d5b001a537f4 100644 > --- a/fs/erofs/zmap.c > +++ b/fs/erofs/zmap.c > @@ -628,10 +628,10 @@ static int z_erofs_fill_inode(struct inode *inode, > struct erofs_map_blocks *map) >=20 > if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) { > /* > - * paired with smp_mb() at the end of the function to=20 ensure > + * paired with smp_wmb() at the end of the function to=20 ensure > * fields will only be observed after the bit is set. > */ > - smp_mb(); > + smp_rmb(); > return 0; > } >=20 > @@ -704,8 +704,8 @@ static int z_erofs_fill_inode(struct inode *inode, > struct erofs_map_blocks *map) goto out_unlock; > } > done: > - /* paired with smp_mb() at the beginning of the function */ > - smp_mb(); > + /* paired with smp_rmb() at the beginning of the function */ > + smp_wmb(); > set_bit(EROFS_I_Z_INITED_BIT, &vi->flags); > out_unlock: > clear_and_wake_up_bit(EROFS_I_BL_Z_BIT, &vi->flags); >=20 > --- > base-commit: 11028ab62899e4191e074ee364c712b77823a9c4 > change-id: 20260729-erofs-weaken-dbar-9fd2edff90e5 >=20 > Best regards, > -- > Bingwu Zhang <[email protected]>