Allow increasing the buffer-head per-CPU LRU size
PATCH 1/1 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.
--- fs/Kconfig | 9 +++++++++ fs/buffer.c | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-)
fs/Kconfig +9 -0
@@ -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
fs/buffer.c +0 -0
@@ -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];
Signature · 1 line
1.7.1
Hi,
two typos:
fs/Kconfig endif # NETWORK_FILESYSTEMS · line 277
Quoted 7 lines
fs/Kconfig +7
-0+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
^^^^^^^
fs/Kconfig endif # NETWORK_FILESYSTEMS · line 279
Quoted 2 lines
fs/Kconfig +2
-0+ within a single transaction, so keeping the buffer heads in + CPU-local cache speeds up modifations significantly.
^^^^^^
Thanks for this nice optimization,
Andreas Mohr
Quoted 5 lines · Sebastien Buisson
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
Signature · 1 line
[email protected] -- Speaking for myself only
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.
--- fs/Kconfig | 9 +++++++++ fs/buffer.c | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-)
fs/Kconfig +9 -0
@@ -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
fs/buffer.c +0 -0
@@ -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];
Signature · 1 line
1.7.1
Quoted 18 lines · Andi Kleen
Quoted 5 lines · Sebastien Buisson
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
fs/Kconfig endif # NETWORK_FILESYSTEMS · line 274
Quoted 12 lines
fs/Kconfig +4
-0@@ -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
Quoted 2 lines
config
BH_LARGE_LRU
bool
should be def_bool y
Quoted 9 lines
depends on (EXT4_FS && QUOTA)config
BH_LRU_SIZE
....
default "16" ifBH_LARGE_LRU
default "8" if !BH_LARGE_LRU-Andi
Signature · 1 line
[email protected] -- Speaking for myself only.
Quoted 21 lines · On Mon, 7 Jul 2014 18:30:03 +0200 Andi Kleen <[email protected]> wrote:
fs/Kconfig endif # NETWORK_FILESYSTEMS · line 274
Quoted 12 lines
fs/Kconfig +4
-0@@ -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.
Quoted 8 lines
config
BH_LARGE_LRUbool depends on (EXT4_FS && QUOTA)config
BH_LRU_SIZE
....
default "16" ifBH_LARGE_LRU
default "8" if !BH_LARGE_LRU
Can anyone demonstrate why we shouldn't just do
fs/buffer.c renamed from fs/buffer.c~a +1 -1
@@ -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 16struct bh_lru {struct buffer_head *bhs[BH_LRU_SIZE ];
_
Quoted 1 line
Can anyone demonstrate why we shouldn't just do
I was assuming due to memory usage: with 4K blocks 32K->64K
-Andi
Quoted 5 lines
Quoted 2 lines
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.
PATCH 1/1 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.
--- fs/Kconfig | 14 ++++++++++++++ fs/buffer.c | 3 +-- 2 files changed, 15 insertions(+), 2 deletions(-)
fs/Kconfig +14 -0
@@ -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
fs/buffer.c +0 -0
@@ -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];
Signature · 1 line
1.7.1
Quoted 14 lines · On Thu, 10 Jul 2014 08:51:17 +0200 Sebastien Buisson…
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)
Quoted 2 lines
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.
Quoted 10 lines
fs/Kconfig +4
-0@@ -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) +
fs/Kconfig endif # NETWORK_FILESYSTEMS · line 284
Quoted 10 lines
fs/Kconfig +10
-0+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"a 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.
fs/buffer.c static struct buffer_head *__bread_slow(struct · line 1255
Quoted 7 lines
fs/Kconfig +0
-0endmenufs/buffer.c +0
-0@@ -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.
Quoted 3 lines · Andrew Morton
This hardwires 16 if ext4"a 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.
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 9 lines · Sebastien Buisson
Quoted 3 lines · Andrew Morton
This hardwires 16 if ext4"a 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
Signature · 1 line
[email protected] -- Speaking for myself only.