From: Eric Dumazet <hidden> Date: 2011-07-26 08:21:12
Le mardi 26 juillet 2011 à 08:00 +0200, Eric Dumazet a écrit :
Next step is to not chain pipes/sockets into superblock s_inodes list
inode_sb_list_add()/inode_sb_list_del() is the very last contention
point because of spin_lock(&inode_sb_list_lock);
Well, not 'last' contention point, as we still hit remove_inode_hash(),
inode_wb_list_del(), inode_lru_list_del(), but thats a clear win on my
2x4x2 machine : 9 seconds instead of 22 on a close(socket()) benchmark.
[PATCH] vfs: dont chain pipe/anon/socket on superblock s_inodes list
Workloads using pipes and sockets hit inode_sb_list_lock contention.
superblock s_inodes list is needed for quota, dirty, pagecache and
fsnotify management. pipe/anon/socket fs are clearly not candidates for
these.
Signed-off-by: Eric Dumazet <redacted>
---
fs/anon_inodes.c | 2 +-
fs/inode.c | 31 +++++++++++++++++++++----------
fs/pipe.c | 2 +-
include/linux/fs.h | 3 ++-
net/socket.c | 2 +-
5 files changed, 26 insertions(+), 14 deletions(-)
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Christoph Hellwig <hch@infradead.org> Date: 2011-07-26 09:04:09
On Tue, Jul 26, 2011 at 10:21:06AM +0200, Eric Dumazet wrote:
Well, not 'last' contention point, as we still hit remove_inode_hash(),
There should be no ned to put pipe or anon inodes on the inode hash.
Probably sockets don't need it either, but I'd need to look at it in
detail.
inode_wb_list_del()
The should never be on the wb list either, doing an unlocked check for
actually beeing on the list before taking the lock should help you.
inode_lru_list_del(),
No real need to keep inodes in the LRU if we only allocate them using
new_inode but never look them up either. You might want to try setting
.drop_inode to generic_delete_inode for these.
This needs a much better name like new_inode_pseudo, and a kerneldoc
comment explaining when it is safe to use, and the consequences, which
appear to me:
- fs may never be unmount
- quotas can't work on the filesystem
- writeback can't work on the filesystem
From: Eric Dumazet <hidden> Date: 2011-07-26 09:36:34
Le mardi 26 juillet 2011 à 05:03 -0400, Christoph Hellwig a écrit :
On Tue, Jul 26, 2011 at 10:21:06AM +0200, Eric Dumazet wrote:
quoted
Well, not 'last' contention point, as we still hit remove_inode_hash(),
There should be no ned to put pipe or anon inodes on the inode hash.
Probably sockets don't need it either, but I'd need to look at it in
detail.
quoted
inode_wb_list_del()
The should never be on the wb list either, doing an unlocked check for
actually beeing on the list before taking the lock should help you.
Yes, it might even help regular inodes ;)
quoted
inode_lru_list_del(),
No real need to keep inodes in the LRU if we only allocate them using
new_inode but never look them up either. You might want to try setting
.drop_inode to generic_delete_inode for these.
This needs a much better name like new_inode_pseudo, and a kerneldoc
comment explaining when it is safe to use, and the consequences, which
appear to me:
- fs may never be unmount
- quotas can't work on the filesystem
- writeback can't work on the filesystem
Thanks for reviewing, here is v2 of the patch, addressing your comments.
[PATCH v2] vfs: dont chain pipe/anon/socket on superblock s_inodes list
Workloads using pipes and sockets hit inode_sb_list_lock contention.
superblock s_inodes list is needed for quota, dirty, pagecache and
fsnotify management. pipe/anon/socket fs are clearly not candidates for
these.
Signed-off-by: Eric Dumazet <redacted>
---
v2: address Christoph comments
fs/anon_inodes.c | 2 +-
fs/inode.c | 39 ++++++++++++++++++++++++++++++---------
fs/pipe.c | 2 +-
include/linux/fs.h | 3 ++-
net/socket.c | 2 +-
5 files changed, 35 insertions(+), 13 deletions(-)
From: Christoph Hellwig <hch@infradead.org> Date: 2011-07-26 09:42:10
On Tue, Jul 26, 2011 at 11:36:34AM +0200, Eric Dumazet wrote:
[PATCH v2] vfs: dont chain pipe/anon/socket on superblock s_inodes list
Workloads using pipes and sockets hit inode_sb_list_lock contention.
superblock s_inodes list is needed for quota, dirty, pagecache and
fsnotify management. pipe/anon/socket fs are clearly not candidates for
these.
Signed-off-by: Eric Dumazet <redacted>
Looks good to me,
Reviewed-by: Christoph Hellwig <hch@lst.de>
From: Eric Dumazet <hidden> Date: 2011-07-26 10:43:41
Le mardi 26 juillet 2011 à 05:42 -0400, Christoph Hellwig a écrit :
On Tue, Jul 26, 2011 at 11:36:34AM +0200, Eric Dumazet wrote:
quoted
[PATCH v2] vfs: dont chain pipe/anon/socket on superblock s_inodes list
Workloads using pipes and sockets hit inode_sb_list_lock contention.
superblock s_inodes list is needed for quota, dirty, pagecache and
fsnotify management. pipe/anon/socket fs are clearly not candidates for
these.
Signed-off-by: Eric Dumazet <redacted>
Looks good to me,
Reviewed-by: Christoph Hellwig <hch@lst.de>
Thanks !
BTW, we have one atomic op that could be avoided in new_inode()
spin_lock(&inode->i_lock);
inode->i_state = 0;
spin_unlock(&inode->i_lock);
can probably be changed to something less expensive...
inode->i_state = 0;
smp_wmb();
Not clear if we really need a memory barrier either....
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Christoph Hellwig <hch@infradead.org> Date: 2011-07-26 11:49:25
On Tue, Jul 26, 2011 at 12:43:33PM +0200, Eric Dumazet wrote:
BTW, we have one atomic op that could be avoided in new_inode()
spin_lock(&inode->i_lock);
inode->i_state = 0;
spin_unlock(&inode->i_lock);
can probably be changed to something less expensive...
inode->i_state = 0;
smp_wmb();
Not clear if we really need a memory barrier either....
I think we already had this in some of the earlier vfs/inode scale
series, but it got lost when Al asked to just put the fundamental
changes in.
For plain new_inode() the barrier shouldn't be needed as we take
the sb list lock just a little later. I'm not sure about your new
variant, so I'll rather lave that to you.
There's a few other things missing from earlier iterations, most notable
the non-atomic i_count, and the bucket locks for the inode hash, if
you're eager enough to look into that area.
From: Eric Dumazet <hidden> Date: 2011-07-27 15:21:10
Le mardi 26 juillet 2011 à 11:36 +0200, Eric Dumazet a écrit :
Le mardi 26 juillet 2011 à 05:03 -0400, Christoph Hellwig a écrit :
quoted
On Tue, Jul 26, 2011 at 10:21:06AM +0200, Eric Dumazet wrote:
quoted
Well, not 'last' contention point, as we still hit remove_inode_hash(),
There should be no ned to put pipe or anon inodes on the inode hash.
Probably sockets don't need it either, but I'd need to look at it in
detail.
quoted
inode_wb_list_del()
The should never be on the wb list either, doing an unlocked check for
actually beeing on the list before taking the lock should help you.
Yes, it might even help regular inodes ;)
quoted
quoted
inode_lru_list_del(),
No real need to keep inodes in the LRU if we only allocate them using
new_inode but never look them up either. You might want to try setting
.drop_inode to generic_delete_inode for these.
Yes, I'll take a look, thanks.
If I am not mistaken, we can add unlocked checks on the three hot spots.
After following patch, a close(socket(PF_INET, SOCK_DGRAM, 0)) pair on
my dev machine takes ~3us instead of ~9us.
Maybe its better to split it in three patches, just let me know.
22us -> 3us, thats a nice patch series ;)
Thanks
[PATCH] vfs: avoid taking locks if inode not in lists
sockets and pipes inodes destruction hits three possibly contended
locks :
system-wide inode_hash_lock in remove_inode_hash()
superblock s_inode_lru_lock in inode_lru_list_del()
bdi wb.list_lock in inode_wb_list_del()
Before even taking locks, we can perform an unlocked test to check if
inode can possibly be in the lists.
On a 2x4x2 machine, a close(socket()) pair can be 200% faster with these
changes.
Signed-off-by: Eric Dumazet <redacted>
---
fs/fs-writeback.c | 10 ++++++----
fs/inode.c | 6 ++++++
2 files changed, 12 insertions(+), 4 deletions(-)
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Before even taking locks, we can perform an unlocked test to check if
inode can possibly be in the lists.
On a 2x4x2 machine, a close(socket()) pair can be 200% faster with these
changes.
Great result! Seems simple and obvious to me.
-Andi
From: Christoph Hellwig <hch@infradead.org> Date: 2011-07-27 20:44:15
On Wed, Jul 27, 2011 at 05:21:05PM +0200, Eric Dumazet wrote:
If I am not mistaken, we can add unlocked checks on the three hot spots.
After following patch, a close(socket(PF_INET, SOCK_DGRAM, 0)) pair on
my dev machine takes ~3us instead of ~9us.
Maybe its better to split it in three patches, just let me know.
I think three patches would be a lot cleaner.
As for safety of the unlocked checks:
- inode are either hashed when created or never, so that one looks
fine.
- same for the sb list.
- the writeback list is a bit more dynamic as we move things around
quite a bit. But in additon to the inode_wb_list_del call from
evict() it only ever gets remove in writeback_single_inode, which
for a freeing inode can only be called from the callers of evict().
Btw, I wonder if you should micro-optimize things a bit further by
moving the unhashed checks from the deletion functions into the callers
and thus save a function call for each of them.
Btw, I wonder if you should micro-optimize things a bit further by
moving the unhashed checks from the deletion functions into the callers
and thus save a function call for each of them.
If the caller is in the same file modern gcc is able to do that automatically
if you're lucky enough ("partial inlining")
I would not uglify the code for it.
-Andi
--
ak@linux.intel.com -- Speaking for myself only.
From: Christoph Hellwig <hch@infradead.org> Date: 2011-07-27 21:01:04
On Wed, Jul 27, 2011 at 10:59:57PM +0200, Andi Kleen wrote:
quoted
Btw, I wonder if you should micro-optimize things a bit further by
moving the unhashed checks from the deletion functions into the callers
and thus save a function call for each of them.
If the caller is in the same file modern gcc is able to do that automatically
if you're lucky enough ("partial inlining")
I would not uglify the code for it.
Depending on how you look at it the code might actually be a tad
cleaner. One of called functions is outside of inode.c.
From: Eric Dumazet <hidden> Date: 2011-07-28 04:11:53
Le mercredi 27 juillet 2011 à 17:01 -0400, Christoph Hellwig a écrit :
On Wed, Jul 27, 2011 at 10:59:57PM +0200, Andi Kleen wrote:
quoted
quoted
Btw, I wonder if you should micro-optimize things a bit further by
moving the unhashed checks from the deletion functions into the callers
and thus save a function call for each of them.
If the caller is in the same file modern gcc is able to do that automatically
if you're lucky enough ("partial inlining")
I would not uglify the code for it.
Depending on how you look at it the code might actually be a tad
cleaner. One of called functions is outside of inode.c.
Thats right, thanks again for your valuable input Christoph.
The following is a clear win, since we avoid the call to external
function.
[PATCH] vfs: conditionally call inode_wb_list_del()
Some inodes (pipes, sockets, ...) are not in bdi writeback list.
evict() can avoid calling inode_wb_list_del() and its expensive spinlock
by checking inode i_wb_list being empty or not.
At this point, no other cpu/user can concurrently manipulate this inode
i_wb_list
Signed-off-by: Eric Dumazet <redacted>
---
fs/inode.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Eric Dumazet <hidden> Date: 2011-07-28 04:41:18
Le mercredi 27 juillet 2011 à 16:44 -0400, Christoph Hellwig a écrit :
On Wed, Jul 27, 2011 at 05:21:05PM +0200, Eric Dumazet wrote:
quoted
If I am not mistaken, we can add unlocked checks on the three hot spots.
After following patch, a close(socket(PF_INET, SOCK_DGRAM, 0)) pair on
my dev machine takes ~3us instead of ~9us.
Maybe its better to split it in three patches, just let me know.
I think three patches would be a lot cleaner.
As for safety of the unlocked checks:
- inode are either hashed when created or never, so that one looks
fine.
- same for the sb list.
- the writeback list is a bit more dynamic as we move things around
quite a bit. But in additon to the inode_wb_list_del call from
evict() it only ever gets remove in writeback_single_inode, which
for a freeing inode can only be called from the callers of evict().
Btw, I wonder if you should micro-optimize things a bit further by
moving the unhashed checks from the deletion functions into the callers
and thus save a function call for each of them.
What about following patch, addressing the micro-optimization and Andi
Kleen concern about evict() readability ?
Thanks !
[PATCH] vfs: avoid taking inode_hash_lock on pipes and sockets
Some inodes (pipes, sockets, ...) are not hashed, no need to take
contended inode_hash_lock at dismantle time.
nice speedup on SMP machines on socket intensive workloads.
Signed-off-by: Eric Dumazet <redacted>
---
fs/inode.c | 6 +++---
include/linux/fs.h | 9 ++++++++-
2 files changed, 11 insertions(+), 4 deletions(-)
@@ -2317,11 +2317,18 @@ extern int should_remove_suid(struct dentry *);externintfile_remove_suid(structfile*);externvoid__insert_inode_hash(structinode*,unsignedlonghashval);-externvoidremove_inode_hash(structinode*);staticinlinevoidinsert_inode_hash(structinode*inode){__insert_inode_hash(inode,inode->i_ino);}++externvoid__remove_inode_hash(structinode*);+staticinlinevoidremove_inode_hash(structinode*inode)+{+if(!inode_unhashed(inode))+__remove_inode_hash(inode);+}+externvoidinode_sb_list_add(structinode*inode);#ifdef CONFIG_BLOCK--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Eric Dumazet <hidden> Date: 2011-07-28 04:55:19
Le mercredi 27 juillet 2011 à 16:44 -0400, Christoph Hellwig a écrit :
On Wed, Jul 27, 2011 at 05:21:05PM +0200, Eric Dumazet wrote:
quoted
If I am not mistaken, we can add unlocked checks on the three hot spots.
After following patch, a close(socket(PF_INET, SOCK_DGRAM, 0)) pair on
my dev machine takes ~3us instead of ~9us.
Maybe its better to split it in three patches, just let me know.
I think three patches would be a lot cleaner.
As for safety of the unlocked checks:
- inode are either hashed when created or never, so that one looks
fine.
- same for the sb list.
- the writeback list is a bit more dynamic as we move things around
quite a bit. But in additon to the inode_wb_list_del call from
evict() it only ever gets remove in writeback_single_inode, which
for a freeing inode can only be called from the callers of evict().
Btw, I wonder if you should micro-optimize things a bit further by
moving the unhashed checks from the deletion functions into the callers
and thus save a function call for each of them.
Here is the last patch, addressing inode_lru_list_del() call.
Only the call done from iput_final() can obviously benefit from checking
i_lru being empty or not, so it makes sense to perform the check at
caller site instead of doing it in inode_lru_list_del()
[PATCH] vfs: avoid call to inode_lru_list_del() if possible
inode_lru_list_del() is expensive because of per superblock lru locking,
while some inodes are not in lru list.
Adding a check in iput_final() can speedup pipe/sockets workloads on
SMP.
Signed-off-by: Eric Dumazet <redacted>
---
fs/inode.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html