btrfs: Keep one more workspace around
authorNick Terrell <terrelln@fb.com>
Thu, 29 Jun 2017 17:57:26 +0000 (10:57 -0700)
committerDavid Sterba <dsterba@suse.com>
Wed, 16 Aug 2017 14:12:02 +0000 (16:12 +0200)
find_workspace() allocates up to num_online_cpus() + 1 workspaces.
free_workspace() will only keep num_online_cpus() workspaces. When
(de)compressing we will allocate num_online_cpus() + 1 workspaces, then
free one, and repeat. Instead, we can just keep num_online_cpus() + 1
workspaces around, and never have to allocate/free another workspace in the
common case.

I tested on a Ubuntu 14.04 VM with 2 cores and 4 GiB of RAM. I mounted a
BtrFS partition with -o compress-force={lzo,zlib,zstd} and logged whenever
a workspace was allocated of freed. Then I copied vmlinux (527 MB) to the
partition. Before the patch, during the copy it would allocate and free 5-6
workspaces. After, it only allocated the initial 3. This held true for lzo,
zlib, and zstd. The time it took to execute cp vmlinux /mnt/btrfs && sync
dropped from 1.70s to 1.44s with lzo compression, and from 2.04s to 1.80s
for zstd compression.

Signed-off-by: Nick Terrell <terrelln@fb.com>
Reviewed-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/compression.c

index d2ef9ac2a63038e279239012fdec7de0cf9573e3..3896bd0175ecaa27ec961d95c44ce3dea0426aa2 100644 (file)
@@ -825,7 +825,7 @@ static void free_workspace(int type, struct list_head *workspace)
        int *free_ws                    = &btrfs_comp_ws[idx].free_ws;
 
        spin_lock(ws_lock);
-       if (*free_ws < num_online_cpus()) {
+       if (*free_ws <= num_online_cpus()) {
                list_add(workspace, idle_ws);
                (*free_ws)++;
                spin_unlock(ws_lock);