* knfsd performance @ 2024-06-18 18:32 Trond Myklebust 2024-06-18 18:40 ` Chuck Lever III 2024-06-18 19:38 ` Jeff Layton 0 siblings, 2 replies; 26+ messages in thread From: Trond Myklebust @ 2024-06-18 18:32 UTC (permalink / raw) To: jlayton@kernel.org, neilb@suse.com, Chuck.Lever@oracle.com Cc: linux-nfs@vger.kernel.org [-- Attachment #1: Type: text/plain, Size: 769 bytes --] I recently back ported Neil's lwq code and sunrpc server changes to our 5.15.130 based kernel in the hope of improving the performance for our data servers. Our performance team recently ran a fio workload on a client that was doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection (infiniband) against that resulting server. I've attached the resulting flame graph from a perf profile run on the server side. Is anyone else seeing this massive contention for the spin lock in __lwq_dequeue? As you can see, it appears to be dwarfing all the other nfsd activity on the system in question here, being responsible for 45% of all the perf hits. -- Trond Myklebust Linux NFS client maintainer, Hammerspace trond.myklebust@hammerspace.com [-- Attachment #2: 5.15.130-200.pd.124.el8.x86_64.dsx.svg --] [-- Type: image/svg+xml, Size: 432471 bytes --] ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 18:32 knfsd performance Trond Myklebust @ 2024-06-18 18:40 ` Chuck Lever III 2024-06-18 19:29 ` Trond Myklebust 2024-06-18 19:38 ` Jeff Layton 1 sibling, 1 reply; 26+ messages in thread From: Chuck Lever III @ 2024-06-18 18:40 UTC (permalink / raw) To: Trond Myklebust Cc: jlayton@kernel.org, neilb@suse.com, Linux NFS Mailing List > On Jun 18, 2024, at 2:32 PM, Trond Myklebust <trondmy@hammerspace.com> wrote: > > I recently back ported Neil's lwq code and sunrpc server changes to our > 5.15.130 based kernel in the hope of improving the performance for our > data servers. > > Our performance team recently ran a fio workload on a client that was > doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection > (infiniband) against that resulting server. I've attached the resulting > flame graph from a perf profile run on the server side. > > Is anyone else seeing this massive contention for the spin lock in > __lwq_dequeue? As you can see, it appears to be dwarfing all the other > nfsd activity on the system in question here, being responsible for 45% > of all the perf hits. I haven't seen that, but I've been working on other issues. What's the nfsd thread count on your test server? Have you seen a similar impact on 6.10 kernels ? -- Chuck Lever ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 18:40 ` Chuck Lever III @ 2024-06-18 19:29 ` Trond Myklebust 2024-06-18 19:39 ` Chuck Lever III 0 siblings, 1 reply; 26+ messages in thread From: Trond Myklebust @ 2024-06-18 19:29 UTC (permalink / raw) To: chuck.lever@oracle.com Cc: linux-nfs@vger.kernel.org, jlayton@kernel.org, neilb@suse.com On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: > > > > On Jun 18, 2024, at 2:32 PM, Trond Myklebust > > <trondmy@hammerspace.com> wrote: > > > > I recently back ported Neil's lwq code and sunrpc server changes to > > our > > 5.15.130 based kernel in the hope of improving the performance for > > our > > data servers. > > > > Our performance team recently ran a fio workload on a client that > > was > > doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection > > (infiniband) against that resulting server. I've attached the > > resulting > > flame graph from a perf profile run on the server side. > > > > Is anyone else seeing this massive contention for the spin lock in > > __lwq_dequeue? As you can see, it appears to be dwarfing all the > > other > > nfsd activity on the system in question here, being responsible for > > 45% > > of all the perf hits. > > I haven't seen that, but I've been working on other issues. > > What's the nfsd thread count on your test server? Have you > seen a similar impact on 6.10 kernels ? > 640 knfsd threads. The machine was a supermicro 2029BT-HNR with 2xIntel 6150, 384GB of memory and 6xWDC SN840. Unfortunately, the machine was a loaner, so cannot compare to 6.10. That's why I was asking if anyone has seen anything similar. -- Trond Myklebust Linux NFS client maintainer, Hammerspace trond.myklebust@hammerspace.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 19:29 ` Trond Myklebust @ 2024-06-18 19:39 ` Chuck Lever III 2024-06-18 19:50 ` Trond Myklebust 0 siblings, 1 reply; 26+ messages in thread From: Chuck Lever III @ 2024-06-18 19:39 UTC (permalink / raw) To: Trond Myklebust Cc: Linux NFS Mailing List, jlayton@kernel.org, neilb@suse.com > On Jun 18, 2024, at 3:29 PM, Trond Myklebust <trondmy@hammerspace.com> wrote: > > On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: >> >> >>> On Jun 18, 2024, at 2:32 PM, Trond Myklebust >>> <trondmy@hammerspace.com> wrote: >>> >>> I recently back ported Neil's lwq code and sunrpc server changes to >>> our >>> 5.15.130 based kernel in the hope of improving the performance for >>> our >>> data servers. >>> >>> Our performance team recently ran a fio workload on a client that >>> was >>> doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection >>> (infiniband) against that resulting server. I've attached the >>> resulting >>> flame graph from a perf profile run on the server side. >>> >>> Is anyone else seeing this massive contention for the spin lock in >>> __lwq_dequeue? As you can see, it appears to be dwarfing all the >>> other >>> nfsd activity on the system in question here, being responsible for >>> 45% >>> of all the perf hits. >> >> I haven't seen that, but I've been working on other issues. >> >> What's the nfsd thread count on your test server? Have you >> seen a similar impact on 6.10 kernels ? >> > > 640 knfsd threads. The machine was a supermicro 2029BT-HNR with 2xIntel > 6150, 384GB of memory and 6xWDC SN840. > > Unfortunately, the machine was a loaner, so cannot compare to 6.10. > That's why I was asking if anyone has seen anything similar. If this system had more than one NUMA node, then using svc's "numa pool" mode might have helped. -- Chuck Lever ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 19:39 ` Chuck Lever III @ 2024-06-18 19:50 ` Trond Myklebust 2024-06-18 19:54 ` Chuck Lever III 0 siblings, 1 reply; 26+ messages in thread From: Trond Myklebust @ 2024-06-18 19:50 UTC (permalink / raw) To: chuck.lever@oracle.com Cc: linux-nfs@vger.kernel.org, jlayton@kernel.org, neilb@suse.com On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: > > > > On Jun 18, 2024, at 3:29 PM, Trond Myklebust > > <trondmy@hammerspace.com> wrote: > > > > On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: > > > > > > > > > > On Jun 18, 2024, at 2:32 PM, Trond Myklebust > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > I recently back ported Neil's lwq code and sunrpc server > > > > changes to > > > > our > > > > 5.15.130 based kernel in the hope of improving the performance > > > > for > > > > our > > > > data servers. > > > > > > > > Our performance team recently ran a fio workload on a client > > > > that > > > > was > > > > doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection > > > > (infiniband) against that resulting server. I've attached the > > > > resulting > > > > flame graph from a perf profile run on the server side. > > > > > > > > Is anyone else seeing this massive contention for the spin lock > > > > in > > > > __lwq_dequeue? As you can see, it appears to be dwarfing all > > > > the > > > > other > > > > nfsd activity on the system in question here, being responsible > > > > for > > > > 45% > > > > of all the perf hits. > > > > > > I haven't seen that, but I've been working on other issues. > > > > > > What's the nfsd thread count on your test server? Have you > > > seen a similar impact on 6.10 kernels ? > > > > > > > 640 knfsd threads. The machine was a supermicro 2029BT-HNR with > > 2xIntel > > 6150, 384GB of memory and 6xWDC SN840. > > > > Unfortunately, the machine was a loaner, so cannot compare to 6.10. > > That's why I was asking if anyone has seen anything similar. > > If this system had more than one NUMA node, then using > svc's "numa pool" mode might have helped. > Interesting. I had forgotten about that setting. Just out of curiosity, is there any reason why we might not want to default to that mode on a NUMA enabled system? -- Trond Myklebust Linux NFS client maintainer, Hammerspace trond.myklebust@hammerspace.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 19:50 ` Trond Myklebust @ 2024-06-18 19:54 ` Chuck Lever III 2024-06-18 20:16 ` Jeff Layton 2024-06-19 0:42 ` Dave Chinner 0 siblings, 2 replies; 26+ messages in thread From: Chuck Lever III @ 2024-06-18 19:54 UTC (permalink / raw) To: Trond Myklebust, Dave Chinner Cc: Linux NFS Mailing List, jlayton@kernel.org, neilb@suse.com > On Jun 18, 2024, at 3:50 PM, Trond Myklebust <trondmy@hammerspace.com> wrote: > > On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: >> >> >>> On Jun 18, 2024, at 3:29 PM, Trond Myklebust >>> <trondmy@hammerspace.com> wrote: >>> >>> On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: >>>> >>>> >>>>> On Jun 18, 2024, at 2:32 PM, Trond Myklebust >>>>> <trondmy@hammerspace.com> wrote: >>>>> >>>>> I recently back ported Neil's lwq code and sunrpc server >>>>> changes to >>>>> our >>>>> 5.15.130 based kernel in the hope of improving the performance >>>>> for >>>>> our >>>>> data servers. >>>>> >>>>> Our performance team recently ran a fio workload on a client >>>>> that >>>>> was >>>>> doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection >>>>> (infiniband) against that resulting server. I've attached the >>>>> resulting >>>>> flame graph from a perf profile run on the server side. >>>>> >>>>> Is anyone else seeing this massive contention for the spin lock >>>>> in >>>>> __lwq_dequeue? As you can see, it appears to be dwarfing all >>>>> the >>>>> other >>>>> nfsd activity on the system in question here, being responsible >>>>> for >>>>> 45% >>>>> of all the perf hits. >>>> >>>> I haven't seen that, but I've been working on other issues. >>>> >>>> What's the nfsd thread count on your test server? Have you >>>> seen a similar impact on 6.10 kernels ? >>>> >>> >>> 640 knfsd threads. The machine was a supermicro 2029BT-HNR with >>> 2xIntel >>> 6150, 384GB of memory and 6xWDC SN840. >>> >>> Unfortunately, the machine was a loaner, so cannot compare to 6.10. >>> That's why I was asking if anyone has seen anything similar. >> >> If this system had more than one NUMA node, then using >> svc's "numa pool" mode might have helped. >> > > Interesting. I had forgotten about that setting. > > Just out of curiosity, is there any reason why we might not want to > default to that mode on a NUMA enabled system? Can't think of one off hand. Maybe back in the day it was hard to tell when you were actually /on/ a NUMA system. Copying Dave to see if he has any recollection. -- Chuck Lever ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 19:54 ` Chuck Lever III @ 2024-06-18 20:16 ` Jeff Layton 2024-06-18 23:17 ` NeilBrown 2024-06-19 0:42 ` Dave Chinner 1 sibling, 1 reply; 26+ messages in thread From: Jeff Layton @ 2024-06-18 20:16 UTC (permalink / raw) To: Chuck Lever III, Trond Myklebust, Dave Chinner Cc: Linux NFS Mailing List, neilb@suse.com On Tue, 2024-06-18 at 19:54 +0000, Chuck Lever III wrote: > > > > On Jun 18, 2024, at 3:50 PM, Trond Myklebust > > <trondmy@hammerspace.com> wrote: > > > > On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: > > > > > > > > > > On Jun 18, 2024, at 3:29 PM, Trond Myklebust > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: > > > > > > > > > > > > > > > > On Jun 18, 2024, at 2:32 PM, Trond Myklebust > > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > I recently back ported Neil's lwq code and sunrpc server > > > > > > changes to > > > > > > our > > > > > > 5.15.130 based kernel in the hope of improving the > > > > > > performance > > > > > > for > > > > > > our > > > > > > data servers. > > > > > > > > > > > > Our performance team recently ran a fio workload on a > > > > > > client > > > > > > that > > > > > > was > > > > > > doing 100% NFSv3 reads in O_DIRECT mode over an RDMA > > > > > > connection > > > > > > (infiniband) against that resulting server. I've attached > > > > > > the > > > > > > resulting > > > > > > flame graph from a perf profile run on the server side. > > > > > > > > > > > > Is anyone else seeing this massive contention for the spin > > > > > > lock > > > > > > in > > > > > > __lwq_dequeue? As you can see, it appears to be dwarfing > > > > > > all > > > > > > the > > > > > > other > > > > > > nfsd activity on the system in question here, being > > > > > > responsible > > > > > > for > > > > > > 45% > > > > > > of all the perf hits. > > > > > > > > > > I haven't seen that, but I've been working on other issues. > > > > > > > > > > What's the nfsd thread count on your test server? Have you > > > > > seen a similar impact on 6.10 kernels ? > > > > > > > > > > > > > 640 knfsd threads. The machine was a supermicro 2029BT-HNR with > > > > 2xIntel > > > > 6150, 384GB of memory and 6xWDC SN840. > > > > > > > > Unfortunately, the machine was a loaner, so cannot compare to > > > > 6.10. > > > > That's why I was asking if anyone has seen anything similar. > > > > > > If this system had more than one NUMA node, then using > > > svc's "numa pool" mode might have helped. > > > > > > > Interesting. I had forgotten about that setting. > > > > Just out of curiosity, is there any reason why we might not want to > > default to that mode on a NUMA enabled system? > > Can't think of one off hand. Maybe back in the day it was > hard to tell when you were actually /on/ a NUMA system. > > Copying Dave to see if he has any recollection. > It's at least partly because of the klunkiness of the old pool_threads interface: You have to bring up the server first using the "threads" procfile, and then you can actually bring up threads in the various pools using pool_threads. Same for shutdown. You have to bring down the pool_threads first and then you can bring down the final thread and the rest of the server with it. Why it was designed this way, I have NFC. The new nfsdctl tool and netlink interfaces should make this simpler in the future. You'll be able to set the pool-mode in /etc/nfs.conf and configure a list of per-pool thread counts in there too. Once we have that, I think we'll be in a better position to consider doing it by default. Eventually we'd like to make the thread poos dynamic, at which point making that the default becomes much simpler from an administrative standpoint. -- Jeff Layton <jlayton@kernel.org> ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 20:16 ` Jeff Layton @ 2024-06-18 23:17 ` NeilBrown 2024-06-18 23:26 ` Chuck Lever III 0 siblings, 1 reply; 26+ messages in thread From: NeilBrown @ 2024-06-18 23:17 UTC (permalink / raw) To: Jeff Layton Cc: Chuck Lever III, Trond Myklebust, Dave Chinner, Linux NFS Mailing List On Wed, 19 Jun 2024, Jeff Layton wrote: > On Tue, 2024-06-18 at 19:54 +0000, Chuck Lever III wrote: > > > > > > > On Jun 18, 2024, at 3:50 PM, Trond Myklebust > > > <trondmy@hammerspace.com> wrote: > > > > > > On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: > > > > > > > > > > > > > On Jun 18, 2024, at 3:29 PM, Trond Myklebust > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: > > > > > > > > > > > > > > > > > > > On Jun 18, 2024, at 2:32 PM, Trond Myklebust > > > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > > > I recently back ported Neil's lwq code and sunrpc server > > > > > > > changes to > > > > > > > our > > > > > > > 5.15.130 based kernel in the hope of improving the > > > > > > > performance > > > > > > > for > > > > > > > our > > > > > > > data servers. > > > > > > > > > > > > > > Our performance team recently ran a fio workload on a > > > > > > > client > > > > > > > that > > > > > > > was > > > > > > > doing 100% NFSv3 reads in O_DIRECT mode over an RDMA > > > > > > > connection > > > > > > > (infiniband) against that resulting server. I've attached > > > > > > > the > > > > > > > resulting > > > > > > > flame graph from a perf profile run on the server side. > > > > > > > > > > > > > > Is anyone else seeing this massive contention for the spin > > > > > > > lock > > > > > > > in > > > > > > > __lwq_dequeue? As you can see, it appears to be dwarfing > > > > > > > all > > > > > > > the > > > > > > > other > > > > > > > nfsd activity on the system in question here, being > > > > > > > responsible > > > > > > > for > > > > > > > 45% > > > > > > > of all the perf hits. > > > > > > > > > > > > I haven't seen that, but I've been working on other issues. > > > > > > > > > > > > What's the nfsd thread count on your test server? Have you > > > > > > seen a similar impact on 6.10 kernels ? > > > > > > > > > > > > > > > > 640 knfsd threads. The machine was a supermicro 2029BT-HNR with > > > > > 2xIntel > > > > > 6150, 384GB of memory and 6xWDC SN840. > > > > > > > > > > Unfortunately, the machine was a loaner, so cannot compare to > > > > > 6.10. > > > > > That's why I was asking if anyone has seen anything similar. > > > > > > > > If this system had more than one NUMA node, then using > > > > svc's "numa pool" mode might have helped. > > > > > > > > > > Interesting. I had forgotten about that setting. > > > > > > Just out of curiosity, is there any reason why we might not want to > > > default to that mode on a NUMA enabled system? > > > > Can't think of one off hand. Maybe back in the day it was > > hard to tell when you were actually /on/ a NUMA system. > > > > Copying Dave to see if he has any recollection. > > > > It's at least partly because of the klunkiness of the old pool_threads > interface: You have to bring up the server first using the "threads" > procfile, and then you can actually bring up threads in the various > pools using pool_threads. > > Same for shutdown. You have to bring down the pool_threads first and > then you can bring down the final thread and the rest of the server > with it. Why it was designed this way, I have NFC. > > The new nfsdctl tool and netlink interfaces should make this simpler in > the future. You'll be able to set the pool-mode in /etc/nfs.conf and > configure a list of per-pool thread counts in there too. Once we have > that, I think we'll be in a better position to consider doing it by > default. > > Eventually we'd like to make the thread poos dynamic, at which point > making that the default becomes much simpler from an administrative > standpoint. I agree that dynamic thread pools will make numa management simpler. Greg Banks did the numa work for SGI - I wonder where he is now. He was at fastmail 10 years ago.. The idea was to bind network interfaces to numa nodes with interrupt routing. There was no expectation that work would be distributed evenly across all nodes. Some might be dedicated to non-nfs work. So there was expected to be non-trivial configuration for both IRQ routing and threads-per-node. If we can make threads-per-node demand-based, then half the problem goes away. We could even default to one-thread-pool-per-CPU if there are more than X cpus.... NeilBrown ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 23:17 ` NeilBrown @ 2024-06-18 23:26 ` Chuck Lever III 2024-06-18 23:33 ` Jeff Layton 2024-06-19 2:56 ` Dave Chinner 0 siblings, 2 replies; 26+ messages in thread From: Chuck Lever III @ 2024-06-18 23:26 UTC (permalink / raw) To: Neil Brown Cc: Jeff Layton, Trond Myklebust, Dave Chinner, Linux NFS Mailing List > On Jun 18, 2024, at 7:17 PM, NeilBrown <neilb@suse.de> wrote: > > On Wed, 19 Jun 2024, Jeff Layton wrote: >> On Tue, 2024-06-18 at 19:54 +0000, Chuck Lever III wrote: >>> >>> >>>> On Jun 18, 2024, at 3:50 PM, Trond Myklebust >>>> <trondmy@hammerspace.com> wrote: >>>> >>>> On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: >>>>> >>>>> >>>>>> On Jun 18, 2024, at 3:29 PM, Trond Myklebust >>>>>> <trondmy@hammerspace.com> wrote: >>>>>> >>>>>> On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: >>>>>>> >>>>>>> >>>>>>>> On Jun 18, 2024, at 2:32 PM, Trond Myklebust >>>>>>>> <trondmy@hammerspace.com> wrote: >>>>>>>> >>>>>>>> I recently back ported Neil's lwq code and sunrpc server >>>>>>>> changes to >>>>>>>> our >>>>>>>> 5.15.130 based kernel in the hope of improving the >>>>>>>> performance >>>>>>>> for >>>>>>>> our >>>>>>>> data servers. >>>>>>>> >>>>>>>> Our performance team recently ran a fio workload on a >>>>>>>> client >>>>>>>> that >>>>>>>> was >>>>>>>> doing 100% NFSv3 reads in O_DIRECT mode over an RDMA >>>>>>>> connection >>>>>>>> (infiniband) against that resulting server. I've attached >>>>>>>> the >>>>>>>> resulting >>>>>>>> flame graph from a perf profile run on the server side. >>>>>>>> >>>>>>>> Is anyone else seeing this massive contention for the spin >>>>>>>> lock >>>>>>>> in >>>>>>>> __lwq_dequeue? As you can see, it appears to be dwarfing >>>>>>>> all >>>>>>>> the >>>>>>>> other >>>>>>>> nfsd activity on the system in question here, being >>>>>>>> responsible >>>>>>>> for >>>>>>>> 45% >>>>>>>> of all the perf hits. >>>>>>> >>>>>>> I haven't seen that, but I've been working on other issues. >>>>>>> >>>>>>> What's the nfsd thread count on your test server? Have you >>>>>>> seen a similar impact on 6.10 kernels ? >>>>>>> >>>>>> >>>>>> 640 knfsd threads. The machine was a supermicro 2029BT-HNR with >>>>>> 2xIntel >>>>>> 6150, 384GB of memory and 6xWDC SN840. >>>>>> >>>>>> Unfortunately, the machine was a loaner, so cannot compare to >>>>>> 6.10. >>>>>> That's why I was asking if anyone has seen anything similar. >>>>> >>>>> If this system had more than one NUMA node, then using >>>>> svc's "numa pool" mode might have helped. >>>>> >>>> >>>> Interesting. I had forgotten about that setting. >>>> >>>> Just out of curiosity, is there any reason why we might not want to >>>> default to that mode on a NUMA enabled system? >>> >>> Can't think of one off hand. Maybe back in the day it was >>> hard to tell when you were actually /on/ a NUMA system. >>> >>> Copying Dave to see if he has any recollection. >>> >> >> It's at least partly because of the klunkiness of the old pool_threads >> interface: You have to bring up the server first using the "threads" >> procfile, and then you can actually bring up threads in the various >> pools using pool_threads. >> >> Same for shutdown. You have to bring down the pool_threads first and >> then you can bring down the final thread and the rest of the server >> with it. Why it was designed this way, I have NFC. >> >> The new nfsdctl tool and netlink interfaces should make this simpler in >> the future. You'll be able to set the pool-mode in /etc/nfs.conf and >> configure a list of per-pool thread counts in there too. Once we have >> that, I think we'll be in a better position to consider doing it by >> default. >> >> Eventually we'd like to make the thread poos dynamic, at which point >> making that the default becomes much simpler from an administrative >> standpoint. > > I agree that dynamic thread pools will make numa management simpler. > Greg Banks did the numa work for SGI - I wonder where he is now. He was > at fastmail 10 years ago.. Dave (cc'd) designed it with Greg, Greg implemented it. > The idea was to bind network interfaces to numa nodes with interrupt > routing. There was no expectation that work would be distributed evenly > across all nodes. Some might be dedicated to non-nfs work. So there was > expected to be non-trivial configuration for both IRQ routing and > threads-per-node. If we can make threads-per-node demand-based, then > half the problem goes away. Network devices (and storage devices) are affined to one NUMA node. If the nfsd threads are not on the same node as the network device, there is a significant penalty. I have a two-node system here, and it performs consistently well when I put it in pool-mode=numa and affine the network device's IRQs to one node. It even works with two network devices (one per node) -- each device gets its own set of nfsd threads. I don't think the pool_mode needs to be demand based. If the system is a NUMA system, it makes sense to split up the thread pools and put our pencils down. The only other step that is needed is proper IRQ affinity settings for the network devices. > We could even default to one-thread-pool-per-CPU if there are more than > X cpus.... I've never seen a performance improvement in the per-cpu pool mode, fwiw. -- Chuck Lever ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 23:26 ` Chuck Lever III @ 2024-06-18 23:33 ` Jeff Layton 2024-06-18 23:51 ` Chuck Lever III 2024-06-19 2:56 ` Dave Chinner 1 sibling, 1 reply; 26+ messages in thread From: Jeff Layton @ 2024-06-18 23:33 UTC (permalink / raw) To: Chuck Lever III, Neil Brown Cc: Trond Myklebust, Dave Chinner, Linux NFS Mailing List On Tue, 2024-06-18 at 23:26 +0000, Chuck Lever III wrote: > > > On Jun 18, 2024, at 7:17 PM, NeilBrown <neilb@suse.de> wrote: > > > > On Wed, 19 Jun 2024, Jeff Layton wrote: > > > On Tue, 2024-06-18 at 19:54 +0000, Chuck Lever III wrote: > > > > > > > > > > > > > On Jun 18, 2024, at 3:50 PM, Trond Myklebust > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: > > > > > > > > > > > > > > > > > > > On Jun 18, 2024, at 3:29 PM, Trond Myklebust > > > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > > > On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: > > > > > > > > > > > > > > > > > > > > > > > > > On Jun 18, 2024, at 2:32 PM, Trond Myklebust > > > > > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > > > > > > > I recently back ported Neil's lwq code and sunrpc server > > > > > > > > > changes to > > > > > > > > > our > > > > > > > > > 5.15.130 based kernel in the hope of improving the > > > > > > > > > performance > > > > > > > > > for > > > > > > > > > our > > > > > > > > > data servers. > > > > > > > > > > > > > > > > > > Our performance team recently ran a fio workload on a > > > > > > > > > client > > > > > > > > > that > > > > > > > > > was > > > > > > > > > doing 100% NFSv3 reads in O_DIRECT mode over an RDMA > > > > > > > > > connection > > > > > > > > > (infiniband) against that resulting server. I've attached > > > > > > > > > the > > > > > > > > > resulting > > > > > > > > > flame graph from a perf profile run on the server side. > > > > > > > > > > > > > > > > > > Is anyone else seeing this massive contention for the spin > > > > > > > > > lock > > > > > > > > > in > > > > > > > > > __lwq_dequeue? As you can see, it appears to be dwarfing > > > > > > > > > all > > > > > > > > > the > > > > > > > > > other > > > > > > > > > nfsd activity on the system in question here, being > > > > > > > > > responsible > > > > > > > > > for > > > > > > > > > 45% > > > > > > > > > of all the perf hits. > > > > > > > > > > > > > > > > I haven't seen that, but I've been working on other issues. > > > > > > > > > > > > > > > > What's the nfsd thread count on your test server? Have you > > > > > > > > seen a similar impact on 6.10 kernels ? > > > > > > > > > > > > > > > > > > > > > > 640 knfsd threads. The machine was a supermicro 2029BT-HNR with > > > > > > > 2xIntel > > > > > > > 6150, 384GB of memory and 6xWDC SN840. > > > > > > > > > > > > > > Unfortunately, the machine was a loaner, so cannot compare to > > > > > > > 6.10. > > > > > > > That's why I was asking if anyone has seen anything similar. > > > > > > > > > > > > If this system had more than one NUMA node, then using > > > > > > svc's "numa pool" mode might have helped. > > > > > > > > > > > > > > > > Interesting. I had forgotten about that setting. > > > > > > > > > > Just out of curiosity, is there any reason why we might not want to > > > > > default to that mode on a NUMA enabled system? > > > > > > > > Can't think of one off hand. Maybe back in the day it was > > > > hard to tell when you were actually /on/ a NUMA system. > > > > > > > > Copying Dave to see if he has any recollection. > > > > > > > > > > It's at least partly because of the klunkiness of the old pool_threads > > > interface: You have to bring up the server first using the "threads" > > > procfile, and then you can actually bring up threads in the various > > > pools using pool_threads. > > > > > > Same for shutdown. You have to bring down the pool_threads first and > > > then you can bring down the final thread and the rest of the server > > > with it. Why it was designed this way, I have NFC. > > > > > > The new nfsdctl tool and netlink interfaces should make this simpler in > > > the future. You'll be able to set the pool-mode in /etc/nfs.conf and > > > configure a list of per-pool thread counts in there too. Once we have > > > that, I think we'll be in a better position to consider doing it by > > > default. > > > > > > Eventually we'd like to make the thread poos dynamic, at which point > > > making that the default becomes much simpler from an administrative > > > standpoint. > > > > I agree that dynamic thread pools will make numa management simpler. > > Greg Banks did the numa work for SGI - I wonder where he is now. He was > > at fastmail 10 years ago.. > > Dave (cc'd) designed it with Greg, Greg implemented it. > > > > The idea was to bind network interfaces to numa nodes with interrupt > > routing. There was no expectation that work would be distributed evenly > > across all nodes. Some might be dedicated to non-nfs work. So there was > > expected to be non-trivial configuration for both IRQ routing and > > threads-per-node. If we can make threads-per-node demand-based, then > > half the problem goes away. > > Network devices (and storage devices) are affined to one > NUMA node. If the nfsd threads are not on the same node > as the network device, there is a significant penalty. > > I have a two-node system here, and it performs consistently > well when I put it in pool-mode=numa and affine the network > device's IRQs to one node. > > It even works with two network devices (one per node) -- > each device gets its own set of nfsd threads. > > I don't think the pool_mode needs to be demand based. If > the system is a NUMA system, it makes sense to split up > the thread pools and put our pencils down. The only other > step that is needed is proper IRQ affinity settings for > the network devices. > Having them be demand-based is a nice-to-have. Right now, you need to know how many thread pools (it's not always trivial to tell) and you have and decide how many threads each gets. There is some cost to getting that wrong too. An on-demand thread pool takes a lot of the guesswork out of the equation (assuming we can get the behavior right, of course). > > > We could even default to one-thread-pool-per-CPU if there are more than > > X cpus.... > > I've never seen a performance improvement in the per-cpu > pool mode, fwiw. > > > -- > Chuck Lever > > -- Jeff Layton <jlayton@kernel.org> ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 23:33 ` Jeff Layton @ 2024-06-18 23:51 ` Chuck Lever III 0 siblings, 0 replies; 26+ messages in thread From: Chuck Lever III @ 2024-06-18 23:51 UTC (permalink / raw) To: Jeff Layton Cc: Neil Brown, Trond Myklebust, Dave Chinner, Linux NFS Mailing List > On Jun 18, 2024, at 7:33 PM, Jeff Layton <jlayton@kernel.org> wrote: > > On Tue, 2024-06-18 at 23:26 +0000, Chuck Lever III wrote: >> >>> On Jun 18, 2024, at 7:17 PM, NeilBrown <neilb@suse.de> wrote: >>> >>> On Wed, 19 Jun 2024, Jeff Layton wrote: >>>> On Tue, 2024-06-18 at 19:54 +0000, Chuck Lever III wrote: >>>>> >>>>> >>>>>> On Jun 18, 2024, at 3:50 PM, Trond Myklebust >>>>>> <trondmy@hammerspace.com> wrote: >>>>>> >>>>>> On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: >>>>>>> >>>>>>> >>>>>>>> On Jun 18, 2024, at 3:29 PM, Trond Myklebust >>>>>>>> <trondmy@hammerspace.com> wrote: >>>>>>>> >>>>>>>> On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: >>>>>>>>> >>>>>>>>> >>>>>>>>>> On Jun 18, 2024, at 2:32 PM, Trond Myklebust >>>>>>>>>> <trondmy@hammerspace.com> wrote: >>>>>>>>>> >>>>>>>>>> I recently back ported Neil's lwq code and sunrpc server >>>>>>>>>> changes to >>>>>>>>>> our >>>>>>>>>> 5.15.130 based kernel in the hope of improving the >>>>>>>>>> performance >>>>>>>>>> for >>>>>>>>>> our >>>>>>>>>> data servers. >>>>>>>>>> >>>>>>>>>> Our performance team recently ran a fio workload on a >>>>>>>>>> client >>>>>>>>>> that >>>>>>>>>> was >>>>>>>>>> doing 100% NFSv3 reads in O_DIRECT mode over an RDMA >>>>>>>>>> connection >>>>>>>>>> (infiniband) against that resulting server. I've attached >>>>>>>>>> the >>>>>>>>>> resulting >>>>>>>>>> flame graph from a perf profile run on the server side. >>>>>>>>>> >>>>>>>>>> Is anyone else seeing this massive contention for the spin >>>>>>>>>> lock >>>>>>>>>> in >>>>>>>>>> __lwq_dequeue? As you can see, it appears to be dwarfing >>>>>>>>>> all >>>>>>>>>> the >>>>>>>>>> other >>>>>>>>>> nfsd activity on the system in question here, being >>>>>>>>>> responsible >>>>>>>>>> for >>>>>>>>>> 45% >>>>>>>>>> of all the perf hits. >>>>>>>>> >>>>>>>>> I haven't seen that, but I've been working on other issues. >>>>>>>>> >>>>>>>>> What's the nfsd thread count on your test server? Have you >>>>>>>>> seen a similar impact on 6.10 kernels ? >>>>>>>>> >>>>>>>> >>>>>>>> 640 knfsd threads. The machine was a supermicro 2029BT-HNR with >>>>>>>> 2xIntel >>>>>>>> 6150, 384GB of memory and 6xWDC SN840. >>>>>>>> >>>>>>>> Unfortunately, the machine was a loaner, so cannot compare to >>>>>>>> 6.10. >>>>>>>> That's why I was asking if anyone has seen anything similar. >>>>>>> >>>>>>> If this system had more than one NUMA node, then using >>>>>>> svc's "numa pool" mode might have helped. >>>>>>> >>>>>> >>>>>> Interesting. I had forgotten about that setting. >>>>>> >>>>>> Just out of curiosity, is there any reason why we might not want to >>>>>> default to that mode on a NUMA enabled system? >>>>> >>>>> Can't think of one off hand. Maybe back in the day it was >>>>> hard to tell when you were actually /on/ a NUMA system. >>>>> >>>>> Copying Dave to see if he has any recollection. >>>>> >>>> >>>> It's at least partly because of the klunkiness of the old pool_threads >>>> interface: You have to bring up the server first using the "threads" >>>> procfile, and then you can actually bring up threads in the various >>>> pools using pool_threads. >>>> >>>> Same for shutdown. You have to bring down the pool_threads first and >>>> then you can bring down the final thread and the rest of the server >>>> with it. Why it was designed this way, I have NFC. >>>> >>>> The new nfsdctl tool and netlink interfaces should make this simpler in >>>> the future. You'll be able to set the pool-mode in /etc/nfs.conf and >>>> configure a list of per-pool thread counts in there too. Once we have >>>> that, I think we'll be in a better position to consider doing it by >>>> default. >>>> >>>> Eventually we'd like to make the thread poos dynamic, at which point >>>> making that the default becomes much simpler from an administrative >>>> standpoint. >>> >>> I agree that dynamic thread pools will make numa management simpler. >>> Greg Banks did the numa work for SGI - I wonder where he is now. He was >>> at fastmail 10 years ago.. >> >> Dave (cc'd) designed it with Greg, Greg implemented it. >> >> >>> The idea was to bind network interfaces to numa nodes with interrupt >>> routing. There was no expectation that work would be distributed evenly >>> across all nodes. Some might be dedicated to non-nfs work. So there was >>> expected to be non-trivial configuration for both IRQ routing and >>> threads-per-node. If we can make threads-per-node demand-based, then >>> half the problem goes away. >> >> Network devices (and storage devices) are affined to one >> NUMA node. If the nfsd threads are not on the same node >> as the network device, there is a significant penalty. >> >> I have a two-node system here, and it performs consistently >> well when I put it in pool-mode=numa and affine the network >> device's IRQs to one node. >> >> It even works with two network devices (one per node) -- >> each device gets its own set of nfsd threads. >> >> I don't think the pool_mode needs to be demand based. If >> the system is a NUMA system, it makes sense to split up >> the thread pools and put our pencils down. The only other >> step that is needed is proper IRQ affinity settings for >> the network devices. >> > > Having them be demand-based is a nice-to-have. Right now, you need to > know how many thread pools (it's not always trivial to tell) and you > have and decide how many threads each gets. There is some cost to > getting that wrong too. I misread Neil's suggestion. I thought he meant that the pool_mode setting would be demand-based. I don't have a problem with a demand-based thread count, and the demand should be estimated per pool, IMO. The current pool_mode=numa setting knows how many pools to set up: it's the same number as the there are NUMA nodes on the system. That probably should not be changed. nfsdctl can look at the pool_mode setting and know how many pools there are, can't it? > An on-demand thread pool takes a lot of the guesswork out of the > equation (assuming we can get the behavior right, of course). > >> >>> We could even default to one-thread-pool-per-CPU if there are more than >>> X cpus.... >> >> I've never seen a performance improvement in the per-cpu >> pool mode, fwiw. >> >> >> -- >> Chuck Lever >> >> > > -- > Jeff Layton <jlayton@kernel.org> -- Chuck Lever ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 23:26 ` Chuck Lever III 2024-06-18 23:33 ` Jeff Layton @ 2024-06-19 2:56 ` Dave Chinner 2024-06-19 5:47 ` Christoph Hellwig ` (2 more replies) 1 sibling, 3 replies; 26+ messages in thread From: Dave Chinner @ 2024-06-19 2:56 UTC (permalink / raw) To: Chuck Lever III Cc: Neil Brown, Jeff Layton, Trond Myklebust, Linux NFS Mailing List On Tue, Jun 18, 2024 at 11:26:22PM +0000, Chuck Lever III wrote: > > On Jun 18, 2024, at 7:17 PM, NeilBrown <neilb@suse.de> wrote: > >> Eventually we'd like to make the thread poos dynamic, at which point > >> making that the default becomes much simpler from an administrative > >> standpoint. > > > > I agree that dynamic thread pools will make numa management simpler. > > Greg Banks did the numa work for SGI - I wonder where he is now. He was > > at fastmail 10 years ago.. > > Dave (cc'd) designed it with Greg, Greg implemented it. [ I'll dump a bit of history about the NUMA nfsd architecture at the end. ] > > The idea was to bind network interfaces to numa nodes with interrupt > > routing. There was no expectation that work would be distributed evenly > > across all nodes. Some might be dedicated to non-nfs work. So there was > > expected to be non-trivial configuration for both IRQ routing and > > threads-per-node. If we can make threads-per-node demand-based, then > > half the problem goes away. Right. For the dynamic thread pool stuff, the grow side was a simple heuristic: when we dequeued a request, we checked if the request queue was empty, if there were idle nfsd threads and whether we were under the max thread count. i.e. If we had more work to do and no idle workers to do it, we forked another nfsd thread to do the work. I don't recall exactly what Greg implemented on Linux for the shrink side. On Irix, the nfsd would record the time at which it completed it's last request processing, we fired a timer every 30s or so to walk the nfsd status array. If we found an nfsd with a completion time older than 30s, the nfsd got reaped. 30s was long enough to handle bursty loads, but short enough that people didn't complain about having hundreds of nfsds sitting around.... This is basically a very simple version of what workqueues do for us now. That is, if we just make the nfsd request work be based on per-node, node affine, unbound work queues, then thread scaling comes along for free. I think that workqueues support this per-node thread pool affinity natively now: enum wq_affn_scope { WQ_AFFN_DFL, /* use system default */ WQ_AFFN_CPU, /* one pod per CPU */ WQ_AFFN_SMT, /* one pod poer SMT */ WQ_AFFN_CACHE, /* one pod per LLC */ >>>>> WQ_AFFN_NUMA, /* one pod per NUMA node */ WQ_AFFN_SYSTEM, /* one pod across the whole system */ WQ_AFFN_NR_TYPES, }; I'm not sure that the NFS server needs to reinvent the wheel here... > Network devices (and storage devices) are affined to one > NUMA node. NVMe storage devices don't need to be affine to the node. They just need to have a hardware queue assigned to each node so that node-local IO always hits the same hardware queue and gets completion interrupts returned to that same node. And, yes, this is something that still has to be configured manually, too. > If the nfsd threads are not on the same node > as the network device, there is a significant penalty. > > I have a two-node system here, and it performs consistently > well when I put it in pool-mode=numa and affine the network > device's IRQs to one node. > > It even works with two network devices (one per node) -- > each device gets its own set of nfsd threads. Right. But this is all orthogonal to solving the problem of demand based thread pool scaling. > I don't think the pool_mode needs to be demand based. If > the system is a NUMA system, it makes sense to split up > the thread pools and put our pencils down. The only other > step that is needed is proper IRQ affinity settings for > the network devices. I think it's better for everyone if the system automatically scales with demand, regardless of whether it's a NUMA system or not, and regardless of whether the proper NUMA affinity has been configured or not. > > We could even default to one-thread-pool-per-CPU if there are more than > > X cpus.... > > I've never seen a performance improvement in the per-cpu > pool mode, fwiw. We're not doing anything inherently per-cpu in processing an NFS request, so I can only see downsides to trying to restrict incoming processing to per-cpu queues. i.e. if the CPU can't handle all the incoming requests, what processes the per-cpu request backlog? At least with per-node queues, we have many cpus to through at the one incoming request queue and we are much less likely to get backlogged and starve the request queue of processing resources... Cheers, Dave. ----- History.... I did the original NUMA NFS server architecture and implementation work on Irix Origin NUMA machines. Greg took that architecture and made it work on Linux Altix NUMA machines. The differences in OS implementation and the general lack of NUMA and hardware topology support in Linux meant that things had to be done differently on Linux. The Linux project was a much bigger and complex undertaking, and Greg did most of that work. The original Irix architecture was per-node NICs and FC HBAs. The per-node HBAs were attached to shared storage via a multi-path FC SAN, and the NICS were bonded to the local switch and load balanced. Every node had the same network and storage bandwdith - I think it was 4x1GbE and 2x2Gb FC ports per 8p/32GB node. IOWs, roughly 400MB/s per numa node to/from network, to/from disk. On Irix, the NICs and storage hardware were always configured at startup to be affine to the nearest CPU node. The OS knew the physical topology of every piece of hardware in the system, and knew what NUMA node they should be bound to. Nothing needed manual configuration to be node affine. Because we were dealing with networks of thousands of NFS clients (think 2000s era renderwalls) we used ip/port hash based load balancing across all the NIC ports in the machine. This effectively always drove the requests from a single client on the network to a specific NIC on the server. With the NICs being bound to a specific node, we essentially sharded per-client information into per-node structures (e.g. duplicate request detection). Hence most requests rarely need cross-node structure access. Incoming requests were processed on the local node, and any IO that the local NFSd needed to do through XFS was sent directly out the HBAs on the local node and completions were signalled back to that node. Essentially, all the requests, the processing and IO for a specific client ended up being bound to a specific NUMA node. The largest Irix machines we shipped as dedicated NAS boxes were 4 node O300 machines. They had 32 600Mhz r18k MIPS CPUs, 192GB RAM, 16 GbE ports, 8xFC HBA ports and they scaled out to a bit over 1.2GB/s to/from the network to/from storage. That doesn't seem like much these days, but this was back in 2005.... There was relatively little that needed to change in Irix to do this. It largely had all the functionality it already needed, and so it was largely a simple matter of connecting existing dots once the overall architecture was worked out. OTOH, at the time Linux didn't really have a concept of physical hardware topology. All interrupt vectoring had to be set up manually in userspace to point them at the right node. The network drivers didn't use node affine memory to fill receive rings. The bonding driver didn't support the whacky arp games the Irix driver utilised to do it's thing. The network stack performance was a long way behind Irix. The nfsd didn't support dynamic worker thread instantiation. The scheduler didn't really understand numa topology or node affinity very well. The list went on. These were some of the problems that Greg and other SGI people addressed - that was *much* more work that what I had to do originally to get this all to work on Irix, even though the overall architecture was largely the same. -- Dave Chinner david@fromorbit.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-19 2:56 ` Dave Chinner @ 2024-06-19 5:47 ` Christoph Hellwig 2024-06-19 13:44 ` Chuck Lever III 2024-06-19 21:16 ` NeilBrown 2 siblings, 0 replies; 26+ messages in thread From: Christoph Hellwig @ 2024-06-19 5:47 UTC (permalink / raw) To: Dave Chinner Cc: Chuck Lever III, Neil Brown, Jeff Layton, Trond Myklebust, Linux NFS Mailing List On Wed, Jun 19, 2024 at 12:56:44PM +1000, Dave Chinner wrote: > I'm not sure that the NFS server needs to reinvent the wheel here... > > > Network devices (and storage devices) are affined to one > > NUMA node. > > NVMe storage devices don't need to be affine to the node. They just > need to have a hardware queue assigned to each node so that > node-local IO always hits the same hardware queue and gets > completion interrupts returned to that same node. > > And, yes, this is something that still has to be configured > manually, too. For NVMe no manual configuration is required. It uses the blk_mq_pci_map_queues helper to spread the queues around optimally. If enough queues are available every core gets one, else they are spread so that close cores share queues. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-19 2:56 ` Dave Chinner 2024-06-19 5:47 ` Christoph Hellwig @ 2024-06-19 13:44 ` Chuck Lever III 2024-06-19 21:16 ` NeilBrown 2 siblings, 0 replies; 26+ messages in thread From: Chuck Lever III @ 2024-06-19 13:44 UTC (permalink / raw) To: Dave Chinner Cc: Neil Brown, Jeff Layton, Trond Myklebust, Linux NFS Mailing List > On Jun 18, 2024, at 10:56 PM, Dave Chinner <david@fromorbit.com> wrote: > > On Tue, Jun 18, 2024 at 11:26:22PM +0000, Chuck Lever III wrote: >>> On Jun 18, 2024, at 7:17 PM, NeilBrown <neilb@suse.de> wrote: >>>> Eventually we'd like to make the thread poos dynamic, at which point >>>> making that the default becomes much simpler from an administrative >>>> standpoint. >>> >>> I agree that dynamic thread pools will make numa management simpler. >>> Greg Banks did the numa work for SGI - I wonder where he is now. He was >>> at fastmail 10 years ago.. >> >> Dave (cc'd) designed it with Greg, Greg implemented it. > > [ I'll dump a bit of history about the NUMA nfsd architecture at the > end. ] > >>> The idea was to bind network interfaces to numa nodes with interrupt >>> routing. There was no expectation that work would be distributed evenly >>> across all nodes. Some might be dedicated to non-nfs work. So there was >>> expected to be non-trivial configuration for both IRQ routing and >>> threads-per-node. If we can make threads-per-node demand-based, then >>> half the problem goes away. > > Right. > > For the dynamic thread pool stuff, the grow side was a simple > heuristic: when we dequeued a request, we checked if the request > queue was empty, if there were idle nfsd threads and whether we were > under the max thread count. i.e. If we had more work to do and no > idle workers to do it, we forked another nfsd thread to do the work. > > I don't recall exactly what Greg implemented on Linux for the shrink > side. On Irix, the nfsd would record the time at which it completed > it's last request processing, we fired a timer every 30s or > so to walk the nfsd status array. If we found an nfsd with a > completion time older than 30s, the nfsd got reaped. 30s was long > enough to handle bursty loads, but short enough that people didn't > complain about having hundreds of nfsds sitting around.... > > This is basically a very simple version of what workqueues do for us > now. > > That is, if we just make the nfsd request work be based on per-node, node > affine, unbound work queues, then thread scaling comes along for > free. I think that workqueues support this per-node thread pool > affinity natively now: > > enum wq_affn_scope { > WQ_AFFN_DFL, /* use system default */ > WQ_AFFN_CPU, /* one pod per CPU */ > WQ_AFFN_SMT, /* one pod poer SMT */ > WQ_AFFN_CACHE, /* one pod per LLC */ >>>>>> WQ_AFFN_NUMA, /* one pod per NUMA node */ > WQ_AFFN_SYSTEM, /* one pod across the whole system */ > > WQ_AFFN_NR_TYPES, > }; Note that wq_affn_scope appeared only in the last one or two kernel releases. Previously there was no way to control workqueue cache affinity. I have observed significant improvement in throughput scalability on the Linux NFS client with the new default workqueue cache affinity behavior (with NFS/RDMA, of course). The issue is, interestingly enough, the same as it was for lwq: spinlock contention is reduced once the set of threads being scheduled all belong to the same hardware cache. > I'm not sure that the NFS server needs to reinvent the wheel here... Jeff implemented a workqueue-based svc thread scheduler about 10 years ago. We could never make it perform as well as the existing kthreads-based scheduler. I'm not sure we need a work-conserving thread scheduler for NFSD/SunRPC. That's why we took the route of keeping the bespoke thread scheduler in SunRPC this time. >> Network devices (and storage devices) are affined to one >> NUMA node. > > NVMe storage devices don't need to be affine to the node. They just > need to have a hardware queue assigned to each node so that > node-local IO always hits the same hardware queue and gets > completion interrupts returned to that same node. > > And, yes, this is something that still has to be configured > manually, too. > >> If the nfsd threads are not on the same node >> as the network device, there is a significant penalty. >> >> I have a two-node system here, and it performs consistently >> well when I put it in pool-mode=numa and affine the network >> device's IRQs to one node. >> >> It even works with two network devices (one per node) -- >> each device gets its own set of nfsd threads. > > Right. But this is all orthogonal to solving the problem of demand > based thread pool scaling. True, but it /is/ related to Trond's initial observation. The network devices need to be affined properly before pool_mode=numa is completely effective. >> I don't think the pool_mode needs to be demand based. If >> the system is a NUMA system, it makes sense to split up >> the thread pools and put our pencils down. The only other >> step that is needed is proper IRQ affinity settings for >> the network devices. > > I think it's better for everyone if the system automatically scales > with demand, regardless of whether it's a NUMA system or not, and > regardless of whether the proper NUMA affinity has been configured > or not. Read the mistakes that I wrote here ;-) I wasn't referring to thread count. As I responded later, I think automatically managing the pool thread count would be a good improvement. We've been discussing this off and on for a while. >>> We could even default to one-thread-pool-per-CPU if there are more than >>> X cpus.... >> >> I've never seen a performance improvement in the per-cpu >> pool mode, fwiw. > > We're not doing anything inherently per-cpu in processing an NFS > request, so I can only see downsides to trying to restrict incoming > processing to per-cpu queues. i.e. if the CPU can't handle all the > incoming requests, what processes the per-cpu request backlog? At > least with per-node queues, we have many cpus to through at the one > incoming request queue and we are much less likely to get backlogged > and starve the request queue of processing resources... I've proposed getting rid of pool_mode=cpu, because I can't find a winning use case for it. We erred on the conservative side and left it in place for now. In terms of making pool_mode=numa the default setting, that will work in many cases, but in some cases it will result in unpleasant surprises. The default out-of-the-shrink-wrap thread count is currently fixed at 8. In pool_mode=global, all 8 threads get used. In pool_mode=numa, the total thread count is split across the nodes. On a single node system, there will be no change. All is well. On a two-node system, though, each pool will get 4 threads, or only 2 threads each on a four-node system. That can have a surprising and undesirable performance impact. I don't know what will happen on a system with more nodes than nfsd threads. Thus I think there needs to be a solution (like dynamic thread count adjustment) in place to address thread count splitting before we can change the default pool mode. -- Chuck Lever ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-19 2:56 ` Dave Chinner 2024-06-19 5:47 ` Christoph Hellwig 2024-06-19 13:44 ` Chuck Lever III @ 2024-06-19 21:16 ` NeilBrown 2 siblings, 0 replies; 26+ messages in thread From: NeilBrown @ 2024-06-19 21:16 UTC (permalink / raw) To: Dave Chinner Cc: Chuck Lever III, Jeff Layton, Trond Myklebust, Linux NFS Mailing List On Wed, 19 Jun 2024, Dave Chinner wrote: > > I'm not sure that the NFS server needs to reinvent the wheel here... > Workqueues provide threads, but we still have to provide the 'struct work_struct'. For nfsd that is essentially 'struct svc_rqst' which is not small by itself, and includes pre-allocated buffer space for the largest possible request+reply - typically a little over 1MB. If we allocate a new svc_rqst for each incoming request and hand it to workqueue, then we are probably doing a lot more allocating and freeing than at present. If we keep a pool of svc_rqst and re-use them - and if we actually have several pools, one for each NUMA node - then it seems very little extra effort to permanently associate a thread with each svc_rqst. It's not clear that workqueue would buy us anything. Certainly we could usefully learn from workqueue and make use of the same primitives that it uses, but I don't see there would be a win from using it directly. Thanks, NeilBrown ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 19:54 ` Chuck Lever III 2024-06-18 20:16 ` Jeff Layton @ 2024-06-19 0:42 ` Dave Chinner 2024-06-19 1:01 ` NeilBrown 1 sibling, 1 reply; 26+ messages in thread From: Dave Chinner @ 2024-06-19 0:42 UTC (permalink / raw) To: Chuck Lever III Cc: Trond Myklebust, Linux NFS Mailing List, jlayton@kernel.org, neilb@suse.com On Tue, Jun 18, 2024 at 07:54:43PM +0000, Chuck Lever III wrote > On Jun 18, 2024, at 3:50 PM, Trond Myklebust <trondmy@hammerspace.com> wrote: > > > > On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: > >> > >> > >>> On Jun 18, 2024, at 3:29 PM, Trond Myklebust > >>> <trondmy@hammerspace.com> wrote: > >>> > >>> On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: > >>>> > >>>> > >>>>> On Jun 18, 2024, at 2:32 PM, Trond Myklebust > >>>>> <trondmy@hammerspace.com> wrote: > >>>>> > >>>>> I recently back ported Neil's lwq code and sunrpc server > >>>>> changes to > >>>>> our > >>>>> 5.15.130 based kernel in the hope of improving the performance > >>>>> for > >>>>> our > >>>>> data servers. > >>>>> > >>>>> Our performance team recently ran a fio workload on a client > >>>>> that > >>>>> was > >>>>> doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection > >>>>> (infiniband) against that resulting server. I've attached the > >>>>> resulting > >>>>> flame graph from a perf profile run on the server side. > >>>>> > >>>>> Is anyone else seeing this massive contention for the spin lock > >>>>> in > >>>>> __lwq_dequeue? As you can see, it appears to be dwarfing all > >>>>> the > >>>>> other > >>>>> nfsd activity on the system in question here, being responsible > >>>>> for > >>>>> 45% > >>>>> of all the perf hits. Ouch. __lwq_dequeue() runs llist_reverse_order() under a spinlock. llist_reverse_order() is an O(n) algorithm involving full length linked list traversal. IOWs, it's a worst case cache miss algorithm running under a spin lock. And then consider what happens when enqueue processing is faster than dequeue processing. This means the depth of the queue grows, and ultimate length of the queue is unbound. Because fo the batch processing nature of lwq - it takes ->new, reverses it and places it in ->ready - the length of the list that needs reversing ends up growing every batch that we queue faster than we dequeue. Unbound processing queues are bad even when they have O(1) behaviour. lwq has O(n) worst case behaviour, and that makes this even worse... Regardless, The current lwq could be slightly improved - the lockless enqueue competes for the same cacheline as the dequeue serialisation lock. struct lwq { spinlock_t lock; struct llist_node *ready; /* entries to be dequeued */ struct llist_head new; /* entries being enqueued */ }; Adding __cacheline_aligned_in_smp to ->new (the enqueue side) might help reduce this enqueue/dequeue cacheline contention a bit by separating them onto different cachelines. That will push the point of catastrophic breakdown out a little bit, not solve the issue of queue depth based batch processing on the dequeue side. I suspect a lockless ring buffer might be a more scalable solution for the nfsd... > >>>> I haven't seen that, but I've been working on other issues. > >>>> > >>>> What's the nfsd thread count on your test server? Have you > >>>> seen a similar impact on 6.10 kernels ? > >>>> > >>> > >>> 640 knfsd threads. The machine was a supermicro 2029BT-HNR with > >>> 2xIntel > >>> 6150, 384GB of memory and 6xWDC SN840. > >>> > >>> Unfortunately, the machine was a loaner, so cannot compare to 6.10. > >>> That's why I was asking if anyone has seen anything similar. > >> > >> If this system had more than one NUMA node, then using > >> svc's "numa pool" mode might have helped. It's a dual socket machine so it has at least 2 physical nodes. Of course, the bios has to be configured to expose this as a NUMA machine and not a "legacy SMP" machine for the OS to know that, but I'm pretty sure that's been the typical server bios defaults for quite a few years now. Even if it wasn't a dual socket machine, the CPU itself is a NUMA architecture. i.e. just about every server x86-64 CPU sold these days is a NUMA SOC - neither core-to-core or core-to-memory latency is uniform within a socket these days. Desktop CPUs are also well down this track, too. Intel exposes the details of the topology within a socket via the bios option known as "sub-numa clustering". This exposes the full sub-socket CPU and memory topology to the OS, so it is fully aware of both the on-chip and off-chip topology. Using sub-numa clustering means we don't end up with 32+ CPUS to a per-socket numa node. Numa scalability algorithms largely rely on keeping the cores-per-numa-node ratio in check. Sub-numa clustering enables the OS to keep this ratio down to reasonable levels. > > Interesting. I had forgotten about that setting. > > > > Just out of curiosity, is there any reason why we might not want to > > default to that mode on a NUMA enabled system? > > Can't think of one off hand. Maybe back in the day it was > hard to tell when you were actually /on/ a NUMA system. As per above, I would assume that the kernel is *always* running on a NUMA machine. IOWs, if CONFIG_NUMA is enabled (which it is on just about every distro kernel these days), then we should be using NUMA optimisations by default. If the machine is not a NUMA machine (e.g. single socket, sub-numa clustering off), then the NUMA subsystem will be initialised with nr_online_nodes = 1 (i.e. a single active node) and numa aware algorithms should just behave as if there is a single global node. If CONFIG_NUMA=n, then nr_online_nodes is hard coded to 1. Hence subsystems only need to implement a single algorithm that is NUMA aware. The bios/system config will tell the kernel how many nodes there are, and the NUMA algorithms will just do the right thing because nr_online_nodes=1 in those situations.. Cheers, Dave. -- Dave Chinner david@fromorbit.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-19 0:42 ` Dave Chinner @ 2024-06-19 1:01 ` NeilBrown 2024-06-19 21:25 ` NeilBrown 0 siblings, 1 reply; 26+ messages in thread From: NeilBrown @ 2024-06-19 1:01 UTC (permalink / raw) To: Dave Chinner Cc: Chuck Lever III, Trond Myklebust, Linux NFS Mailing List, jlayton@kernel.org On Wed, 19 Jun 2024, Dave Chinner wrote: > On Tue, Jun 18, 2024 at 07:54:43PM +0000, Chuck Lever III wrote > On Jun 18, 2024, at 3:50 PM, Trond Myklebust <trondmy@hammerspace.com> wrote: > > > > > > On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: > > >> > > >> > > >>> On Jun 18, 2024, at 3:29 PM, Trond Myklebust > > >>> <trondmy@hammerspace.com> wrote: > > >>> > > >>> On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: > > >>>> > > >>>> > > >>>>> On Jun 18, 2024, at 2:32 PM, Trond Myklebust > > >>>>> <trondmy@hammerspace.com> wrote: > > >>>>> > > >>>>> I recently back ported Neil's lwq code and sunrpc server > > >>>>> changes to > > >>>>> our > > >>>>> 5.15.130 based kernel in the hope of improving the performance > > >>>>> for > > >>>>> our > > >>>>> data servers. > > >>>>> > > >>>>> Our performance team recently ran a fio workload on a client > > >>>>> that > > >>>>> was > > >>>>> doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection > > >>>>> (infiniband) against that resulting server. I've attached the > > >>>>> resulting > > >>>>> flame graph from a perf profile run on the server side. > > >>>>> > > >>>>> Is anyone else seeing this massive contention for the spin lock > > >>>>> in > > >>>>> __lwq_dequeue? As you can see, it appears to be dwarfing all > > >>>>> the > > >>>>> other > > >>>>> nfsd activity on the system in question here, being responsible > > >>>>> for > > >>>>> 45% > > >>>>> of all the perf hits. > > Ouch. __lwq_dequeue() runs llist_reverse_order() under a spinlock. > > llist_reverse_order() is an O(n) algorithm involving full length > linked list traversal. IOWs, it's a worst case cache miss algorithm > running under a spin lock. And then consider what happens when > enqueue processing is faster than dequeue processing. My expectation was that if enqueue processing (incoming packets) was faster than dequeue processing (handling NFS requests) then there was a bottleneck elsewhere, and this one wouldn't be relevant. It might be useful to measure how long the queue gets. > > This means the depth of the queue grows, and ultimate length of the > queue is unbound. Because fo the batch processing nature of lwq - > it takes ->new, reverses it and places it in ->ready - the length of > the list that needs reversing ends up growing every batch that > we queue faster than we dequeue. Unbound processing queues are bad > even when they have O(1) behaviour. lwq has O(n) worst case > behaviour, and that makes this even worse... > > Regardless, The current lwq could be slightly improved - the > lockless enqueue competes for the same cacheline as the dequeue > serialisation lock. > > struct lwq { > spinlock_t lock; > struct llist_node *ready; /* entries to be dequeued */ > struct llist_head new; /* entries being enqueued */ > }; > > Adding __cacheline_aligned_in_smp to ->new (the enqueue side) might > help reduce this enqueue/dequeue cacheline contention a bit by > separating them onto different cachelines. That will push the point > of catastrophic breakdown out a little bit, not solve the issue of > queue depth based batch processing on the dequeue side. > Yes, that might be beneficial - thanks. > I suspect a lockless ring buffer might be a more scalable solution > for the nfsd... We would need to size the buffer to the maximum number of connections (if there is one - I don't recall) or resize the buffer as the number of connections grows. Certainly doable. Thanks, NeilBrown ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-19 1:01 ` NeilBrown @ 2024-06-19 21:25 ` NeilBrown 2024-06-20 2:29 ` Dave Chinner 0 siblings, 1 reply; 26+ messages in thread From: NeilBrown @ 2024-06-19 21:25 UTC (permalink / raw) To: Dave Chinner Cc: Chuck Lever III, Trond Myklebust, Linux NFS Mailing List, jlayton@kernel.org On Wed, 19 Jun 2024, NeilBrown wrote: > On Wed, 19 Jun 2024, Dave Chinner wrote: > > On Tue, Jun 18, 2024 at 07:54:43PM +0000, Chuck Lever III wrote > On Jun 18, 2024, at 3:50 PM, Trond Myklebust <trondmy@hammerspace.com> wrote: > > > > > > > > On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: > > > >> > > > >> > > > >>> On Jun 18, 2024, at 3:29 PM, Trond Myklebust > > > >>> <trondmy@hammerspace.com> wrote: > > > >>> > > > >>> On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: > > > >>>> > > > >>>> > > > >>>>> On Jun 18, 2024, at 2:32 PM, Trond Myklebust > > > >>>>> <trondmy@hammerspace.com> wrote: > > > >>>>> > > > >>>>> I recently back ported Neil's lwq code and sunrpc server > > > >>>>> changes to > > > >>>>> our > > > >>>>> 5.15.130 based kernel in the hope of improving the performance > > > >>>>> for > > > >>>>> our > > > >>>>> data servers. > > > >>>>> > > > >>>>> Our performance team recently ran a fio workload on a client > > > >>>>> that > > > >>>>> was > > > >>>>> doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection > > > >>>>> (infiniband) against that resulting server. I've attached the > > > >>>>> resulting > > > >>>>> flame graph from a perf profile run on the server side. > > > >>>>> > > > >>>>> Is anyone else seeing this massive contention for the spin lock > > > >>>>> in > > > >>>>> __lwq_dequeue? As you can see, it appears to be dwarfing all > > > >>>>> the > > > >>>>> other > > > >>>>> nfsd activity on the system in question here, being responsible > > > >>>>> for > > > >>>>> 45% > > > >>>>> of all the perf hits. > > > > Ouch. __lwq_dequeue() runs llist_reverse_order() under a spinlock. > > > > llist_reverse_order() is an O(n) algorithm involving full length > > linked list traversal. IOWs, it's a worst case cache miss algorithm > > running under a spin lock. And then consider what happens when > > enqueue processing is faster than dequeue processing. > > My expectation was that if enqueue processing (incoming packets) was > faster than dequeue processing (handling NFS requests) then there was a > bottleneck elsewhere, and this one wouldn't be relevant. > > It might be useful to measure how long the queue gets. Thinking about this some more .... if it did turn out that the queue gets long, and maybe even if it didn't, we could reimplement lwq as a simple linked list with head and tail pointers. enqueue would be something like: new->next = NULL; old_tail = xchg(&q->tail, new); if (old_tail) /* dequeue of old_tail cannot succeed until this assignment completes */ old_tail->next = new else q->head = new dequeue would be spinlock() ret = q->head; if (ret) { while (ret->next == NULL && cmp_xchg(&q->tail, ret, NULL) != ret) /* wait for enqueue of q->tail to complete */ cpu_relax(); } cmp_xchg(&q->head, ret, ret->next); spin_unlock(); plus some barriers and a bit more careful thought. That would put a stronger limit on the time that the spinlock was held, though it could still have to wait for another CPU occasionally. NeilBrown ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-19 21:25 ` NeilBrown @ 2024-06-20 2:29 ` Dave Chinner 2024-06-20 10:18 ` Jeff Layton 2024-06-20 18:33 ` Chuck Lever III 0 siblings, 2 replies; 26+ messages in thread From: Dave Chinner @ 2024-06-20 2:29 UTC (permalink / raw) To: NeilBrown Cc: Chuck Lever III, Trond Myklebust, Linux NFS Mailing List, jlayton@kernel.org On Thu, Jun 20, 2024 at 07:25:15AM +1000, NeilBrown wrote: > On Wed, 19 Jun 2024, NeilBrown wrote: > > On Wed, 19 Jun 2024, Dave Chinner wrote: > > > On Tue, Jun 18, 2024 at 07:54:43PM +0000, Chuck Lever III wrote > On Jun 18, 2024, at 3:50 PM, Trond Myklebust <trondmy@hammerspace.com> wrote: > > > > > > > > > > On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: > > > > >> > > > > >> > > > > >>> On Jun 18, 2024, at 3:29 PM, Trond Myklebust > > > > >>> <trondmy@hammerspace.com> wrote: > > > > >>> > > > > >>> On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: > > > > >>>> > > > > >>>> > > > > >>>>> On Jun 18, 2024, at 2:32 PM, Trond Myklebust > > > > >>>>> <trondmy@hammerspace.com> wrote: > > > > >>>>> > > > > >>>>> I recently back ported Neil's lwq code and sunrpc server > > > > >>>>> changes to > > > > >>>>> our > > > > >>>>> 5.15.130 based kernel in the hope of improving the performance > > > > >>>>> for > > > > >>>>> our > > > > >>>>> data servers. > > > > >>>>> > > > > >>>>> Our performance team recently ran a fio workload on a client > > > > >>>>> that > > > > >>>>> was > > > > >>>>> doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection > > > > >>>>> (infiniband) against that resulting server. I've attached the > > > > >>>>> resulting > > > > >>>>> flame graph from a perf profile run on the server side. > > > > >>>>> > > > > >>>>> Is anyone else seeing this massive contention for the spin lock > > > > >>>>> in > > > > >>>>> __lwq_dequeue? As you can see, it appears to be dwarfing all > > > > >>>>> the > > > > >>>>> other > > > > >>>>> nfsd activity on the system in question here, being responsible > > > > >>>>> for > > > > >>>>> 45% > > > > >>>>> of all the perf hits. > > > > > > Ouch. __lwq_dequeue() runs llist_reverse_order() under a spinlock. > > > > > > llist_reverse_order() is an O(n) algorithm involving full length > > > linked list traversal. IOWs, it's a worst case cache miss algorithm > > > running under a spin lock. And then consider what happens when > > > enqueue processing is faster than dequeue processing. > > > > My expectation was that if enqueue processing (incoming packets) was > > faster than dequeue processing (handling NFS requests) then there was a > > bottleneck elsewhere, and this one wouldn't be relevant. > > > > It might be useful to measure how long the queue gets. > > Thinking about this some more .... if it did turn out that the queue > gets long, and maybe even if it didn't, we could reimplement lwq as a > simple linked list with head and tail pointers. > > enqueue would be something like: > > new->next = NULL; > old_tail = xchg(&q->tail, new); > if (old_tail) > /* dequeue of old_tail cannot succeed until this assignment completes */ > old_tail->next = new > else > q->head = new > > dequeue would be > > spinlock() > ret = q->head; > if (ret) { > while (ret->next == NULL && cmp_xchg(&q->tail, ret, NULL) != ret) > /* wait for enqueue of q->tail to complete */ > cpu_relax(); > } > cmp_xchg(&q->head, ret, ret->next); > spin_unlock(); That might work, but I suspect that it's still only putting off the inevitable. Doing the dequeue purely with atomic operations might be possible, but it's not immediately obvious to me how to solve both head/tail race conditions with atomic operations. I can work out an algorithm that makes enqueue safe against dequeue races (or vice versa), but I can't also get the logic on the opposite side to also be safe. I'll let it bounce around my head a bit more... -Dave. -- Dave Chinner david@fromorbit.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-20 2:29 ` Dave Chinner @ 2024-06-20 10:18 ` Jeff Layton 2024-06-20 21:39 ` NeilBrown 2024-06-20 18:33 ` Chuck Lever III 1 sibling, 1 reply; 26+ messages in thread From: Jeff Layton @ 2024-06-20 10:18 UTC (permalink / raw) To: Dave Chinner, NeilBrown Cc: Chuck Lever III, Trond Myklebust, Linux NFS Mailing List On Thu, 2024-06-20 at 12:29 +1000, Dave Chinner wrote: > On Thu, Jun 20, 2024 at 07:25:15AM +1000, NeilBrown wrote: > > On Wed, 19 Jun 2024, NeilBrown wrote: > > > On Wed, 19 Jun 2024, Dave Chinner wrote: > > > > On Tue, Jun 18, 2024 at 07:54:43PM +0000, Chuck Lever III wrote > On Jun 18, 2024, at 3:50 PM, Trond Myklebust <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: > > > > > > > > > > > > > > > > > > > > > > On Jun 18, 2024, at 3:29 PM, Trond Myklebust > > > > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > > > > > On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Jun 18, 2024, at 2:32 PM, Trond Myklebust > > > > > > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > > > > > > > > > I recently back ported Neil's lwq code and sunrpc server > > > > > > > > > > changes to > > > > > > > > > > our > > > > > > > > > > 5.15.130 based kernel in the hope of improving the performance > > > > > > > > > > for > > > > > > > > > > our > > > > > > > > > > data servers. > > > > > > > > > > > > > > > > > > > > Our performance team recently ran a fio workload on a client > > > > > > > > > > that > > > > > > > > > > was > > > > > > > > > > doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection > > > > > > > > > > (infiniband) against that resulting server. I've attached the > > > > > > > > > > resulting > > > > > > > > > > flame graph from a perf profile run on the server side. > > > > > > > > > > > > > > > > > > > > Is anyone else seeing this massive contention for the spin lock > > > > > > > > > > in > > > > > > > > > > __lwq_dequeue? As you can see, it appears to be dwarfing all > > > > > > > > > > the > > > > > > > > > > other > > > > > > > > > > nfsd activity on the system in question here, being responsible > > > > > > > > > > for > > > > > > > > > > 45% > > > > > > > > > > of all the perf hits. > > > > > > > > Ouch. __lwq_dequeue() runs llist_reverse_order() under a spinlock. > > > > > > > > llist_reverse_order() is an O(n) algorithm involving full length > > > > linked list traversal. IOWs, it's a worst case cache miss algorithm > > > > running under a spin lock. And then consider what happens when > > > > enqueue processing is faster than dequeue processing. > > > > > > My expectation was that if enqueue processing (incoming packets) was > > > faster than dequeue processing (handling NFS requests) then there was a > > > bottleneck elsewhere, and this one wouldn't be relevant. > > > > > > It might be useful to measure how long the queue gets. > > > > Thinking about this some more .... if it did turn out that the queue > > gets long, and maybe even if it didn't, we could reimplement lwq as a > > simple linked list with head and tail pointers. > > > > enqueue would be something like: > > > > new->next = NULL; > > old_tail = xchg(&q->tail, new); > > if (old_tail) > > /* dequeue of old_tail cannot succeed until this assignment completes */ > > old_tail->next = new > > else > > q->head = new > > > > dequeue would be > > > > spinlock() > > ret = q->head; > > if (ret) { > > while (ret->next == NULL && cmp_xchg(&q->tail, ret, NULL) != ret) > > /* wait for enqueue of q->tail to complete */ > > cpu_relax(); > > } > > cmp_xchg(&q->head, ret, ret->next); > > spin_unlock(); > > That might work, but I suspect that it's still only putting off the > inevitable. > > Doing the dequeue purely with atomic operations might be possible, > but it's not immediately obvious to me how to solve both head/tail > race conditions with atomic operations. I can work out an algorithm > that makes enqueue safe against dequeue races (or vice versa), but I > can't also get the logic on the opposite side to also be safe. > > I'll let it bounce around my head a bit more... > The latest version of the multigrain timestamp patches doesn't use it, but Jan Kara pointed out to me that there is a cmpxchg128 function in the kernel. It's only defined for some arches (x86, s390, and aarch64, I think), but maybe that could be used here. -- Jeff Layton <jlayton@kernel.org> ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-20 10:18 ` Jeff Layton @ 2024-06-20 21:39 ` NeilBrown 0 siblings, 0 replies; 26+ messages in thread From: NeilBrown @ 2024-06-20 21:39 UTC (permalink / raw) To: Jeff Layton Cc: Dave Chinner, Chuck Lever III, Trond Myklebust, Linux NFS Mailing List On Thu, 20 Jun 2024, Jeff Layton wrote: > On Thu, 2024-06-20 at 12:29 +1000, Dave Chinner wrote: > > On Thu, Jun 20, 2024 at 07:25:15AM +1000, NeilBrown wrote: > > > On Wed, 19 Jun 2024, NeilBrown wrote: > > > > On Wed, 19 Jun 2024, Dave Chinner wrote: > > > > > On Tue, Jun 18, 2024 at 07:54:43PM +0000, Chuck Lever III wrote > On Jun 18, 2024, at 3:50 PM, Trond Myklebust <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > > > On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: > > > > > > > > > > > > > > > > > > > > > > > > > On Jun 18, 2024, at 3:29 PM, Trond Myklebust > > > > > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > > > > > > > On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Jun 18, 2024, at 2:32 PM, Trond Myklebust > > > > > > > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > > > > > > > > > > > I recently back ported Neil's lwq code and sunrpc server > > > > > > > > > > > changes to > > > > > > > > > > > our > > > > > > > > > > > 5.15.130 based kernel in the hope of improving the performance > > > > > > > > > > > for > > > > > > > > > > > our > > > > > > > > > > > data servers. > > > > > > > > > > > > > > > > > > > > > > Our performance team recently ran a fio workload on a client > > > > > > > > > > > that > > > > > > > > > > > was > > > > > > > > > > > doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection > > > > > > > > > > > (infiniband) against that resulting server. I've attached the > > > > > > > > > > > resulting > > > > > > > > > > > flame graph from a perf profile run on the server side. > > > > > > > > > > > > > > > > > > > > > > Is anyone else seeing this massive contention for the spin lock > > > > > > > > > > > in > > > > > > > > > > > __lwq_dequeue? As you can see, it appears to be dwarfing all > > > > > > > > > > > the > > > > > > > > > > > other > > > > > > > > > > > nfsd activity on the system in question here, being responsible > > > > > > > > > > > for > > > > > > > > > > > 45% > > > > > > > > > > > of all the perf hits. > > > > > > > > > > Ouch. __lwq_dequeue() runs llist_reverse_order() under a spinlock. > > > > > > > > > > llist_reverse_order() is an O(n) algorithm involving full length > > > > > linked list traversal. IOWs, it's a worst case cache miss algorithm > > > > > running under a spin lock. And then consider what happens when > > > > > enqueue processing is faster than dequeue processing. > > > > > > > > My expectation was that if enqueue processing (incoming packets) was > > > > faster than dequeue processing (handling NFS requests) then there was a > > > > bottleneck elsewhere, and this one wouldn't be relevant. > > > > > > > > It might be useful to measure how long the queue gets. > > > > > > Thinking about this some more .... if it did turn out that the queue > > > gets long, and maybe even if it didn't, we could reimplement lwq as a > > > simple linked list with head and tail pointers. > > > > > > enqueue would be something like: > > > > > > new->next = NULL; > > > old_tail = xchg(&q->tail, new); > > > if (old_tail) > > > /* dequeue of old_tail cannot succeed until this assignment completes */ > > > old_tail->next = new > > > else > > > q->head = new > > > > > > dequeue would be > > > > > > spinlock() > > > ret = q->head; > > > if (ret) { > > > while (ret->next == NULL && cmp_xchg(&q->tail, ret, NULL) != ret) > > > /* wait for enqueue of q->tail to complete */ > > > cpu_relax(); > > > } > > > cmp_xchg(&q->head, ret, ret->next); > > > spin_unlock(); > > > > That might work, but I suspect that it's still only putting off the > > inevitable. > > > > Doing the dequeue purely with atomic operations might be possible, > > but it's not immediately obvious to me how to solve both head/tail > > race conditions with atomic operations. I can work out an algorithm > > that makes enqueue safe against dequeue races (or vice versa), but I > > can't also get the logic on the opposite side to also be safe. > > > > I'll let it bounce around my head a bit more... > > > > The latest version of the multigrain timestamp patches doesn't use it, > but Jan Kara pointed out to me that there is a cmpxchg128 function in > the kernel. It's only defined for some arches (x86, s390, and aarch64, > I think), but maybe that could be used here. One of the particularly pernicious scenarios that a non-locking approach needs to deal with is if two threads try to dequeue at the same time and just before the atomic ops which commits the dequeue, one of the threads is suspends - e.g. by an interrupt or VM pauses or whatever. While that thread is paused the other thread completes the dequeue, consumes the event, recycles the object, and it ends up back at the start of the queue, though this time with a different ->next pointer. The paused thread then wakes up and the cmpxchg succeeds but does the wrong thing. This can be addressed with ll/sc because the sc will always fail after a long pause like that. With cmpxchg we could fix it by including a large sequence counter with the address in the atomic exchange. That is where cmpxchg128 comes in. So: head = q->head ctr = q->ctr new = head->next if (cmpxchg128(q, [head,ctr] [new,ctr+1]) fails) goto So; would avoid that problem as the ctr would be different - and a 64 bit counter never cycles. This only solves that particular issue. There are other more obvious races but I think it could be made to work. We'd need a spinlock fallback of other archs of course. Thanks, NeilBrown ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-20 2:29 ` Dave Chinner 2024-06-20 10:18 ` Jeff Layton @ 2024-06-20 18:33 ` Chuck Lever III 2024-06-20 22:04 ` NeilBrown 1 sibling, 1 reply; 26+ messages in thread From: Chuck Lever III @ 2024-06-20 18:33 UTC (permalink / raw) To: Dave Chinner, Neil Brown Cc: Trond Myklebust, Linux NFS Mailing List, jlayton@kernel.org > On Jun 19, 2024, at 10:29 PM, Dave Chinner <david@fromorbit.com> wrote: > > On Thu, Jun 20, 2024 at 07:25:15AM +1000, NeilBrown wrote: >> On Wed, 19 Jun 2024, NeilBrown wrote: >>> On Wed, 19 Jun 2024, Dave Chinner wrote: >>>> On Tue, Jun 18, 2024 at 07:54:43PM +0000, Chuck Lever III wrote > On Jun 18, 2024, at 3:50 PM, Trond Myklebust <trondmy@hammerspace.com> wrote: >>>>>> >>>>>> On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: >>>>>>> >>>>>>> >>>>>>>> On Jun 18, 2024, at 3:29 PM, Trond Myklebust >>>>>>>> <trondmy@hammerspace.com> wrote: >>>>>>>> >>>>>>>> On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: >>>>>>>>> >>>>>>>>> >>>>>>>>>> On Jun 18, 2024, at 2:32 PM, Trond Myklebust >>>>>>>>>> <trondmy@hammerspace.com> wrote: >>>>>>>>>> >>>>>>>>>> I recently back ported Neil's lwq code and sunrpc server >>>>>>>>>> changes to >>>>>>>>>> our >>>>>>>>>> 5.15.130 based kernel in the hope of improving the performance >>>>>>>>>> for >>>>>>>>>> our >>>>>>>>>> data servers. >>>>>>>>>> >>>>>>>>>> Our performance team recently ran a fio workload on a client >>>>>>>>>> that >>>>>>>>>> was >>>>>>>>>> doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection >>>>>>>>>> (infiniband) against that resulting server. I've attached the >>>>>>>>>> resulting >>>>>>>>>> flame graph from a perf profile run on the server side. >>>>>>>>>> >>>>>>>>>> Is anyone else seeing this massive contention for the spin lock >>>>>>>>>> in >>>>>>>>>> __lwq_dequeue? As you can see, it appears to be dwarfing all >>>>>>>>>> the >>>>>>>>>> other >>>>>>>>>> nfsd activity on the system in question here, being responsible >>>>>>>>>> for >>>>>>>>>> 45% >>>>>>>>>> of all the perf hits. >>>> >>>> Ouch. __lwq_dequeue() runs llist_reverse_order() under a spinlock. >>>> >>>> llist_reverse_order() is an O(n) algorithm involving full length >>>> linked list traversal. IOWs, it's a worst case cache miss algorithm >>>> running under a spin lock. And then consider what happens when >>>> enqueue processing is faster than dequeue processing. >>> >>> My expectation was that if enqueue processing (incoming packets) was >>> faster than dequeue processing (handling NFS requests) then there was a >>> bottleneck elsewhere, and this one wouldn't be relevant. >>> >>> It might be useful to measure how long the queue gets. >> >> Thinking about this some more .... if it did turn out that the queue >> gets long, and maybe even if it didn't, we could reimplement lwq as a >> simple linked list with head and tail pointers. >> >> enqueue would be something like: >> >> new->next = NULL; >> old_tail = xchg(&q->tail, new); >> if (old_tail) >> /* dequeue of old_tail cannot succeed until this assignment completes */ >> old_tail->next = new >> else >> q->head = new >> >> dequeue would be >> >> spinlock() >> ret = q->head; >> if (ret) { >> while (ret->next == NULL && cmp_xchg(&q->tail, ret, NULL) != ret) >> /* wait for enqueue of q->tail to complete */ >> cpu_relax(); >> } >> cmp_xchg(&q->head, ret, ret->next); >> spin_unlock(); > > That might work, but I suspect that it's still only putting off the > inevitable. > > Doing the dequeue purely with atomic operations might be possible, > but it's not immediately obvious to me how to solve both head/tail > race conditions with atomic operations. I can work out an algorithm > that makes enqueue safe against dequeue races (or vice versa), but I > can't also get the logic on the opposite side to also be safe. > > I'll let it bounce around my head a bit more... I agree that O(n) dequeuing is potentially alarming. Before we go too far down this path, I'd like to see reproducible numbers that show there is a problem when a recent upstream NFS server is properly set up with a sensible number of threads and running a real workload. Otherwise there is a risk of introducing code in a fundamental part of SunRPC that is optimized to the point of brittleness, and for no good reason. This is what keeps me from sleeping at night: [1] See, it even has my name on it. :-) -- Chuck Lever [1] - https://www.linusakesson.net/programming/kernighans-lever/index.php ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-20 18:33 ` Chuck Lever III @ 2024-06-20 22:04 ` NeilBrown 2024-06-20 23:57 ` Trond Myklebust 0 siblings, 1 reply; 26+ messages in thread From: NeilBrown @ 2024-06-20 22:04 UTC (permalink / raw) To: Chuck Lever III Cc: Dave Chinner, Trond Myklebust, Linux NFS Mailing List, jlayton@kernel.org On Fri, 21 Jun 2024, Chuck Lever III wrote: > > > > On Jun 19, 2024, at 10:29 PM, Dave Chinner <david@fromorbit.com> wrote: > > > > On Thu, Jun 20, 2024 at 07:25:15AM +1000, NeilBrown wrote: > >> On Wed, 19 Jun 2024, NeilBrown wrote: > >>> On Wed, 19 Jun 2024, Dave Chinner wrote: > >>>> On Tue, Jun 18, 2024 at 07:54:43PM +0000, Chuck Lever III wrote > On Jun 18, 2024, at 3:50 PM, Trond Myklebust <trondmy@hammerspace.com> wrote: > >>>>>> > >>>>>> On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III wrote: > >>>>>>> > >>>>>>> > >>>>>>>> On Jun 18, 2024, at 3:29 PM, Trond Myklebust > >>>>>>>> <trondmy@hammerspace.com> wrote: > >>>>>>>> > >>>>>>>> On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III wrote: > >>>>>>>>> > >>>>>>>>> > >>>>>>>>>> On Jun 18, 2024, at 2:32 PM, Trond Myklebust > >>>>>>>>>> <trondmy@hammerspace.com> wrote: > >>>>>>>>>> > >>>>>>>>>> I recently back ported Neil's lwq code and sunrpc server > >>>>>>>>>> changes to > >>>>>>>>>> our > >>>>>>>>>> 5.15.130 based kernel in the hope of improving the performance > >>>>>>>>>> for > >>>>>>>>>> our > >>>>>>>>>> data servers. > >>>>>>>>>> > >>>>>>>>>> Our performance team recently ran a fio workload on a client > >>>>>>>>>> that > >>>>>>>>>> was > >>>>>>>>>> doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection > >>>>>>>>>> (infiniband) against that resulting server. I've attached the > >>>>>>>>>> resulting > >>>>>>>>>> flame graph from a perf profile run on the server side. > >>>>>>>>>> > >>>>>>>>>> Is anyone else seeing this massive contention for the spin lock > >>>>>>>>>> in > >>>>>>>>>> __lwq_dequeue? As you can see, it appears to be dwarfing all > >>>>>>>>>> the > >>>>>>>>>> other > >>>>>>>>>> nfsd activity on the system in question here, being responsible > >>>>>>>>>> for > >>>>>>>>>> 45% > >>>>>>>>>> of all the perf hits. > >>>> > >>>> Ouch. __lwq_dequeue() runs llist_reverse_order() under a spinlock. > >>>> > >>>> llist_reverse_order() is an O(n) algorithm involving full length > >>>> linked list traversal. IOWs, it's a worst case cache miss algorithm > >>>> running under a spin lock. And then consider what happens when > >>>> enqueue processing is faster than dequeue processing. > >>> > >>> My expectation was that if enqueue processing (incoming packets) was > >>> faster than dequeue processing (handling NFS requests) then there was a > >>> bottleneck elsewhere, and this one wouldn't be relevant. > >>> > >>> It might be useful to measure how long the queue gets. > >> > >> Thinking about this some more .... if it did turn out that the queue > >> gets long, and maybe even if it didn't, we could reimplement lwq as a > >> simple linked list with head and tail pointers. > >> > >> enqueue would be something like: > >> > >> new->next = NULL; > >> old_tail = xchg(&q->tail, new); > >> if (old_tail) > >> /* dequeue of old_tail cannot succeed until this assignment completes */ > >> old_tail->next = new > >> else > >> q->head = new > >> > >> dequeue would be > >> > >> spinlock() > >> ret = q->head; > >> if (ret) { > >> while (ret->next == NULL && cmp_xchg(&q->tail, ret, NULL) != ret) > >> /* wait for enqueue of q->tail to complete */ > >> cpu_relax(); > >> } > >> cmp_xchg(&q->head, ret, ret->next); > >> spin_unlock(); > > > > That might work, but I suspect that it's still only putting off the > > inevitable. > > > > Doing the dequeue purely with atomic operations might be possible, > > but it's not immediately obvious to me how to solve both head/tail > > race conditions with atomic operations. I can work out an algorithm > > that makes enqueue safe against dequeue races (or vice versa), but I > > can't also get the logic on the opposite side to also be safe. > > > > I'll let it bounce around my head a bit more... > > I agree that O(n) dequeuing is potentially alarming. Only O(n) 1/n of the time. On average it is still constant time. > > Before we go too far down this path, I'd like to see > reproducible numbers that show there is a problem > when a recent upstream NFS server is properly set up > with a sensible number of threads and running a real > workload. Question for Trond: was nconnect configured, or was there only a single connection? With a single connection there is only ever zero or one xprt in the queue to be dequeued, and if there are zero we don't take the lock. With 16 connections they might always be busy so as soon as a request is read from the connection it is requeued. This means 1/16 of dequeue operations would be slowish and the other 15/16 would be fast. Maybe the 1/16 slow case could swamp the others but I'd be surprised. > > Otherwise there is a risk of introducing code in a > fundamental part of SunRPC that is optimized to the > point of brittleness, and for no good reason. > > This is what keeps me from sleeping at night: [1] > See, it even has my name on it. :-) > > > -- > Chuck Lever > > [1] - https://www.linusakesson.net/programming/kernighans-lever/index.php The conclusion of that article is that we SHOULD try to write clever code because the effort invested in writing it and then debugging it makes us cleverer so that the next time we can do even better. That thought would help me sleep at night! NeilBrown ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-20 22:04 ` NeilBrown @ 2024-06-20 23:57 ` Trond Myklebust 0 siblings, 0 replies; 26+ messages in thread From: Trond Myklebust @ 2024-06-20 23:57 UTC (permalink / raw) To: neilb@suse.de, chuck.lever@oracle.com Cc: david@fromorbit.com, linux-nfs@vger.kernel.org, jlayton@kernel.org On Fri, 2024-06-21 at 08:04 +1000, NeilBrown wrote: > On Fri, 21 Jun 2024, Chuck Lever III wrote: > > > > > > > On Jun 19, 2024, at 10:29 PM, Dave Chinner <david@fromorbit.com> > > > wrote: > > > > > > On Thu, Jun 20, 2024 at 07:25:15AM +1000, NeilBrown wrote: > > > > On Wed, 19 Jun 2024, NeilBrown wrote: > > > > > On Wed, 19 Jun 2024, Dave Chinner wrote: > > > > > > On Tue, Jun 18, 2024 at 07:54:43PM +0000, Chuck Lever III > > > > > > wrote > On Jun 18, 2024, at 3:50 PM, Trond Myklebust > > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > > > > > On Tue, 2024-06-18 at 19:39 +0000, Chuck Lever III > > > > > > > > wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Jun 18, 2024, at 3:29 PM, Trond Myklebust > > > > > > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > > > > > > > > > On Tue, 2024-06-18 at 18:40 +0000, Chuck Lever III > > > > > > > > > > wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Jun 18, 2024, at 2:32 PM, Trond Myklebust > > > > > > > > > > > > <trondmy@hammerspace.com> wrote: > > > > > > > > > > > > > > > > > > > > > > > > I recently back ported Neil's lwq code and > > > > > > > > > > > > sunrpc server > > > > > > > > > > > > changes to > > > > > > > > > > > > our > > > > > > > > > > > > 5.15.130 based kernel in the hope of improving > > > > > > > > > > > > the performance > > > > > > > > > > > > for > > > > > > > > > > > > our > > > > > > > > > > > > data servers. > > > > > > > > > > > > > > > > > > > > > > > > Our performance team recently ran a fio > > > > > > > > > > > > workload on a client > > > > > > > > > > > > that > > > > > > > > > > > > was > > > > > > > > > > > > doing 100% NFSv3 reads in O_DIRECT mode over an > > > > > > > > > > > > RDMA connection > > > > > > > > > > > > (infiniband) against that resulting server. > > > > > > > > > > > > I've attached the > > > > > > > > > > > > resulting > > > > > > > > > > > > flame graph from a perf profile run on the > > > > > > > > > > > > server side. > > > > > > > > > > > > > > > > > > > > > > > > Is anyone else seeing this massive contention > > > > > > > > > > > > for the spin lock > > > > > > > > > > > > in > > > > > > > > > > > > __lwq_dequeue? As you can see, it appears to be > > > > > > > > > > > > dwarfing all > > > > > > > > > > > > the > > > > > > > > > > > > other > > > > > > > > > > > > nfsd activity on the system in question here, > > > > > > > > > > > > being responsible > > > > > > > > > > > > for > > > > > > > > > > > > 45% > > > > > > > > > > > > of all the perf hits. > > > > > > > > > > > > Ouch. __lwq_dequeue() runs llist_reverse_order() under a > > > > > > spinlock. > > > > > > > > > > > > llist_reverse_order() is an O(n) algorithm involving full > > > > > > length > > > > > > linked list traversal. IOWs, it's a worst case cache miss > > > > > > algorithm > > > > > > running under a spin lock. And then consider what happens > > > > > > when > > > > > > enqueue processing is faster than dequeue processing. > > > > > > > > > > My expectation was that if enqueue processing (incoming > > > > > packets) was > > > > > faster than dequeue processing (handling NFS requests) then > > > > > there was a > > > > > bottleneck elsewhere, and this one wouldn't be relevant. > > > > > > > > > > It might be useful to measure how long the queue gets. > > > > > > > > Thinking about this some more .... if it did turn out that the > > > > queue > > > > gets long, and maybe even if it didn't, we could reimplement > > > > lwq as a > > > > simple linked list with head and tail pointers. > > > > > > > > enqueue would be something like: > > > > > > > > new->next = NULL; > > > > old_tail = xchg(&q->tail, new); > > > > if (old_tail) > > > > /* dequeue of old_tail cannot succeed until this > > > > assignment completes */ > > > > old_tail->next = new > > > > else > > > > q->head = new > > > > > > > > dequeue would be > > > > > > > > spinlock() > > > > ret = q->head; > > > > if (ret) { > > > > while (ret->next == NULL && cmp_xchg(&q->tail, ret, > > > > NULL) != ret) > > > > /* wait for enqueue of q->tail to complete */ > > > > cpu_relax(); > > > > } > > > > cmp_xchg(&q->head, ret, ret->next); > > > > spin_unlock(); > > > > > > That might work, but I suspect that it's still only putting off > > > the > > > inevitable. > > > > > > Doing the dequeue purely with atomic operations might be > > > possible, > > > but it's not immediately obvious to me how to solve both > > > head/tail > > > race conditions with atomic operations. I can work out an > > > algorithm > > > that makes enqueue safe against dequeue races (or vice versa), > > > but I > > > can't also get the logic on the opposite side to also be safe. > > > > > > I'll let it bounce around my head a bit more... > > > > I agree that O(n) dequeuing is potentially alarming. > > Only O(n) 1/n of the time. On average it is still constant time. > > > > > Before we go too far down this path, I'd like to see > > reproducible numbers that show there is a problem > > when a recent upstream NFS server is properly set up > > with a sensible number of threads and running a real > > workload. The flame graph is showing contention on a spin lock, so it is affecting running threads only. It will be 100% insensitive to sleeping threads. Yes, there is the issue of NUMA and the resulting potential for cache bouncing between CPUs, and I do agree that particular detail warrants a re-test. However I don't see how the overall number of nfsd threads is relevant. Nor do I see how the use of a random read workload in any way invalidates the test. > Question for Trond: was nconnect configured, or was there only a > single > connection? > > With a single connection there is only ever zero or one xprt in the > queue to be dequeued, and if there are zero we don't take the lock. > > With 16 connections they might always be busy so as soon as a request > is > read from the connection it is requeued. This means 1/16 of dequeue > operations would be slowish and the other 15/16 would be fast. > > Maybe the 1/16 slow case could swamp the others but I'd be surprised. > We deliberately coded up commit b326df4a8ec6 ("NFS: enable nconnect for RDMA") because of the poor performance of RDMA when compared to nconnect enabled TCP on these tests. So yes, this particular test was running with both RDMA and nconnect enabled. However given that the contended spinlock is not per connection, but rather per pool, I don't see how nconnect matters much either since all that does is to increase the number of connections. The other obvious way to do that is to increase the number of NFS clients. > > > > Otherwise there is a risk of introducing code in a > > fundamental part of SunRPC that is optimized to the > > point of brittleness, and for no good reason. > > > > This is what keeps me from sleeping at night: [1] > > See, it even has my name on it. :-) > > > > > > -- > > Chuck Lever > > > > [1] - > > https://www.linusakesson.net/programming/kernighans-lever/index.php > > The conclusion of that article is that we SHOULD try to write clever > code because the effort invested in writing it and then debugging it > makes us cleverer so that the next time we can do even better. That > thought would help me sleep at night! > I mostly sleep well. However that doesn't stop me from thinking that we have a good reason to address bottlenecks when they are as obvious as this. Again, I'm happy to see if I can get hold of some more hardware to test the NUMA hypothesis. However, if that retest shows the contention is still present, then we should consider the proposals that have been made in this thread. -- Trond Myklebust Linux NFS client maintainer, Hammerspace trond.myklebust@hammerspace.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 18:32 knfsd performance Trond Myklebust 2024-06-18 18:40 ` Chuck Lever III @ 2024-06-18 19:38 ` Jeff Layton 2024-06-18 23:12 ` NeilBrown 1 sibling, 1 reply; 26+ messages in thread From: Jeff Layton @ 2024-06-18 19:38 UTC (permalink / raw) To: Trond Myklebust, neilb@suse.com, Chuck.Lever@oracle.com Cc: linux-nfs@vger.kernel.org On Tue, 2024-06-18 at 18:32 +0000, Trond Myklebust wrote: > I recently back ported Neil's lwq code and sunrpc server changes to > our > 5.15.130 based kernel in the hope of improving the performance for > our > data servers. > > Our performance team recently ran a fio workload on a client that was > doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection > (infiniband) against that resulting server. I've attached the > resulting > flame graph from a perf profile run on the server side. > > Is anyone else seeing this massive contention for the spin lock in > __lwq_dequeue? As you can see, it appears to be dwarfing all the > other > nfsd activity on the system in question here, being responsible for > 45% > of all the perf hits. > > I haven't spent much time on performance testing since I keep getting involved in bugs. It looks like that's just the way lwq works. From the comments in lib/lwq.c: * Entries are dequeued using a spinlock to protect against multiple * access. The llist is staged in reverse order, and refreshed * from the llist when it exhausts. * * This is particularly suitable when work items are queued in BH or * IRQ context, and where work items are handled one at a time by * dedicated threads. ...we have dedicated threads, but we usually have a lot of them, so that lock ends up being pretty contended. Is the box you're testing on NUMA-enabled? Setting the server for pool_mode=pernode might be worth an experiment. At least you'd have more than one lwq and less cross-node chatter. You could also try pool_mode=percpu, but that's rumored to not be as helpful. Maybe we need to consider some other lockless queueing mechanism longer term, but I'm not sure how possible that is. -- Jeff Layton <jlayton@kernel.org> ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: knfsd performance 2024-06-18 19:38 ` Jeff Layton @ 2024-06-18 23:12 ` NeilBrown 0 siblings, 0 replies; 26+ messages in thread From: NeilBrown @ 2024-06-18 23:12 UTC (permalink / raw) To: Jeff Layton Cc: Trond Myklebust, Chuck.Lever@oracle.com, linux-nfs@vger.kernel.org On Wed, 19 Jun 2024, Jeff Layton wrote: > On Tue, 2024-06-18 at 18:32 +0000, Trond Myklebust wrote: > > I recently back ported Neil's lwq code and sunrpc server changes to > > our > > 5.15.130 based kernel in the hope of improving the performance for > > our > > data servers. > > > > Our performance team recently ran a fio workload on a client that was > > doing 100% NFSv3 reads in O_DIRECT mode over an RDMA connection > > (infiniband) against that resulting server. I've attached the > > resulting > > flame graph from a perf profile run on the server side. > > > > Is anyone else seeing this massive contention for the spin lock in > > __lwq_dequeue? As you can see, it appears to be dwarfing all the > > other > > nfsd activity on the system in question here, being responsible for > > 45% > > of all the perf hits. > > > > > > I haven't spent much time on performance testing since I keep getting > involved in bugs. It looks like that's just the way lwq works. From the > comments in lib/lwq.c: > > * Entries are dequeued using a spinlock to protect against multiple > * access. The llist is staged in reverse order, and refreshed > * from the llist when it exhausts. > * > * This is particularly suitable when work items are queued in BH or > * IRQ context, and where work items are handled one at a time by > * dedicated threads. > > ...we have dedicated threads, but we usually have a lot of them, so > that lock ends up being pretty contended. > > Is the box you're testing on NUMA-enabled? Setting the server for > pool_mode=pernode might be worth an experiment. At least you'd have > more than one lwq and less cross-node chatter. You could also try > pool_mode=percpu, but that's rumored to not be as helpful. > > Maybe we need to consider some other lockless queueing mechanism longer > term, but I'm not sure how possible that is. I spent a lot of thought trying to come up with a lockless dequeue and failed. I could do it if we had generic load-locked/store-conditional primitives, but that requires hardware support to be efficient. compare-and-exchange cannot do it. The core of the problem is that dequeue requires concurrent control of the "head" pointer and the selected entry. cmpxchg can only control one address at a time. If the lock is highly contended, then sharding is likely the best option - across numa nodes or across some other subset of CPUs. NeilBrown ^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2024-06-20 23:57 UTC | newest] Thread overview: 26+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-06-18 18:32 knfsd performance Trond Myklebust 2024-06-18 18:40 ` Chuck Lever III 2024-06-18 19:29 ` Trond Myklebust 2024-06-18 19:39 ` Chuck Lever III 2024-06-18 19:50 ` Trond Myklebust 2024-06-18 19:54 ` Chuck Lever III 2024-06-18 20:16 ` Jeff Layton 2024-06-18 23:17 ` NeilBrown 2024-06-18 23:26 ` Chuck Lever III 2024-06-18 23:33 ` Jeff Layton 2024-06-18 23:51 ` Chuck Lever III 2024-06-19 2:56 ` Dave Chinner 2024-06-19 5:47 ` Christoph Hellwig 2024-06-19 13:44 ` Chuck Lever III 2024-06-19 21:16 ` NeilBrown 2024-06-19 0:42 ` Dave Chinner 2024-06-19 1:01 ` NeilBrown 2024-06-19 21:25 ` NeilBrown 2024-06-20 2:29 ` Dave Chinner 2024-06-20 10:18 ` Jeff Layton 2024-06-20 21:39 ` NeilBrown 2024-06-20 18:33 ` Chuck Lever III 2024-06-20 22:04 ` NeilBrown 2024-06-20 23:57 ` Trond Myklebust 2024-06-18 19:38 ` Jeff Layton 2024-06-18 23:12 ` NeilBrown
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox