2014-07-04 08:38:24

by Sebastien Buisson

[permalink] [raw]
Subject: [PATCH] Allow increasing the buffer-head per-CPU LRU size

Allow increasing the buffer-head per-CPU LRU size to allow efficient
filesystem operations that access many blocks for each transaction.
For example, creating a file in a large ext4 directory with quota
enabled will accesses multiple buffer heads and will overflow the LRU
at the default 8-block LRU size:

* parent directory inode table block (ctime, nlinks for subdirs)
* new inode bitmap
* inode table block
* 2 quota blocks
* directory leaf block (not reused, but pollutes one cache entry)
* 2 levels htree blocks (only one is reused, other pollutes cache)
* 2 levels indirect/index blocks (only one is reused)

The buffer-head per-CPU LRU size can be changed at config time, and its
default value is raised to 16.

Signed-off-by: Liang Zhen <[email protected]>
Signed-off-by: Andreas Dilger <[email protected]>
---
fs/Kconfig | 9 +++++++++
fs/buffer.c | 3 +--
2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index c229f82..afea808 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -268,4 +268,13 @@ endif # NETWORK_FILESYSTEMS
source "fs/nls/Kconfig"
source "fs/dlm/Kconfig"

+config BH_LRU_SIZE
+ int "buffer head per-CPU LRU size"
+ range 8 64
+ default "16"
+ help
+ This sets the per-CPU LRU size for buffer heads in memory.
+ More complex filesystems may be modiyfing multiple blocks
+ within a single transaction, so keeping the buffer heads in
+ CPU-local cache speeds up modifations significantly.
endmenu
diff --git a/fs/buffer.c b/fs/buffer.c
index 6024877..b83fa63 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1255,8 +1255,7 @@ static struct buffer_head *__bread_slow(struct
buffer_head *bh)
* The LRUs themselves only need locking against invalidate_bh_lrus.
We use
* a local interrupt disable for that.
*/
-
-#define BH_LRU_SIZE 8
+#define BH_LRU_SIZE CONFIG_BH_LRU_SIZE

struct bh_lru {
struct buffer_head *bhs[BH_LRU_SIZE];
--
1.7.1


2014-07-05 07:44:45

by Andreas Mohr

[permalink] [raw]
Subject: Re: [PATCH] Allow increasing the buffer-head per-CPU LRU size

Hi,

two typos:

> +config BH_LRU_SIZE
> + int "buffer head per-CPU LRU size"
> + range 8 64
> + default "16"
> + help
> + This sets the per-CPU LRU size for buffer heads in memory.
> + More complex filesystems may be modiyfing multiple blocks
^^^^^^^

> + within a single transaction, so keeping the buffer heads in
> + CPU-local cache speeds up modifations significantly.
^^^^^^

Thanks for this nice optimization,

Andreas Mohr

2014-07-06 16:18:14

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH] Allow increasing the buffer-head per-CPU LRU size

Sebastien Buisson <[email protected]> writes:

> Allow increasing the buffer-head per-CPU LRU size to allow efficient
> filesystem operations that access many blocks for each transaction.
> For example, creating a file in a large ext4 directory with quota
> enabled will accesses multiple buffer heads and will overflow the LRU
> at the default 8-block LRU size:

I don't think that should be a user visible config. Most users wouldn't
know how to set it. And Linux already has far too many obscure
config options.

Either make it set implicitely by the file system config.
Or just increase it unconditionally?

-Andi


--
[email protected] -- Speaking for myself only

2014-07-07 10:32:17

by Sebastien Buisson

[permalink] [raw]
Subject: Re: [PATCH] Allow increasing the buffer-head per-CPU LRU size

Allow increasing the buffer-head per-CPU LRU size to allow efficient
filesystem operations that access many blocks for each transaction.
For example, creating a file in a large ext4 directory with quota
enabled will accesses multiple buffer heads and will overflow the LRU
at the default 8-block LRU size:

* parent directory inode table block (ctime, nlinks for subdirs)
* new inode bitmap
* inode table block
* 2 quota blocks
* directory leaf block (not reused, but pollutes one cache entry)
* 2 levels htree blocks (only one is reused, other pollutes cache)
* 2 levels indirect/index blocks (only one is reused)

The buffer-head per-CPU LRU size can be changed at config time, and its
default value is raised to 16.

Signed-off-by: Liang Zhen <[email protected]>
Signed-off-by: Andreas Dilger <[email protected]>
---
fs/Kconfig | 9 +++++++++
fs/buffer.c | 3 +--
2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index c229f82..c08844c 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -268,4 +268,13 @@ endif # NETWORK_FILESYSTEMS
source "fs/nls/Kconfig"
source "fs/dlm/Kconfig"

+config BH_LRU_SIZE
+ int
+ range 8 64
+ default "16"
+ help
+ This sets the per-CPU LRU size for buffer heads in memory.
+ More complex filesystems may be modifying multiple blocks
+ within a single transaction, so keeping the buffer heads in
+ CPU-local cache speeds up modifications significantly.
endmenu
diff --git a/fs/buffer.c b/fs/buffer.c
index 6024877..b83fa63 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1255,8 +1255,7 @@ static struct buffer_head *__bread_slow(struct
buffer_head *bh)
* The LRUs themselves only need locking against invalidate_bh_lrus.
We use
* a local interrupt disable for that.
*/
-
-#define BH_LRU_SIZE 8
+#define BH_LRU_SIZE CONFIG_BH_LRU_SIZE

struct bh_lru {
struct buffer_head *bhs[BH_LRU_SIZE];
--
1.7.1



Le 06/07/2014 18:18, Andi Kleen a ?crit :
> Sebastien Buisson <[email protected]> writes:
>
>> Allow increasing the buffer-head per-CPU LRU size to allow efficient
>> filesystem operations that access many blocks for each transaction.
>> For example, creating a file in a large ext4 directory with quota
>> enabled will accesses multiple buffer heads and will overflow the LRU
>> at the default 8-block LRU size:
>
> I don't think that should be a user visible config. Most users wouldn't
> know how to set it. And Linux already has far too many obscure
> config options.
>
> Either make it set implicitely by the file system config.
> Or just increase it unconditionally?
>
> -Andi
>
>

2014-07-07 16:30:08

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH] Allow increasing the buffer-head per-CPU LRU size

> diff --git a/fs/Kconfig b/fs/Kconfig
> index c229f82..c08844c 100644
> --- a/fs/Kconfig
> +++ b/fs/Kconfig
> @@ -268,4 +268,13 @@ endif # NETWORK_FILESYSTEMS
> source "fs/nls/Kconfig"
> source "fs/dlm/Kconfig"
>
> +config BH_LRU_SIZE
> + int
> + range 8 64
> + default "16"

So who sets it then?

You need it for ext4 and quota right? So this combination
should set it at least. Something like (unested)

It would be also good to audit or test other file systems if they need the
same if that's possible.

config BH_LARGE_LRU
bool
depends on (EXT4_FS && QUOTA)

config BH_LRU_SIZE
....
default "16" if BH_LARGE_LRU
default "8" if !BH_LARGE_LRU

-Andi

2014-07-07 16:31:01

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH] Allow increasing the buffer-head per-CPU LRU size

> config BH_LARGE_LRU
> bool

should be def_bool y

> depends on (EXT4_FS && QUOTA)
>
> config BH_LRU_SIZE
> ....
> default "16" if BH_LARGE_LRU
> default "8" if !BH_LARGE_LRU
>
> -Andi
>

--
[email protected] -- Speaking for myself only.

2014-07-07 22:29:39

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] Allow increasing the buffer-head per-CPU LRU size

On Mon, 7 Jul 2014 18:30:03 +0200 Andi Kleen <[email protected]> wrote:

> > diff --git a/fs/Kconfig b/fs/Kconfig
> > index c229f82..c08844c 100644
> > --- a/fs/Kconfig
> > +++ b/fs/Kconfig
> > @@ -268,4 +268,13 @@ endif # NETWORK_FILESYSTEMS
> > source "fs/nls/Kconfig"
> > source "fs/dlm/Kconfig"
> >
> > +config BH_LRU_SIZE
> > + int
> > + range 8 64
> > + default "16"
>
> So who sets it then?
>
> You need it for ext4 and quota right? So this combination
> should set it at least. Something like (unested)
>
> It would be also good to audit or test other file systems if they need the
> same if that's possible.
>
> config BH_LARGE_LRU
> bool
> depends on (EXT4_FS && QUOTA)
>
> config BH_LRU_SIZE
> ....
> default "16" if BH_LARGE_LRU
> default "8" if !BH_LARGE_LRU

Can anyone demonstrate why we shouldn't just do

--- a/fs/buffer.c~a
+++ a/fs/buffer.c
@@ -1258,7 +1258,7 @@ static struct buffer_head *__bread_slow(
* a local interrupt disable for that.
*/

-#define BH_LRU_SIZE 8
+#define BH_LRU_SIZE 16

struct bh_lru {
struct buffer_head *bhs[BH_LRU_SIZE];
_

2014-07-07 22:46:38

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH] Allow increasing the buffer-head per-CPU LRU size

> Can anyone demonstrate why we shouldn't just do

I was assuming due to memory usage: with 4K blocks 32K->64K

-Andi

2014-07-08 06:28:16

by Sebastien Buisson

[permalink] [raw]
Subject: Re: [PATCH] Allow increasing the buffer-head per-CPU LRU size


>> Can anyone demonstrate why we shouldn't just do
>
> I was assuming due to memory usage: with 4K blocks 32K->64K
>

Moreover, performance gain was not that satisfactory on ext4 when
increasing BH_LRU_SIZE to 16.
Here are the performances I got with:
(a) mdtest on ramdisk device, single shared dir, with large ACL and SELinux
(b) mdtest on ramdisk device, single shared dir, with large ACL but NO
SELinux

(results show performance gain in percentage when increasing BH_LRU_SIZE
to 16)

(a)
files tasks dir size Creation Stat Removal
1000000 1 0 -8,7 -2,7 -0,5
1000000 1 100000 -5,2 -0,5 -1,1
1000000 1 500000 -5,1 -3,7 -1,5
1000000 1 2000000 -5,1 -4,0 -8,5
1000000 1 5000000 -4,2 -5,3 -10,2
1000000 1 10000000 -3,5 -8,0 -10,9
1000000 8 0 -0,3 -3,8 -1,2
1000000 8 100000 -1,2 -3,7 -1,5
1000000 8 500000 0,5 -3,2 -5,3
1000000 8 2000000 -1,7 -6,1 -8,7
1000000 8 5000000 -5,9 -7,7 -11,9
1000000 8 10000000 -4,1 -8,8 -13,6

(b)
files tasks dir size Creation Stat Removal
1000000 1 0 0,0 -0,9 -1,1
1000000 1 100000 1,0 -3,0 -3,5
1000000 1 500000 3,7 -3,0 -2,4
1000000 1 2000000 1,1 3,6 -0,2
1000000 1 5000000 3,5 0,1 5,9
1000000 1 10000000 9,0 3,8 6,4
1000000 8 0 2,4 -1,2 -4,3
1000000 8 100000 -0,2 -1,8 -2,4
1000000 8 500000 1,1 -0,3 2,0
1000000 8 2000000 -0,3 -2,8 -3,3
1000000 8 5000000 0,3 -3,1 -1,3
1000000 8 10000000 1,5 0,0 0,7


To compare with the performances I got on Lustre with:
(c) mds-survey on ramdisk device, quota enabled, shared directory
(d) mds-survey on ramdisk device, quota enabled, directory per process

(c)
fi dir threads create lookup destroy
1000000 1 1 11,3 1,2 7,2
1000000 1 2 6,4 2,3 6,9
1000000 1 4 1,9 3,0 1,3
1000000 1 8 -0,6 4,3 0,7
1000000 1 16 0,5 4,4 0,6

(d)
files dir threads create lookup destroy
1000000 4 4 3,2 28,5 5,3
1000000 8 8 1,2 33,9 2,0
1000000 16 16 0,6 7,9 -0,2


Sebastien.

2014-07-10 06:51:22

by Sebastien Buisson

[permalink] [raw]
Subject: [PATCH] Allow increasing the buffer-head per-CPU LRU size

Allow increasing the buffer-head per-CPU LRU size to allow efficient
filesystem operations that access many blocks for each transaction.
For example, creating a file in a large ext4 directory with quota
enabled will accesses multiple buffer heads and will overflow the LRU
at the default 8-block LRU size:

* parent directory inode table block (ctime, nlinks for subdirs)
* new inode bitmap
* inode table block
* 2 quota blocks
* directory leaf block (not reused, but pollutes one cache entry)
* 2 levels htree blocks (only one is reused, other pollutes cache)
* 2 levels indirect/index blocks (only one is reused)

The buffer-head per-CPU LRU size can be changed at config time, and its
default value is raised to 16.

Signed-off-by: Liang Zhen <[email protected]>
Signed-off-by: Andreas Dilger <[email protected]>
---
fs/Kconfig | 14 ++++++++++++++
fs/buffer.c | 3 +--
2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index c229f82..afbb6fa 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -268,4 +268,18 @@ endif # NETWORK_FILESYSTEMS
source "fs/nls/Kconfig"
source "fs/dlm/Kconfig"

+config BH_LARGE_LRU
+ def_bool y
+ depends on (EXT4_FS && QUOTA)
+
+config BH_LRU_SIZE
+ int
+ range 8 64
+ default "16" if BH_LARGE_LRU
+ default "8" if !BH_LARGE_LRU
+ help
+ This sets the per-CPU LRU size for buffer heads in memory.
+ More complex filesystems may be modifying multiple blocks
+ within a single transaction, so keeping the buffer heads in
+ CPU-local cache speeds up modifications significantly.
endmenu
diff --git a/fs/buffer.c b/fs/buffer.c
index 6024877..b83fa63 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1255,8 +1255,7 @@ static struct buffer_head *__bread_slow(struct
buffer_head *bh)
* The LRUs themselves only need locking against invalidate_bh_lrus.
We use
* a local interrupt disable for that.
*/
-
-#define BH_LRU_SIZE 8
+#define BH_LRU_SIZE CONFIG_BH_LRU_SIZE

struct bh_lru {
struct buffer_head *bhs[BH_LRU_SIZE];
--
1.7.1

2014-07-10 07:08:40

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] Allow increasing the buffer-head per-CPU LRU size

On Thu, 10 Jul 2014 08:51:17 +0200 Sebastien Buisson <[email protected]> wrote:

> Allow increasing the buffer-head per-CPU LRU size to allow efficient
> filesystem operations that access many blocks for each transaction.
> For example, creating a file in a large ext4 directory with quota
> enabled will accesses multiple buffer heads and will overflow the LRU
> at the default 8-block LRU size:
>
> * parent directory inode table block (ctime, nlinks for subdirs)
> * new inode bitmap
> * inode table block
> * 2 quota blocks
> * directory leaf block (not reused, but pollutes one cache entry)
> * 2 levels htree blocks (only one is reused, other pollutes cache)
> * 2 levels indirect/index blocks (only one is reused)
>
> The buffer-head per-CPU LRU size can be changed at config time, and its
> default value is raised to 16.

The patch is a performance optimisation but the changelog omits all
mention of the most important part: the magnitude of the performance
improvement.

> --- a/fs/Kconfig
> +++ b/fs/Kconfig
> @@ -268,4 +268,18 @@ endif # NETWORK_FILESYSTEMS
> source "fs/nls/Kconfig"
> source "fs/dlm/Kconfig"
>
> +config BH_LARGE_LRU
> + def_bool y
> + depends on (EXT4_FS && QUOTA)
> +
> +config BH_LRU_SIZE
> + int
> + range 8 64
> + default "16" if BH_LARGE_LRU
> + default "8" if !BH_LARGE_LRU
> + help
> + This sets the per-CPU LRU size for buffer heads in memory.
> + More complex filesystems may be modifying multiple blocks
> + within a single transaction, so keeping the buffer heads in
> + CPU-local cache speeds up modifications significantly.

This hardwires 16 if ext4&quota and 8 otherwise. There's no way for
anyone to alter this decision if they think it will be helpful (or
harmful) in their setup.

> endmenu
> diff --git a/fs/buffer.c b/fs/buffer.c
> index 6024877..b83fa63 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -1255,8 +1255,7 @@ static struct buffer_head *__bread_slow(struct
> buffer_head *bh)

Your email client is wordwrapping the patches btw. And it replaces
tabs with spaces.

2014-07-10 07:29:43

by Sebastien Buisson

[permalink] [raw]
Subject: Re: [PATCH] Allow increasing the buffer-head per-CPU LRU size


Le 10/07/2014 09:07, Andrew Morton a ?crit :
> This hardwires 16 if ext4&quota and 8 otherwise. There's no way for
> anyone to alter this decision if they think it will be helpful (or
> harmful) in their setup.

In fact I do not know how to let experienced people alter the value
without confusing the others with yet another obscure config option
(Andi's comment). I would welcome any suggestion to achieve this.

Many thanks,
Sebastien.

2014-07-10 14:17:27

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH] Allow increasing the buffer-head per-CPU LRU size

On Thu, Jul 10, 2014 at 09:29:39AM +0200, Sebastien Buisson wrote:
>
> Le 10/07/2014 09:07, Andrew Morton a ?crit :
> >This hardwires 16 if ext4&quota and 8 otherwise. There's no way for
> >anyone to alter this decision if they think it will be helpful (or
> >harmful) in their setup.
>
> In fact I do not know how to let experienced people alter the value
> without confusing the others with yet another obscure config option
> (Andi's comment). I would welcome any suggestion to achieve this.

I don't think we should generally expose it.

If someone really wants to experiment they can change the source.

-Andi

--
[email protected] -- Speaking for myself only.