Some more detail would be good. If memory is requested from a particular
node then it would be best to use one that has memory. Callers also may
have used numa_node_id() and that also would need to be fixed.
This needs to be numa_mem_id() and numa_mem_id would need to be
consistently used.
quoted
quoted
+ if (!node_present_pages(searchnode))
+ searchnode = numa_mem_id();
Probably wont need that?
I think the problem is a memoryless node being used for kmalloc_node() so
we need to decide where to enforce node_present_pages(). __slab_alloc()
seems like the best candidate when !node_match().
This needs to be numa_mem_id() and numa_mem_id would need to be
consistently used.
quoted
quoted
+ if (!node_present_pages(searchnode))
+ searchnode = numa_mem_id();
Probably wont need that?
I think the problem is a memoryless node being used for kmalloc_node() so
we need to decide where to enforce node_present_pages(). __slab_alloc()
seems like the best candidate when !node_match().
Yep, I'm looking through callers and such right now and came to a
similar conclusion. I should have a patch soon.
Thanks,
Nish
This needs to be numa_mem_id() and numa_mem_id would need to be
consistently used.
quoted
quoted
+ if (!node_present_pages(searchnode))
+ searchnode = numa_mem_id();
Probably wont need that?
I think the problem is a memoryless node being used for kmalloc_node() so
we need to decide where to enforce node_present_pages(). __slab_alloc()
seems like the best candidate when !node_match().
Actually, this is effectively what Anton's patch does, except with
Wanpeng's adjustment to use node_present_pages(). Does that seem
sufficient to you?
It does only cover the memoryless node case (not the exhausted node
case), but I think that shouldn't block the fix (and it does fix the
issue we've run across in our testing).
-Nish
From: David Rientjes <rientjes@google.com> Date: 2014-01-24 23:49:40
On Fri, 24 Jan 2014, Nishanth Aravamudan wrote:
quoted
I think the problem is a memoryless node being used for kmalloc_node() so
we need to decide where to enforce node_present_pages(). __slab_alloc()
seems like the best candidate when !node_match().
Actually, this is effectively what Anton's patch does, except with
Wanpeng's adjustment to use node_present_pages(). Does that seem
sufficient to you?
I don't see that as being the effect of Anton's patch. We need to use
numa_mem_id() as Christoph mentioned when a memoryless node is passed for
the best NUMA locality. Something like this:
It does only cover the memoryless node case (not the exhausted node
case), but I think that shouldn't block the fix (and it does fix the
issue we've run across in our testing).
kmalloc_node(nid) and kmem_cache_alloc_node(nid) should fallback to nodes
other than nid when memory can't be allocated, these functions only
indicate a preference.
On 24.01.2014 [15:49:33 -0800], David Rientjes wrote:
On Fri, 24 Jan 2014, Nishanth Aravamudan wrote:
quoted
quoted
I think the problem is a memoryless node being used for kmalloc_node() so
we need to decide where to enforce node_present_pages(). __slab_alloc()
seems like the best candidate when !node_match().
Actually, this is effectively what Anton's patch does, except with
Wanpeng's adjustment to use node_present_pages(). Does that seem
sufficient to you?
I don't see that as being the effect of Anton's patch. We need to use
numa_mem_id() as Christoph mentioned when a memoryless node is passed for
the best NUMA locality. Something like this:
Thank you for clarifying and providing a test patch. I ran with this on
the system showing the original problem, configured to have 15GB of
memory.
With your patch after boot:
MemTotal: 15604736 kB
MemFree: 8768192 kB
Slab: 3882560 kB
SReclaimable: 105408 kB
SUnreclaim: 3777152 kB
With Anton's patch after boot:
MemTotal: 15604736 kB
MemFree: 11195008 kB
Slab: 1427968 kB
SReclaimable: 109184 kB
SUnreclaim: 1318784 kB
I know that's fairly unscientific, but the numbers are reproducible.
For what it's worth, a sample of the unmodified numbers:
MemTotal: 15317632 kB
MemFree: 5023424 kB
Slab: 7176064 kB
SReclaimable: 106816 kB
SUnreclaim: 7069248 kB
So it's an improvement, but something is still causing us to (it seems)
be pretty inefficient with the slabs.
Semantically, and please correct me if I'm wrong, this patch is saying
if we have a memoryless node, we expect the page's locality to be that
of numa_mem_id(), and we still deactivate the slab if that isn't true.
Just wanting to make sure I understand the intent.
What I find odd is that there are only 2 nodes on this system, node 0
(empty) and node 1. So won't numa_mem_id() always be 1? And every page
should be coming from node 1 (thus node_match() should always be true?)
Thanks,
Nish
From: David Rientjes <rientjes@google.com> Date: 2014-01-25 00:26:04
On Fri, 24 Jan 2014, Nishanth Aravamudan wrote:
Thank you for clarifying and providing a test patch. I ran with this on
the system showing the original problem, configured to have 15GB of
memory.
With your patch after boot:
MemTotal: 15604736 kB
MemFree: 8768192 kB
Slab: 3882560 kB
SReclaimable: 105408 kB
SUnreclaim: 3777152 kB
With Anton's patch after boot:
MemTotal: 15604736 kB
MemFree: 11195008 kB
Slab: 1427968 kB
SReclaimable: 109184 kB
SUnreclaim: 1318784 kB
I know that's fairly unscientific, but the numbers are reproducible.
I don't think the goal of the discussion is to reduce the amount of slab
allocated, but rather get the most local slab memory possible by use of
kmalloc_node(). When a memoryless node is being passed to kmalloc_node(),
which is probably cpu_to_node() for a cpu bound to a node without memory,
my patch is allocating it on the most local node; Anton's patch is
allocating it on whatever happened to be the cpu slab.
Semantically, and please correct me if I'm wrong, this patch is saying
if we have a memoryless node, we expect the page's locality to be that
of numa_mem_id(), and we still deactivate the slab if that isn't true.
Just wanting to make sure I understand the intent.
Yeah, the default policy should be to fallback to local memory if the node
passed is memoryless.
What I find odd is that there are only 2 nodes on this system, node 0
(empty) and node 1. So won't numa_mem_id() always be 1? And every page
should be coming from node 1 (thus node_match() should always be true?)
The nice thing about slub is its debugging ability, what is
/sys/kernel/slab/cache/objects showing in comparison between the two
patches?
On 24.01.2014 [16:25:58 -0800], David Rientjes wrote:
On Fri, 24 Jan 2014, Nishanth Aravamudan wrote:
quoted
Thank you for clarifying and providing a test patch. I ran with this on
the system showing the original problem, configured to have 15GB of
memory.
With your patch after boot:
MemTotal: 15604736 kB
MemFree: 8768192 kB
Slab: 3882560 kB
SReclaimable: 105408 kB
SUnreclaim: 3777152 kB
With Anton's patch after boot:
MemTotal: 15604736 kB
MemFree: 11195008 kB
Slab: 1427968 kB
SReclaimable: 109184 kB
SUnreclaim: 1318784 kB
I know that's fairly unscientific, but the numbers are reproducible.
I don't think the goal of the discussion is to reduce the amount of slab
allocated, but rather get the most local slab memory possible by use of
kmalloc_node(). When a memoryless node is being passed to kmalloc_node(),
which is probably cpu_to_node() for a cpu bound to a node without memory,
my patch is allocating it on the most local node; Anton's patch is
allocating it on whatever happened to be the cpu slab.
Well, the issue we're trying to resolve, based upon our analysis, is
that we're seeing incredibly inefficient slab usage with memoryless
nodes. To the point where we are OOM'ing a 8GB system without doing
anything in particularly stressful.
As to cpu_to_node() being passed to kmalloc_node(), I think an
appropriate fix is to change that to cpu_to_mem()?
Semantically, and please correct me if I'm wrong, this patch is saying
if we have a memoryless node, we expect the page's locality to be that
of numa_mem_id(), and we still deactivate the slab if that isn't true.
Just wanting to make sure I understand the intent.
Yeah, the default policy should be to fallback to local memory if the node
passed is memoryless.
Thanks!
quoted
What I find odd is that there are only 2 nodes on this system, node 0
(empty) and node 1. So won't numa_mem_id() always be 1? And every page
should be coming from node 1 (thus node_match() should always be true?)
The nice thing about slub is its debugging ability, what is
/sys/kernel/slab/cache/objects showing in comparison between the two
patches?
From: Joonsoo Kim <hidden> Date: 2014-01-27 05:58:09
On Fri, Jan 24, 2014 at 05:10:42PM -0800, Nishanth Aravamudan wrote:
On 24.01.2014 [16:25:58 -0800], David Rientjes wrote:
quoted
On Fri, 24 Jan 2014, Nishanth Aravamudan wrote:
quoted
Thank you for clarifying and providing a test patch. I ran with this on
the system showing the original problem, configured to have 15GB of
memory.
With your patch after boot:
MemTotal: 15604736 kB
MemFree: 8768192 kB
Slab: 3882560 kB
SReclaimable: 105408 kB
SUnreclaim: 3777152 kB
With Anton's patch after boot:
MemTotal: 15604736 kB
MemFree: 11195008 kB
Slab: 1427968 kB
SReclaimable: 109184 kB
SUnreclaim: 1318784 kB
I know that's fairly unscientific, but the numbers are reproducible.
Hello,
I think that there is one mistake on David's patch although I'm not sure
that it is the reason for this result.
With David's patch, get_partial() in new_slab_objects() doesn't work properly,
because we only change node id in !node_match() case. If we meet just !freelist
case, we pass node id directly to new_slab_objects(), so we always try to allocate
new slab page regardless existence of partial pages. We should solve it.
Could you try this one?
Thanks.
From: Christoph Lameter <hidden> Date: 2014-01-27 16:16:26
On Fri, 24 Jan 2014, David Rientjes wrote:
kmalloc_node(nid) and kmem_cache_alloc_node(nid) should fallback to nodes
other than nid when memory can't be allocated, these functions only
indicate a preference.
The nid passed indicated a preference unless __GFP_THIS_NODE is specified.
Then the allocation must occur on that node.
From: Christoph Lameter <hidden> Date: 2014-01-27 16:18:46
On Fri, 24 Jan 2014, Nishanth Aravamudan wrote:
As to cpu_to_node() being passed to kmalloc_node(), I think an
appropriate fix is to change that to cpu_to_mem()?
Yup.
quoted
Yeah, the default policy should be to fallback to local memory if the node
passed is memoryless.
Thanks!
I would suggest to use NUMA_NO_NODE instead. That will fit any slab that
we may be currently allocating from or can get a hold of and is mosty
efficient.
From: Christoph Lameter <hidden> Date: 2014-01-27 16:24:35
On Fri, 24 Jan 2014, Nishanth Aravamudan wrote:
What I find odd is that there are only 2 nodes on this system, node 0
(empty) and node 1. So won't numa_mem_id() always be 1? And every page
should be coming from node 1 (thus node_match() should always be true?)
Well yes that occurs if you specify the node or just always use the
default memory allocation policy.
In order to spread the allocatios over both node you would have to set the
tasks memory allocation policy to MPOL_INTERLEAVE.
On 27.01.2014 [14:58:05 +0900], Joonsoo Kim wrote:
On Fri, Jan 24, 2014 at 05:10:42PM -0800, Nishanth Aravamudan wrote:
quoted
On 24.01.2014 [16:25:58 -0800], David Rientjes wrote:
quoted
On Fri, 24 Jan 2014, Nishanth Aravamudan wrote:
quoted
Thank you for clarifying and providing a test patch. I ran with this on
the system showing the original problem, configured to have 15GB of
memory.
With your patch after boot:
MemTotal: 15604736 kB
MemFree: 8768192 kB
Slab: 3882560 kB
SReclaimable: 105408 kB
SUnreclaim: 3777152 kB
With Anton's patch after boot:
MemTotal: 15604736 kB
MemFree: 11195008 kB
Slab: 1427968 kB
SReclaimable: 109184 kB
SUnreclaim: 1318784 kB
I know that's fairly unscientific, but the numbers are reproducible.
Hello,
I think that there is one mistake on David's patch although I'm not sure
that it is the reason for this result.
With David's patch, get_partial() in new_slab_objects() doesn't work
properly, because we only change node id in !node_match() case. If we
meet just !freelist case, we pass node id directly to
new_slab_objects(), so we always try to allocate new slab page
regardless existence of partial pages. We should solve it.
Could you try this one?
This helps about the same as David's patch -- but I found the reason
why! ppc64 doesn't set CONFIG_HAVE_MEMORYLESS_NODES :) Expect a patch
shortly for that and one other case I found.
This patch on its own seems to help on our test system by saving around
1.5GB of slab.
Tested-by: Nishanth Aravamudan <redacted>
Acked-by: Nishanth Aravamudan <redacted>
with the caveat below.
Thanks,
Nish
From: Christoph Lameter <hidden> Date: 2014-01-29 15:55:03
On Tue, 28 Jan 2014, Nishanth Aravamudan wrote:
This helps about the same as David's patch -- but I found the reason
why! ppc64 doesn't set CONFIG_HAVE_MEMORYLESS_NODES :) Expect a patch
shortly for that and one other case I found.
On 28.01.2014 [10:29:47 -0800], Nishanth Aravamudan wrote:
On 27.01.2014 [14:58:05 +0900], Joonsoo Kim wrote:
quoted
On Fri, Jan 24, 2014 at 05:10:42PM -0800, Nishanth Aravamudan wrote:
quoted
On 24.01.2014 [16:25:58 -0800], David Rientjes wrote:
quoted
On Fri, 24 Jan 2014, Nishanth Aravamudan wrote:
quoted
Thank you for clarifying and providing a test patch. I ran with this on
the system showing the original problem, configured to have 15GB of
memory.
With your patch after boot:
MemTotal: 15604736 kB
MemFree: 8768192 kB
Slab: 3882560 kB
SReclaimable: 105408 kB
SUnreclaim: 3777152 kB
With Anton's patch after boot:
MemTotal: 15604736 kB
MemFree: 11195008 kB
Slab: 1427968 kB
SReclaimable: 109184 kB
SUnreclaim: 1318784 kB
I know that's fairly unscientific, but the numbers are reproducible.
Hello,
I think that there is one mistake on David's patch although I'm not sure
that it is the reason for this result.
With David's patch, get_partial() in new_slab_objects() doesn't work
properly, because we only change node id in !node_match() case. If we
meet just !freelist case, we pass node id directly to
new_slab_objects(), so we always try to allocate new slab page
regardless existence of partial pages. We should solve it.
Could you try this one?
This helps about the same as David's patch -- but I found the reason
why! ppc64 doesn't set CONFIG_HAVE_MEMORYLESS_NODES :) Expect a patch
shortly for that and one other case I found.
This patch on its own seems to help on our test system by saving around
1.5GB of slab.
Tested-by: Nishanth Aravamudan <redacted>
Acked-by: Nishanth Aravamudan <redacted>
with the caveat below.
Thanks,
Nish
This might be clearer as:
int searchnode = node;
if (node == NUMA_NO_NODE || !node_present_pages(node))
searchnode = numa_mem_id();
Cody Schafer mentioned to me on IRC that this may not always reflect
exactly what the caller intends.
int searchnode = node;
if (node == NUMA_NO_NODE)
searchnode = numa_mem_id();
if (!node_present_pages(node))
searchnode = local_memory_node(node);
The difference in semantics from the previous is that here, if we have a
memoryless node, rather than using the CPU's nearest NUMA node, we use
the NUMA node closest to the requested one?
From: Christoph Lameter <hidden> Date: 2014-01-30 16:26:54
On Wed, 29 Jan 2014, Nishanth Aravamudan wrote:
exactly what the caller intends.
int searchnode = node;
if (node == NUMA_NO_NODE)
searchnode = numa_mem_id();
if (!node_present_pages(node))
searchnode = local_memory_node(node);
The difference in semantics from the previous is that here, if we have a
memoryless node, rather than using the CPU's nearest NUMA node, we use
the NUMA node closest to the requested one?
The idea here is that the page allocator will do the fallback to other
nodes. This check for !node_present should not be necessary. SLUB needs to
accept the page from whatever node the page allocator returned and work
with that.
The problem is the check for having a slab from the "right" node may fall
again after another attempt to allocate from the same node. SLUB will then
push the slab from the *wrong* node back to the partial lists and may
attempt another allocation that will again be successful but return memory
from another node. That way the partial lists from a particular node are
growing uselessly.
One way to solve this may be to check if memory is actually allocated
from the requested node and fallback to NUMA_NO_NODE (which will use the
last allocated slab) for future allocs if the page allocator returned
memory from a different node (unless GFP_THIS_NODE is set of course).
Otherwise we end up replicating the page allocator logic in slub like in
slab. That is what I wanted to
avoid.
On 28.01.2014 [10:29:47 -0800], Nishanth Aravamudan wrote:
On 27.01.2014 [14:58:05 +0900], Joonsoo Kim wrote:
quoted
On Fri, Jan 24, 2014 at 05:10:42PM -0800, Nishanth Aravamudan wrote:
quoted
On 24.01.2014 [16:25:58 -0800], David Rientjes wrote:
quoted
On Fri, 24 Jan 2014, Nishanth Aravamudan wrote:
quoted
Thank you for clarifying and providing a test patch. I ran with this on
the system showing the original problem, configured to have 15GB of
memory.
With your patch after boot:
MemTotal: 15604736 kB
MemFree: 8768192 kB
Slab: 3882560 kB
SReclaimable: 105408 kB
SUnreclaim: 3777152 kB
With Anton's patch after boot:
MemTotal: 15604736 kB
MemFree: 11195008 kB
Slab: 1427968 kB
SReclaimable: 109184 kB
SUnreclaim: 1318784 kB
I know that's fairly unscientific, but the numbers are reproducible.
Hello,
I think that there is one mistake on David's patch although I'm not sure
that it is the reason for this result.
With David's patch, get_partial() in new_slab_objects() doesn't work
properly, because we only change node id in !node_match() case. If we
meet just !freelist case, we pass node id directly to
new_slab_objects(), so we always try to allocate new slab page
regardless existence of partial pages. We should solve it.
Could you try this one?
This helps about the same as David's patch -- but I found the reason
why! ppc64 doesn't set CONFIG_HAVE_MEMORYLESS_NODES :) Expect a patch
shortly for that and one other case I found.
This patch on its own seems to help on our test system by saving around
1.5GB of slab.
Tested-by: Nishanth Aravamudan <redacted>
Acked-by: Nishanth Aravamudan <redacted>
with the caveat below.
So what's the status of this patch? Christoph, do you think this is fine
as it is?
Thanks,
Nish
From: Christoph Lameter <hidden> Date: 2014-02-04 20:39:37
On Mon, 3 Feb 2014, Nishanth Aravamudan wrote:
Yes, sorry for my lack of clarity. I meant Joonsoo's latest patch for
the $SUBJECT issue.
Hmmm... I am not sure that this is a general solution. The fallback to
other nodes can not only occur because a node has no memory as his patch
assumes.
If the target node allocation fails (for whatever reason) then I would
recommend for simplicities sake to change the target node to NUMA_NO_NODE
and just take whatever is in the current cpu slab. A more complex solution
would be to look through partial lists in increasing distance to find a
partially used slab that is reasonable close to the current node. Slab has
logic like that in fallback_alloc(). Slubs get_any_partial() function does
something close to what you want.
On 04.02.2014 [14:39:32 -0600], Christoph Lameter wrote:
On Mon, 3 Feb 2014, Nishanth Aravamudan wrote:
quoted
Yes, sorry for my lack of clarity. I meant Joonsoo's latest patch for
the $SUBJECT issue.
Hmmm... I am not sure that this is a general solution. The fallback to
other nodes can not only occur because a node has no memory as his patch
assumes.
Thanks, Christoph. I see your point.
Something in this area would be nice, though, as it does produce a
fairly significant bump in the slab usage on our test system.
If the target node allocation fails (for whatever reason) then I would
recommend for simplicities sake to change the target node to
NUMA_NO_NODE and just take whatever is in the current cpu slab. A more
complex solution would be to look through partial lists in increasing
distance to find a partially used slab that is reasonable close to the
current node. Slab has logic like that in fallback_alloc(). Slubs
get_any_partial() function does something close to what you want.
I apologize for my own ignorance, but I'm having trouble following.
Anton's original patch did fallback to the current cpu slab, but I'm not
sure any NUMA_NO_NODE change is necessary there. At the point we're
deactivating the slab (in the current code, in __slab_alloc()), we have
successfully allocated from somewhere, it's just not on the node we
expected to be on.
So perhaps you are saying to make a change lower in the code? I'm not
sure where it makes sense to change the target node in that case. I'd
appreciate any guidance you can give.
Thanks,
Nish
From: Christoph Lameter <hidden> Date: 2014-02-05 19:28:07
On Tue, 4 Feb 2014, Nishanth Aravamudan wrote:
quoted
If the target node allocation fails (for whatever reason) then I would
recommend for simplicities sake to change the target node to
NUMA_NO_NODE and just take whatever is in the current cpu slab. A more
complex solution would be to look through partial lists in increasing
distance to find a partially used slab that is reasonable close to the
current node. Slab has logic like that in fallback_alloc(). Slubs
get_any_partial() function does something close to what you want.
I apologize for my own ignorance, but I'm having trouble following.
Anton's original patch did fallback to the current cpu slab, but I'm not
sure any NUMA_NO_NODE change is necessary there. At the point we're
deactivating the slab (in the current code, in __slab_alloc()), we have
successfully allocated from somewhere, it's just not on the node we
expected to be on.
Right so if we are ignoring the node then the simplest thing to do is to
not deactivate the current cpu slab but to take an object from it.
So perhaps you are saying to make a change lower in the code? I'm not
sure where it makes sense to change the target node in that case. I'd
appreciate any guidance you can give.
This not an easy thing to do. If the current slab is not the right node
but would be the node from which the page allocator would be returning
memory then the current slab can still be allocated from. If the fallback
is to another node then the current cpu slab needs to be deactivated and
the allocation from that node needs to proceeed. Have a look at
fallback_alloc() in the slab allocator.
A allocation attempt from the page allocator can be restricted to a
specific node through GFP_THIS_NODE.
On 24.01.2014 [16:25:58 -0800], David Rientjes wrote:
On Fri, 24 Jan 2014, Nishanth Aravamudan wrote:
quoted
Thank you for clarifying and providing a test patch. I ran with this on
the system showing the original problem, configured to have 15GB of
memory.
With your patch after boot:
MemTotal: 15604736 kB
MemFree: 8768192 kB
Slab: 3882560 kB
SReclaimable: 105408 kB
SUnreclaim: 3777152 kB
With Anton's patch after boot:
MemTotal: 15604736 kB
MemFree: 11195008 kB
Slab: 1427968 kB
SReclaimable: 109184 kB
SUnreclaim: 1318784 kB
I know that's fairly unscientific, but the numbers are reproducible.
I don't think the goal of the discussion is to reduce the amount of slab
allocated, but rather get the most local slab memory possible by use of
kmalloc_node(). When a memoryless node is being passed to kmalloc_node(),
which is probably cpu_to_node() for a cpu bound to a node without memory,
my patch is allocating it on the most local node; Anton's patch is
allocating it on whatever happened to be the cpu slab.
Semantically, and please correct me if I'm wrong, this patch is saying
if we have a memoryless node, we expect the page's locality to be that
of numa_mem_id(), and we still deactivate the slab if that isn't true.
Just wanting to make sure I understand the intent.
Yeah, the default policy should be to fallback to local memory if the node
passed is memoryless.
quoted
What I find odd is that there are only 2 nodes on this system, node 0
(empty) and node 1. So won't numa_mem_id() always be 1? And every page
should be coming from node 1 (thus node_match() should always be true?)
The nice thing about slub is its debugging ability, what is
/sys/kernel/slab/cache/objects showing in comparison between the two
patches?
Ok, I finally got around to writing a script that compares the objects
output from both kernels.
log1 is with CONFIG_HAVE_MEMORYLESS_NODES on, my kthread locality patch
and Joonsoo's patch.
log2 is with CONFIG_HAVE_MEMORYLESS_NODES on, my kthread locality patch
and Anton's patch.
slab objects objects percent
log1 log2 change
-----------------------------------------------------------
:t-0000104 71190 85680 20.353982 %
UDP 4352 3392 22.058824 %
inode_cache 54302 41923 22.796582 %
fscache_cookie_jar 3276 2457 25.000000 %
:t-0000896 438 292 33.333333 %
:t-0000080 310401 195323 37.073978 %
ext4_inode_cache 335 201 40.000000 %
:t-0000192 89408 128898 44.168307 %
:t-0000184 151300 81880 45.882353 %
:t-0000512 49698 73648 48.191074 %
:at-0000192 242867 120948 50.199904 %
xfs_inode 34350 15221 55.688501 %
:t-0016384 11005 17257 56.810541 %
proc_inode_cache 103868 34717 66.575846 %
tw_sock_TCP 768 256 66.666667 %
:t-0004096 15240 25672 68.451444 %
nfs_inode_cache 1008 315 68.750000 %
:t-0001024 14528 24720 70.154185 %
:t-0032768 655 1312 100.305344%
:t-0002048 14242 30720 115.700042%
:t-0000640 1020 2550 150.000000%
:t-0008192 10005 27905 178.910545%
FWIW, the configuration of this LPAR has slightly changed. It is now configured
for maximally 400 CPUs, of which 200 are present. The result is that even with
Joonsoo's patch (log1 above), we OOM pretty easily and Anton's slab usage
script reports:
slab mem objs slabs
used active active
------------------------------------------------------------
kmalloc-512 1182 MB 2.03% 100.00%
kmalloc-192 1182 MB 1.38% 100.00%
kmalloc-16384 966 MB 17.66% 100.00%
kmalloc-4096 353 MB 15.92% 100.00%
kmalloc-8192 259 MB 27.28% 100.00%
kmalloc-32768 207 MB 9.86% 100.00%
In comparison (log2 above):
slab mem objs slabs
used active active
------------------------------------------------------------
kmalloc-16384 273 MB 98.76% 100.00%
kmalloc-8192 225 MB 98.67% 100.00%
pgtable-2^11 114 MB 100.00% 100.00%
pgtable-2^12 109 MB 100.00% 100.00%
kmalloc-4096 104 MB 98.59% 100.00%
I appreciate all the help so far, if anyone has any ideas how best to
proceed further, or what they'd like debugged more, I'm happy to get
this fixed. We're hitting this on a couple of different systems and I'd
like to find a good resolution to the problem.
Thanks,
Nish
On 05.02.2014 [13:28:03 -0600], Christoph Lameter wrote:
On Tue, 4 Feb 2014, Nishanth Aravamudan wrote:
quoted
quoted
If the target node allocation fails (for whatever reason) then I would
recommend for simplicities sake to change the target node to
NUMA_NO_NODE and just take whatever is in the current cpu slab. A more
complex solution would be to look through partial lists in increasing
distance to find a partially used slab that is reasonable close to the
current node. Slab has logic like that in fallback_alloc(). Slubs
get_any_partial() function does something close to what you want.
I apologize for my own ignorance, but I'm having trouble following.
Anton's original patch did fallback to the current cpu slab, but I'm not
sure any NUMA_NO_NODE change is necessary there. At the point we're
deactivating the slab (in the current code, in __slab_alloc()), we have
successfully allocated from somewhere, it's just not on the node we
expected to be on.
Right so if we are ignoring the node then the simplest thing to do is to
not deactivate the current cpu slab but to take an object from it.
Ok, that's what Anton's patch does, I believe. Are you ok with that
patch as it is?
quoted
So perhaps you are saying to make a change lower in the code? I'm not
sure where it makes sense to change the target node in that case. I'd
appreciate any guidance you can give.
This not an easy thing to do. If the current slab is not the right node
but would be the node from which the page allocator would be returning
memory then the current slab can still be allocated from. If the fallback
is to another node then the current cpu slab needs to be deactivated and
the allocation from that node needs to proceeed. Have a look at
fallback_alloc() in the slab allocator.
A allocation attempt from the page allocator can be restricted to a
specific node through GFP_THIS_NODE.
Thanks for the pointers, I will try and take a look.
Thanks,
Nish
From: Joonsoo Kim <hidden> Date: 2014-02-06 08:04:16
On Wed, Feb 05, 2014 at 06:07:57PM -0800, Nishanth Aravamudan wrote:
On 24.01.2014 [16:25:58 -0800], David Rientjes wrote:
quoted
On Fri, 24 Jan 2014, Nishanth Aravamudan wrote:
quoted
Thank you for clarifying and providing a test patch. I ran with this on
the system showing the original problem, configured to have 15GB of
memory.
With your patch after boot:
MemTotal: 15604736 kB
MemFree: 8768192 kB
Slab: 3882560 kB
SReclaimable: 105408 kB
SUnreclaim: 3777152 kB
With Anton's patch after boot:
MemTotal: 15604736 kB
MemFree: 11195008 kB
Slab: 1427968 kB
SReclaimable: 109184 kB
SUnreclaim: 1318784 kB
I know that's fairly unscientific, but the numbers are reproducible.
I don't think the goal of the discussion is to reduce the amount of slab
allocated, but rather get the most local slab memory possible by use of
kmalloc_node(). When a memoryless node is being passed to kmalloc_node(),
which is probably cpu_to_node() for a cpu bound to a node without memory,
my patch is allocating it on the most local node; Anton's patch is
allocating it on whatever happened to be the cpu slab.
Semantically, and please correct me if I'm wrong, this patch is saying
if we have a memoryless node, we expect the page's locality to be that
of numa_mem_id(), and we still deactivate the slab if that isn't true.
Just wanting to make sure I understand the intent.
Yeah, the default policy should be to fallback to local memory if the node
passed is memoryless.
quoted
What I find odd is that there are only 2 nodes on this system, node 0
(empty) and node 1. So won't numa_mem_id() always be 1? And every page
should be coming from node 1 (thus node_match() should always be true?)
The nice thing about slub is its debugging ability, what is
/sys/kernel/slab/cache/objects showing in comparison between the two
patches?
Ok, I finally got around to writing a script that compares the objects
output from both kernels.
log1 is with CONFIG_HAVE_MEMORYLESS_NODES on, my kthread locality patch
and Joonsoo's patch.
log2 is with CONFIG_HAVE_MEMORYLESS_NODES on, my kthread locality patch
and Anton's patch.
slab objects objects percent
log1 log2 change
-----------------------------------------------------------
:t-0000104 71190 85680 20.353982 %
UDP 4352 3392 22.058824 %
inode_cache 54302 41923 22.796582 %
fscache_cookie_jar 3276 2457 25.000000 %
:t-0000896 438 292 33.333333 %
:t-0000080 310401 195323 37.073978 %
ext4_inode_cache 335 201 40.000000 %
:t-0000192 89408 128898 44.168307 %
:t-0000184 151300 81880 45.882353 %
:t-0000512 49698 73648 48.191074 %
:at-0000192 242867 120948 50.199904 %
xfs_inode 34350 15221 55.688501 %
:t-0016384 11005 17257 56.810541 %
proc_inode_cache 103868 34717 66.575846 %
tw_sock_TCP 768 256 66.666667 %
:t-0004096 15240 25672 68.451444 %
nfs_inode_cache 1008 315 68.750000 %
:t-0001024 14528 24720 70.154185 %
:t-0032768 655 1312 100.305344%
:t-0002048 14242 30720 115.700042%
:t-0000640 1020 2550 150.000000%
:t-0008192 10005 27905 178.910545%
FWIW, the configuration of this LPAR has slightly changed. It is now configured
for maximally 400 CPUs, of which 200 are present. The result is that even with
Joonsoo's patch (log1 above), we OOM pretty easily and Anton's slab usage
script reports:
slab mem objs slabs
used active active
------------------------------------------------------------
kmalloc-512 1182 MB 2.03% 100.00%
kmalloc-192 1182 MB 1.38% 100.00%
kmalloc-16384 966 MB 17.66% 100.00%
kmalloc-4096 353 MB 15.92% 100.00%
kmalloc-8192 259 MB 27.28% 100.00%
kmalloc-32768 207 MB 9.86% 100.00%
In comparison (log2 above):
slab mem objs slabs
used active active
------------------------------------------------------------
kmalloc-16384 273 MB 98.76% 100.00%
kmalloc-8192 225 MB 98.67% 100.00%
pgtable-2^11 114 MB 100.00% 100.00%
pgtable-2^12 109 MB 100.00% 100.00%
kmalloc-4096 104 MB 98.59% 100.00%
I appreciate all the help so far, if anyone has any ideas how best to
proceed further, or what they'd like debugged more, I'm happy to get
this fixed. We're hitting this on a couple of different systems and I'd
like to find a good resolution to the problem.
Hello,
I have no memoryless system, so, to debug it, I need your help. :)
First, please let me know node information on your system.
I'm preparing 3 another patches which are nearly same with previous patch,
but slightly different approach. Could you test them on your system?
I will send them soon.
And I think that same problem exists if CONFIG_SLAB is enabled. Could you
confirm that?
And, could you confirm that your system's numa_mem_id() is properly set?
And, could you confirm that node_present_pages() test works properly?
And, with my patches, could you give me more information on slub stat?
For this, you need to enable CONFIG_SLUB_STATS. Then please send me all the
slub stat on /proc/sys/kernel/debug/slab.
Sorry for too many request.
If it bothers you too much, please ignore it :)
Thanks.
From: Joonsoo Kim <hidden> Date: 2014-02-06 08:07:01
Currently, if allocation constraint to node is NUMA_NO_NODE, we search
a partial slab on numa_node_id() node. This doesn't work properly on the
system having memoryless node, since it can have no memory on that node and
there must be no partial slab on that node.
On that node, page allocation always fallback to numa_mem_id() first. So
searching a partial slab on numa_node_id() in that case is proper solution
for memoryless node case.
Signed-off-by: Joonsoo Kim <redacted>
From: David Rientjes <rientjes@google.com> Date: 2014-02-06 08:38:45
On Thu, 6 Feb 2014, Joonsoo Kim wrote:
Currently, if allocation constraint to node is NUMA_NO_NODE, we search
a partial slab on numa_node_id() node. This doesn't work properly on the
system having memoryless node, since it can have no memory on that node and
there must be no partial slab on that node.
On that node, page allocation always fallback to numa_mem_id() first. So
searching a partial slab on numa_node_id() in that case is proper solution
for memoryless node case.
Signed-off-by: Joonsoo Kim <redacted>
Acked-by: David Rientjes <rientjes@google.com>
I think you'll need to send these to Andrew since he appears to be picking
up slub patches these days.
@@ -233,11 +233,20 @@ static inline int numa_node_id(void)*Usetheaccessorfunctionsset_numa_mem(),numa_mem_id()andcpu_to_mem().*/DECLARE_PER_CPU(int,_numa_mem_);+int_node_numa_mem_[MAX_NUMNODES];#ifndef set_numa_memstaticinlinevoidset_numa_mem(intnode){this_cpu_write(_numa_mem_,node);+_node_numa_mem_[numa_node_id()]=node;+}+#endif++#ifndef get_numa_mem+staticinlineintget_numa_mem(intnode)+{+return_node_numa_mem_[node];}#endif
@@ -260,6 +269,7 @@ static inline int cpu_to_mem(int cpu)staticinlinevoidset_cpu_numa_mem(intcpu,intnode){per_cpu(_numa_mem_,cpu)=node;+_node_numa_mem_[numa_node_id()]=node;
The intention seems to be that _node_numa_mem_[X] for a node X will return
a node Y with memory that has the nearest distance? In other words,
caching the value returned by local_memory_node(X)?
That doesn't seem to be what it's doing since numa_node_id() is the node
of the cpu that current is running on so this ends up getting initialized
to whatever local_memory_node(cpu_to_node(cpu)) is for the last bit set in
cpu_possible_mask.
quoted hunk
}
#endif
@@ -273,6 +283,13 @@ static inline int numa_mem_id(void) } #endif+#ifndef get_numa_mem+static inline int get_numa_mem(int node)+{+ return node;+}+#endif+ #ifndef cpu_to_mem static inline int cpu_to_mem(int cpu) {
@@ -233,11 +233,20 @@ static inline int numa_node_id(void)*Usetheaccessorfunctionsset_numa_mem(),numa_mem_id()andcpu_to_mem().*/DECLARE_PER_CPU(int,_numa_mem_);+int_node_numa_mem_[MAX_NUMNODES];#ifndef set_numa_memstaticinlinevoidset_numa_mem(intnode){this_cpu_write(_numa_mem_,node);+_node_numa_mem_[numa_node_id()]=node;+}+#endif++#ifndef get_numa_mem+staticinlineintget_numa_mem(intnode)+{+return_node_numa_mem_[node];}#endif
@@ -260,6 +269,7 @@ static inline int cpu_to_mem(int cpu)staticinlinevoidset_cpu_numa_mem(intcpu,intnode){per_cpu(_numa_mem_,cpu)=node;+_node_numa_mem_[numa_node_id()]=node;
The intention seems to be that _node_numa_mem_[X] for a node X will return
a node Y with memory that has the nearest distance? In other words,
caching the value returned by local_memory_node(X)?
Yes, you are right.
That doesn't seem to be what it's doing since numa_node_id() is the node
of the cpu that current is running on so this ends up getting initialized
to whatever local_memory_node(cpu_to_node(cpu)) is for the last bit set in
cpu_possible_mask.
Yes, I made a mistake.
Thanks for pointer.
I fix it and attach v2.
Now I'm out of office, so I'm not sure this second version is correct :(
Thanks.
----------8<--------------
From bf691e7eb07f966e3aed251eaeb18f229ee32d1f Mon Sep 17 00:00:00 2001
From: Joonsoo Kim <redacted>
Date: Thu, 6 Feb 2014 17:07:05 +0900
Subject: [RFC PATCH 2/3 v2] topology: support node_numa_mem() for
determining the
fallback node
We need to determine the fallback node in slub allocator if the allocation
target node is memoryless node. Without it, the SLUB wrongly select
the node which has no memory and can't use a partial slab, because of node
mismatch. Introduced function, node_numa_mem(X), will return
a node Y with memory that has the nearest distance. If X is memoryless
node, it will return nearest distance node, but, if
X is normal node, it will return itself.
We will use this function in following patch to determine the fallback
node.
Signed-off-by: Joonsoo Kim <redacted>
This check wouild need to be something that checks for other contigencies
in the page allocator as well. A simple solution would be to actually run
a GFP_THIS_NODE alloc to see if you can grab a page from the proper node.
If that fails then fallback. See how fallback_alloc() does it in slab.
Same issue here. I would suggest not deactivating the slab and first check
if the node has no pages. If so then just take an object from the current
cpu slab. If that is not available do an allcoation from the indicated
node and take whatever the page allocator gave you.
From: Christoph Lameter <hidden> Date: 2014-02-06 23:13:58
On Thu, 6 Feb 2014, Joonsoo Kim wrote:
Currently, if allocation constraint to node is NUMA_NO_NODE, we search
a partial slab on numa_node_id() node. This doesn't work properly on the
system having memoryless node, since it can have no memory on that node and
there must be no partial slab on that node.
On that node, page allocation always fallback to numa_mem_id() first. So
searching a partial slab on numa_node_id() in that case is proper solution
for memoryless node case.
@@ -233,11 +233,20 @@ static inline int numa_node_id(void)*Usetheaccessorfunctionsset_numa_mem(),numa_mem_id()andcpu_to_mem().*/DECLARE_PER_CPU(int,_numa_mem_);+int_node_numa_mem_[MAX_NUMNODES];#ifndef set_numa_memstaticinlinevoidset_numa_mem(intnode){this_cpu_write(_numa_mem_,node);+_node_numa_mem_[numa_node_id()]=node;+}+#endif++#ifndef get_numa_mem+staticinlineintget_numa_mem(intnode)+{+return_node_numa_mem_[node];}#endif
@@ -260,6 +269,7 @@ static inline int cpu_to_mem(int cpu)staticinlinevoidset_cpu_numa_mem(intcpu,intnode){per_cpu(_numa_mem_,cpu)=node;+_node_numa_mem_[numa_node_id()]=node;
The intention seems to be that _node_numa_mem_[X] for a node X will return
a node Y with memory that has the nearest distance? In other words,
caching the value returned by local_memory_node(X)?
Yes, you are right.
quoted
That doesn't seem to be what it's doing since numa_node_id() is the node
of the cpu that current is running on so this ends up getting initialized
to whatever local_memory_node(cpu_to_node(cpu)) is for the last bit set in
cpu_possible_mask.
Yes, I made a mistake.
Thanks for pointer.
I fix it and attach v2.
Now I'm out of office, so I'm not sure this second version is correct :(
Thanks.
----------8<--------------
From bf691e7eb07f966e3aed251eaeb18f229ee32d1f Mon Sep 17 00:00:00 2001
From: Joonsoo Kim <redacted>
Date: Thu, 6 Feb 2014 17:07:05 +0900
Subject: [RFC PATCH 2/3 v2] topology: support node_numa_mem() for
determining the
fallback node
We need to determine the fallback node in slub allocator if the allocation
target node is memoryless node. Without it, the SLUB wrongly select
the node which has no memory and can't use a partial slab, because of node
mismatch. Introduced function, node_numa_mem(X), will return
a node Y with memory that has the nearest distance. If X is memoryless
node, it will return nearest distance node, but, if
X is normal node, it will return itself.
We will use this function in following patch to determine the fallback
node.
Signed-off-by: Joonsoo Kim <redacted>
From: David Rientjes <rientjes@google.com> Date: 2014-02-06 23:33:11
On Thu, 6 Feb 2014, Joonsoo Kim wrote:
From bf691e7eb07f966e3aed251eaeb18f229ee32d1f Mon Sep 17 00:00:00 2001
From: Joonsoo Kim <redacted>
Date: Thu, 6 Feb 2014 17:07:05 +0900
Subject: [RFC PATCH 2/3 v2] topology: support node_numa_mem() for
determining the
fallback node
We need to determine the fallback node in slub allocator if the allocation
target node is memoryless node. Without it, the SLUB wrongly select
the node which has no memory and can't use a partial slab, because of node
mismatch. Introduced function, node_numa_mem(X), will return
a node Y with memory that has the nearest distance. If X is memoryless
node, it will return nearest distance node, but, if
X is normal node, it will return itself.
We will use this function in following patch to determine the fallback
node.
I like the approach and it may fix the problem today, but it may not be
sufficient in the future: nodes may not only be memoryless but they may
also be cpuless. It's possible that a node can only have I/O, networking,
or storage devices and we can define affinity for them that is remote from
every cpu and/or memory by the ACPI specification.
It seems like a better approach would be to do this when a node is brought
online and determine the fallback node based not on the zonelists as you
do here but rather on locality (such as through a SLIT if provided, see
node_distance()).
Also, the names aren't very descriptive: {get,set}_numa_mem() doesn't make
a lot of sense in generic code. I'd suggest something like
node_to_mem_node().
This check wouild need to be something that checks for other contigencies
in the page allocator as well. A simple solution would be to actually run
a GFP_THIS_NODE alloc to see if you can grab a page from the proper node.
If that fails then fallback. See how fallback_alloc() does it in slab.
Hello, Christoph.
This !node_present_pages() ensure that allocation on this node cannot succeed.
So we can directly use numa_mem_id() here.
Same issue here. I would suggest not deactivating the slab and first check
if the node has no pages. If so then just take an object from the current
cpu slab. If that is not available do an allcoation from the indicated
node and take whatever the page allocator gave you.
Here I do is not to deactivate the slab. I first check if the node has no pages.
And then, not taking an object from the current cpu slab. Instead, checking
current cpu slab comes from proper node getting from introduced get_numa_mem().
I think that this approach is better than just taking an object whatever node
requested.
Thanks.
From: Joonsoo Kim <hidden> Date: 2014-02-07 05:48:24
On Thu, Feb 06, 2014 at 12:52:11PM -0800, David Rientjes wrote:
On Thu, 6 Feb 2014, Joonsoo Kim wrote:
quoted
From bf691e7eb07f966e3aed251eaeb18f229ee32d1f Mon Sep 17 00:00:00 2001
From: Joonsoo Kim <redacted>
Date: Thu, 6 Feb 2014 17:07:05 +0900
Subject: [RFC PATCH 2/3 v2] topology: support node_numa_mem() for
determining the
fallback node
We need to determine the fallback node in slub allocator if the allocation
target node is memoryless node. Without it, the SLUB wrongly select
the node which has no memory and can't use a partial slab, because of node
mismatch. Introduced function, node_numa_mem(X), will return
a node Y with memory that has the nearest distance. If X is memoryless
node, it will return nearest distance node, but, if
X is normal node, it will return itself.
We will use this function in following patch to determine the fallback
node.
I like the approach and it may fix the problem today, but it may not be
sufficient in the future: nodes may not only be memoryless but they may
also be cpuless. It's possible that a node can only have I/O, networking,
or storage devices and we can define affinity for them that is remote from
every cpu and/or memory by the ACPI specification.
It seems like a better approach would be to do this when a node is brought
online and determine the fallback node based not on the zonelists as you
do here but rather on locality (such as through a SLIT if provided, see
node_distance()).
Hmm...
I guess that zonelist is base on locality. Zonelist is generated using
node_distance(), so I think that it reflects locality. But, I'm not expert
on NUMA, so please let me know what I am missing here :)
Also, the names aren't very descriptive: {get,set}_numa_mem() doesn't make
a lot of sense in generic code. I'd suggest something like
node_to_mem_node().
It's much better!
If this patch eventually will be needed, I will update it.
Thanks.
From: Christoph Lameter <hidden> Date: 2014-02-07 17:50:02
On Fri, 7 Feb 2014, Joonsoo Kim wrote:
quoted
This check wouild need to be something that checks for other contigencies
in the page allocator as well. A simple solution would be to actually run
a GFP_THIS_NODE alloc to see if you can grab a page from the proper node.
If that fails then fallback. See how fallback_alloc() does it in slab.
Hello, Christoph.
This !node_present_pages() ensure that allocation on this node cannot succeed.
So we can directly use numa_mem_id() here.
Yes of course we can use numa_mem_id().
But the check is only for not having any memory at all on a node. There
are other reason for allocations to fail on a certain node. The node could
have memory that cannot be reclaimed, all dirty, beyond certain
thresholds, not in the current set of allowed nodes etc etc.
From: Christoph Lameter <hidden> Date: 2014-02-07 17:54:01
On Fri, 7 Feb 2014, Joonsoo Kim wrote:
quoted
It seems like a better approach would be to do this when a node is brought
online and determine the fallback node based not on the zonelists as you
do here but rather on locality (such as through a SLIT if provided, see
node_distance()).
Hmm...
I guess that zonelist is base on locality. Zonelist is generated using
node_distance(), so I think that it reflects locality. But, I'm not expert
on NUMA, so please let me know what I am missing here :)
The next node can be found by going through the zonelist of a node and
checking for available memory. See fallback_alloc().
There is a function node_distance() that determines the relative
performance of a memory access from one to the other node.
The building of the fallback list for every node in build_zonelists()
relies on that.
From: Christoph Lameter <hidden> Date: 2014-02-07 18:51:12
Here is a draft of a patch to make this work with memoryless nodes.
The first thing is that we modify node_match to also match if we hit an
empty node. In that case we simply take the current slab if its there.
If there is no current slab then a regular allocation occurs with the
memoryless node. The page allocator will fallback to a possible node and
that will become the current slab. Next alloc from a memoryless node
will then use that slab.
For that we also add some tracking of allocations on nodes that were not
satisfied using the empty_node[] array. A successful alloc on a node
clears that flag.
I would rather avoid the empty_node[] array since its global and there may
be thread specific allocation restrictions but it would be expensive to do
an allocation attempt via the page allocator to make sure that there is
really no page available from the page allocator.
Index: linux/mm/slub.c
===================================================================
@@ -2107,8 +2115,25 @@ static void flush_all(struct kmem_cachestaticinlineintnode_match(structpage*page,intnode){#ifdef CONFIG_NUMA-if(!page||(node!=NUMA_NO_NODE&&page_to_nid(page)!=node))+intpage_node;++/* No data means no match */+if(!page)return0;++/* Node does not matter. Therefore anything is a match */+if(node==NUMA_NO_NODE)+return1;++/* Did we hit the requested node ? */+page_node=page_to_nid(page);+if(page_node==node)+return1;++/* If the node has available data then we can use it. Mismatch */+return!empty_node[page_node];++/* Target node empty so just take anything */#endifreturn1;}
From: David Rientjes <rientjes@google.com> Date: 2014-02-08 09:57:43
On Fri, 7 Feb 2014, Joonsoo Kim wrote:
quoted
It seems like a better approach would be to do this when a node is brought
online and determine the fallback node based not on the zonelists as you
do here but rather on locality (such as through a SLIT if provided, see
node_distance()).
Hmm...
I guess that zonelist is base on locality. Zonelist is generated using
node_distance(), so I think that it reflects locality. But, I'm not expert
on NUMA, so please let me know what I am missing here :)
The zonelist is, yes, but I'm talking about memoryless and cpuless nodes.
If your solution is going to become the generic kernel API that determines
what node has local memory for a particular node, then it will have to
support all definitions of node. That includes nodes that consist solely
of I/O, chipsets, networking, or storage devices. These nodes may not
have memory or cpus, so doing it as part of onlining cpus isn't going to
be generic enough. You want a node_to_mem_node() API for all possible
node types (the possible node types listed above are straight from the
ACPI spec). For 99% of people, node_to_mem_node(X) is always going to be
X and we can optimize for that, but any solution that relies on cpu online
is probably shortsighted right now.
I think it would be much better to do this as a part of setting a node to
be online.
From: Joonsoo Kim <hidden> Date: 2014-02-10 01:09:36
On Sat, Feb 08, 2014 at 01:57:39AM -0800, David Rientjes wrote:
On Fri, 7 Feb 2014, Joonsoo Kim wrote:
quoted
quoted
It seems like a better approach would be to do this when a node is brought
online and determine the fallback node based not on the zonelists as you
do here but rather on locality (such as through a SLIT if provided, see
node_distance()).
Hmm...
I guess that zonelist is base on locality. Zonelist is generated using
node_distance(), so I think that it reflects locality. But, I'm not expert
on NUMA, so please let me know what I am missing here :)
The zonelist is, yes, but I'm talking about memoryless and cpuless nodes.
If your solution is going to become the generic kernel API that determines
what node has local memory for a particular node, then it will have to
support all definitions of node. That includes nodes that consist solely
of I/O, chipsets, networking, or storage devices. These nodes may not
have memory or cpus, so doing it as part of onlining cpus isn't going to
be generic enough. You want a node_to_mem_node() API for all possible
node types (the possible node types listed above are straight from the
ACPI spec). For 99% of people, node_to_mem_node(X) is always going to be
X and we can optimize for that, but any solution that relies on cpu online
is probably shortsighted right now.
I think it would be much better to do this as a part of setting a node to
be online.
Okay. I got your point.
I will change it to rely on node online if this patch is really needed.
Thanks!
From: Joonsoo Kim <hidden> Date: 2014-02-10 01:15:27
On Fri, Feb 07, 2014 at 01:38:55PM -0800, Nishanth Aravamudan wrote:
On 07.02.2014 [12:51:07 -0600], Christoph Lameter wrote:
quoted
Here is a draft of a patch to make this work with memoryless nodes.
Hi Christoph, this should be tested instead of Joonsoo's patch 2 (and 3)?
Hello,
I guess that your system has another problem that makes my patches inactive.
Maybe it will also affect to the Christoph's one. Could you confirm page_to_nid(),
numa_mem_id() and node_present_pages although I doubt mostly about page_to_nid()?
Thanks.
From: Joonsoo Kim <hidden> Date: 2014-02-10 01:21:56
On Fri, Feb 07, 2014 at 11:49:57AM -0600, Christoph Lameter wrote:
On Fri, 7 Feb 2014, Joonsoo Kim wrote:
quoted
quoted
This check wouild need to be something that checks for other contigencies
in the page allocator as well. A simple solution would be to actually run
a GFP_THIS_NODE alloc to see if you can grab a page from the proper node.
If that fails then fallback. See how fallback_alloc() does it in slab.
Hello, Christoph.
This !node_present_pages() ensure that allocation on this node cannot succeed.
So we can directly use numa_mem_id() here.
Yes of course we can use numa_mem_id().
But the check is only for not having any memory at all on a node. There
are other reason for allocations to fail on a certain node. The node could
have memory that cannot be reclaimed, all dirty, beyond certain
thresholds, not in the current set of allowed nodes etc etc.
Yes. There are many other cases, but I prefer that we think them separately.
Maybe they needs another approach. For now, to solve memoryless node problem,
my solution is enough and safe.
Thanks.
From: Joonsoo Kim <hidden> Date: 2014-02-10 01:29:11
On Fri, Feb 07, 2014 at 12:51:07PM -0600, Christoph Lameter wrote:
Here is a draft of a patch to make this work with memoryless nodes.
The first thing is that we modify node_match to also match if we hit an
empty node. In that case we simply take the current slab if its there.
Why not inspecting whether we can get the page on the best node such as
numa_mem_id() node?
quoted hunk
If there is no current slab then a regular allocation occurs with the
memoryless node. The page allocator will fallback to a possible node and
that will become the current slab. Next alloc from a memoryless node
will then use that slab.
For that we also add some tracking of allocations on nodes that were not
satisfied using the empty_node[] array. A successful alloc on a node
clears that flag.
I would rather avoid the empty_node[] array since its global and there may
be thread specific allocation restrictions but it would be expensive to do
an allocation attempt via the page allocator to make sure that there is
really no page available from the page allocator.
Index: linux/mm/slub.c
===================================================================
Hi Christoph,
On 07.02.2014 [12:51:07 -0600], Christoph Lameter wrote:
Here is a draft of a patch to make this work with memoryless nodes.
The first thing is that we modify node_match to also match if we hit an
empty node. In that case we simply take the current slab if its there.
If there is no current slab then a regular allocation occurs with the
memoryless node. The page allocator will fallback to a possible node and
that will become the current slab. Next alloc from a memoryless node
will then use that slab.
For that we also add some tracking of allocations on nodes that were not
satisfied using the empty_node[] array. A successful alloc on a node
clears that flag.
I would rather avoid the empty_node[] array since its global and there may
be thread specific allocation restrictions but it would be expensive to do
an allocation attempt via the page allocator to make sure that there is
really no page available from the page allocator.
With this patch on our test system (I pulled out the numa_mem_id()
change, since you Acked Joonsoo's already), on top of 3.13.0 + my
kthread locality change + CONFIG_HAVE_MEMORYLESS_NODES + Joonsoo's RFC
patch 1):
MemTotal: 8264704 kB
MemFree: 5924608 kB
...
Slab: 1402496 kB
SReclaimable: 102848 kB
SUnreclaim: 1299648 kB
And Anton's slabusage reports:
slab mem objs slabs
used active active
------------------------------------------------------------
kmalloc-16384 207 MB 98.60% 100.00%
task_struct 134 MB 97.82% 100.00%
kmalloc-8192 117 MB 100.00% 100.00%
pgtable-2^12 111 MB 100.00% 100.00%
pgtable-2^10 104 MB 100.00% 100.00%
For comparison, Anton's patch applied at the same point in the series:
meminfo:
MemTotal: 8264704 kB
MemFree: 4150464 kB
...
Slab: 1590336 kB
SReclaimable: 208768 kB
SUnreclaim: 1381568 kB
slabusage:
slab mem objs slabs
used active active
------------------------------------------------------------
kmalloc-16384 227 MB 98.63% 100.00%
kmalloc-8192 130 MB 100.00% 100.00%
task_struct 129 MB 97.73% 100.00%
pgtable-2^12 112 MB 100.00% 100.00%
pgtable-2^10 106 MB 100.00% 100.00%
Consider this patch:
Acked-by: Nishanth Aravamudan <redacted>
Tested-by: Nishanth Aravamudan <redacted>
I was thinking about your concerns about empty_node[]. Would it make
sense to use a helper function, rather than direct access to
direct_node, such as:
bool is_node_empty(int nid)
void set_node_empty(int nid, bool empty)
which we stub out if !HAVE_MEMORYLESS_NODES to return false and noop
respectively?
That way only architectures that have memoryless nodes pay the penalty
of the array allocation?
Thanks,
Nish
@@ -2107,8 +2115,25 @@ static void flush_all(struct kmem_cachestaticinlineintnode_match(structpage*page,intnode){#ifdef CONFIG_NUMA-if(!page||(node!=NUMA_NO_NODE&&page_to_nid(page)!=node))+intpage_node;++/* No data means no match */+if(!page)return0;++/* Node does not matter. Therefore anything is a match */+if(node==NUMA_NO_NODE)+return1;++/* Did we hit the requested node ? */+page_node=page_to_nid(page);+if(page_node==node)+return1;++/* If the node has available data then we can use it. Mismatch */+return!empty_node[page_node];++/* Target node empty so just take anything */#endifreturn1;}
From: Joonsoo Kim <hidden> Date: 2014-02-11 07:42:03
On Mon, Feb 10, 2014 at 11:13:21AM -0800, Nishanth Aravamudan wrote:
Hi Christoph,
On 07.02.2014 [12:51:07 -0600], Christoph Lameter wrote:
quoted
Here is a draft of a patch to make this work with memoryless nodes.
The first thing is that we modify node_match to also match if we hit an
empty node. In that case we simply take the current slab if its there.
If there is no current slab then a regular allocation occurs with the
memoryless node. The page allocator will fallback to a possible node and
that will become the current slab. Next alloc from a memoryless node
will then use that slab.
For that we also add some tracking of allocations on nodes that were not
satisfied using the empty_node[] array. A successful alloc on a node
clears that flag.
I would rather avoid the empty_node[] array since its global and there may
be thread specific allocation restrictions but it would be expensive to do
an allocation attempt via the page allocator to make sure that there is
really no page available from the page allocator.
With this patch on our test system (I pulled out the numa_mem_id()
change, since you Acked Joonsoo's already), on top of 3.13.0 + my
kthread locality change + CONFIG_HAVE_MEMORYLESS_NODES + Joonsoo's RFC
patch 1):
MemTotal: 8264704 kB
MemFree: 5924608 kB
...
Slab: 1402496 kB
SReclaimable: 102848 kB
SUnreclaim: 1299648 kB
And Anton's slabusage reports:
slab mem objs slabs
used active active
------------------------------------------------------------
kmalloc-16384 207 MB 98.60% 100.00%
task_struct 134 MB 97.82% 100.00%
kmalloc-8192 117 MB 100.00% 100.00%
pgtable-2^12 111 MB 100.00% 100.00%
pgtable-2^10 104 MB 100.00% 100.00%
For comparison, Anton's patch applied at the same point in the series:
meminfo:
MemTotal: 8264704 kB
MemFree: 4150464 kB
...
Slab: 1590336 kB
SReclaimable: 208768 kB
SUnreclaim: 1381568 kB
slabusage:
slab mem objs slabs
used active active
------------------------------------------------------------
kmalloc-16384 227 MB 98.63% 100.00%
kmalloc-8192 130 MB 100.00% 100.00%
task_struct 129 MB 97.73% 100.00%
pgtable-2^12 112 MB 100.00% 100.00%
pgtable-2^10 106 MB 100.00% 100.00%
Consider this patch:
Acked-by: Nishanth Aravamudan <redacted>
Tested-by: Nishanth Aravamudan <redacted>
Hello,
I still think that there is another problem.
Your report about CONFIG_SLAB said that SLAB uses just 200MB.
Below is your previous report.
Ok, with your patches applied and CONFIG_SLAB enabled:
MemTotal: 8264640 kB
MemFree: 7119680 kB
Slab: 207232 kB
SReclaimable: 32896 kB
SUnreclaim: 174336 kB
The number on CONFIG_SLUB with these patches tell us that SLUB uses 1.4GB.
There is large difference on slab usage.
And, I should note that number of active objects on slabinfo can be wrong
on some situation, since it doesn't consider cpu slab (and cpu partial slab).
I recommend to confirm page_to_nid() and other things as I mentioned earlier.
Thanks.
From: Christoph Lameter <hidden> Date: 2014-02-11 18:45:32
On Mon, 10 Feb 2014, Joonsoo Kim wrote:
On Fri, Feb 07, 2014 at 12:51:07PM -0600, Christoph Lameter wrote:
quoted
Here is a draft of a patch to make this work with memoryless nodes.
The first thing is that we modify node_match to also match if we hit an
empty node. In that case we simply take the current slab if its there.
Why not inspecting whether we can get the page on the best node such as
numa_mem_id() node?
Its expensive to do so.
empty_node cannot be set on memoryless node, since page allocation would
succeed on different node.
Ok then we need to add a check for being on the rignt node there too.
From: Christoph Lameter <hidden> Date: 2014-02-12 22:16:16
Here is another patch with some fixes. The additional logic is only
compiled in if CONFIG_HAVE_MEMORYLESS_NODES is set.
Subject: slub: Memoryless node support
Support memoryless nodes by tracking which allocations are failing.
Allocations targeted to the nodes without memory fall back to the
current available per cpu objects and if that is not available will
create a new slab using the page allocator to fallback from the
memoryless node to some other node.
Signed-off-by: Christoph Lameter <redacted>
Index: linux/mm/slub.c
===================================================================
On 12.02.2014 [16:16:11 -0600], Christoph Lameter wrote:
Here is another patch with some fixes. The additional logic is only
compiled in if CONFIG_HAVE_MEMORYLESS_NODES is set.
Subject: slub: Memoryless node support
Support memoryless nodes by tracking which allocations are failing.
Allocations targeted to the nodes without memory fall back to the
current available per cpu objects and if that is not available will
create a new slab using the page allocator to fallback from the
memoryless node to some other node.
I'll try and retest this once the LPAR in question comes free. Hopefully
in the next day or two.
Thanks,
Nish
quoted hunk
Signed-off-by: Christoph Lameter <redacted>
Index: linux/mm/slub.c
===================================================================
Hi Joonsoo,
On 11.02.2014 [16:42:00 +0900], Joonsoo Kim wrote:
On Mon, Feb 10, 2014 at 11:13:21AM -0800, Nishanth Aravamudan wrote:
quoted
Hi Christoph,
On 07.02.2014 [12:51:07 -0600], Christoph Lameter wrote:
quoted
Here is a draft of a patch to make this work with memoryless nodes.
The first thing is that we modify node_match to also match if we hit an
empty node. In that case we simply take the current slab if its there.
If there is no current slab then a regular allocation occurs with the
memoryless node. The page allocator will fallback to a possible node and
that will become the current slab. Next alloc from a memoryless node
will then use that slab.
For that we also add some tracking of allocations on nodes that were not
satisfied using the empty_node[] array. A successful alloc on a node
clears that flag.
I would rather avoid the empty_node[] array since its global and there may
be thread specific allocation restrictions but it would be expensive to do
an allocation attempt via the page allocator to make sure that there is
really no page available from the page allocator.
With this patch on our test system (I pulled out the numa_mem_id()
change, since you Acked Joonsoo's already), on top of 3.13.0 + my
kthread locality change + CONFIG_HAVE_MEMORYLESS_NODES + Joonsoo's RFC
patch 1):
MemTotal: 8264704 kB
MemFree: 5924608 kB
...
Slab: 1402496 kB
SReclaimable: 102848 kB
SUnreclaim: 1299648 kB
And Anton's slabusage reports:
slab mem objs slabs
used active active
------------------------------------------------------------
kmalloc-16384 207 MB 98.60% 100.00%
task_struct 134 MB 97.82% 100.00%
kmalloc-8192 117 MB 100.00% 100.00%
pgtable-2^12 111 MB 100.00% 100.00%
pgtable-2^10 104 MB 100.00% 100.00%
For comparison, Anton's patch applied at the same point in the series:
meminfo:
MemTotal: 8264704 kB
MemFree: 4150464 kB
...
Slab: 1590336 kB
SReclaimable: 208768 kB
SUnreclaim: 1381568 kB
slabusage:
slab mem objs slabs
used active active
------------------------------------------------------------
kmalloc-16384 227 MB 98.63% 100.00%
kmalloc-8192 130 MB 100.00% 100.00%
task_struct 129 MB 97.73% 100.00%
pgtable-2^12 112 MB 100.00% 100.00%
pgtable-2^10 106 MB 100.00% 100.00%
Consider this patch:
Acked-by: Nishanth Aravamudan <redacted>
Tested-by: Nishanth Aravamudan <redacted>
Hello,
I still think that there is another problem.
Your report about CONFIG_SLAB said that SLAB uses just 200MB.
Below is your previous report.
Ok, with your patches applied and CONFIG_SLAB enabled:
MemTotal: 8264640 kB
MemFree: 7119680 kB
Slab: 207232 kB
SReclaimable: 32896 kB
SUnreclaim: 174336 kB
The number on CONFIG_SLUB with these patches tell us that SLUB uses 1.4GB.
There is large difference on slab usage.
Agreed. But, at least for now, this gets us to not OOM all the time :) I
think that's significant progress. I will continue to look at this
issue for where the other gaps are, but would like to see Christoph's
latest patch get merged (pending my re-testing).
And, I should note that number of active objects on slabinfo can be
wrong on some situation, since it doesn't consider cpu slab (and cpu
partial slab).
Well, I grabbed everything from /sys/kernel/slab for you in the
tarballs, I believe.
I recommend to confirm page_to_nid() and other things as I mentioned
earlier.
I believe these all work once CONFIG_HAVE_MEMORYLESS_NODES was set for
ppc64, but will test it again when I have access to the test system.
Also, given that only ia64 and (hopefuly soon) ppc64 can set
CONFIG_HAVE_MEMORYLESS_NODES, does that mean x86_64 can't have
memoryless nodes present? Even with fakenuma? Just curious.
-Nish
From: Joonsoo Kim <hidden> Date: 2014-02-17 06:52:50
On Wed, Feb 12, 2014 at 04:16:11PM -0600, Christoph Lameter wrote:
Here is another patch with some fixes. The additional logic is only
compiled in if CONFIG_HAVE_MEMORYLESS_NODES is set.
Subject: slub: Memoryless node support
Support memoryless nodes by tracking which allocations are failing.
I still don't understand why this tracking is needed.
All we need for allcation targeted to memoryless node is to fallback proper
node, that it, numa_mem_id() node of targeted node. My previous patch
implements it and use proper fallback node on every allocation code path.
Why this tracking is needed? Please elaborate more on this.
quoted hunk
Allocations targeted to the nodes without memory fall back to the
current available per cpu objects and if that is not available will
create a new slab using the page allocator to fallback from the
memoryless node to some other node.
Signed-off-by: Christoph Lameter <redacted>
This isn't enough.
Consider that allcation targeted to memoryless node.
get_partial_node() always fails even if there are some partial slab on
memoryless node's neareast node.
We should fallback to some proper node in this case, since there is no slab
on memoryless node.
Thanks.
From: Joonsoo Kim <hidden> Date: 2014-02-17 07:00:44
On Wed, Feb 12, 2014 at 10:51:37PM -0800, Nishanth Aravamudan wrote:
Hi Joonsoo,
Also, given that only ia64 and (hopefuly soon) ppc64 can set
CONFIG_HAVE_MEMORYLESS_NODES, does that mean x86_64 can't have
memoryless nodes present? Even with fakenuma? Just curious.
I don't know, because I'm not expert on NUMA system :)
At first glance, fakenuma can't be used for testing
CONFIG_HAVE_MEMORYLESS_NODES. Maybe some modification is needed.
Thanks.
From: Christoph Lameter <hidden> Date: 2014-02-18 16:38:05
On Mon, 17 Feb 2014, Joonsoo Kim wrote:
On Wed, Feb 12, 2014 at 04:16:11PM -0600, Christoph Lameter wrote:
quoted
Here is another patch with some fixes. The additional logic is only
compiled in if CONFIG_HAVE_MEMORYLESS_NODES is set.
Subject: slub: Memoryless node support
Support memoryless nodes by tracking which allocations are failing.
I still don't understand why this tracking is needed.
Its an optimization to avoid calling the page allocator to figure out if
there is memory available on a particular node.
All we need for allcation targeted to memoryless node is to fallback proper
node, that it, numa_mem_id() node of targeted node. My previous patch
implements it and use proper fallback node on every allocation code path.
Why this tracking is needed? Please elaborate more on this.
Its too slow to do that on every alloc. One needs to be able to satisfy
most allocations without switching percpu slabs for optimal performance.
quoted
Allocations targeted to the nodes without memory fall back to the
current available per cpu objects and if that is not available will
create a new slab using the page allocator to fallback from the
memoryless node to some other node.
And what about the next alloc? Assuem there are N allocs from a memoryless
node this means we push back the partial slab on each alloc and then fall
back?
This isn't enough.
Consider that allcation targeted to memoryless node.
It will not common get there because of the tracking. Instead a per cpu
object will be used.
get_partial_node() always fails even if there are some partial slab on
memoryless node's neareast node.
Correct and that leads to a page allocator action whereupon the node will
be marked as empty.
We should fallback to some proper node in this case, since there is no slab
on memoryless node.
NUMA is about optimization of memory allocations. It is often *not* about
correctness but heuristics are used in many cases. F.e. see the zone
reclaim logic, zone reclaim mode, fallback scenarios in the page allocator
etc etc.
From: Christoph Lameter <hidden> Date: 2014-02-18 16:57:13
On Mon, 17 Feb 2014, Joonsoo Kim wrote:
On Wed, Feb 12, 2014 at 10:51:37PM -0800, Nishanth Aravamudan wrote:
quoted
Hi Joonsoo,
Also, given that only ia64 and (hopefuly soon) ppc64 can set
CONFIG_HAVE_MEMORYLESS_NODES, does that mean x86_64 can't have
memoryless nodes present? Even with fakenuma? Just curious.
x86_64 currently does not support memoryless nodes otherwise it would
have set CONFIG_HAVE_MEMORYLESS_NODES in the kconfig. Memoryless nodes are
a bit strange given that the NUMA paradigm is to have NUMA nodes (meaning
memory) with processors. MEMORYLESS nodes means that we have a fake NUMA
node without memory but just processors. Not very efficient. Not sure why
people use these configurations.
I don't know, because I'm not expert on NUMA system :)
At first glance, fakenuma can't be used for testing
CONFIG_HAVE_MEMORYLESS_NODES. Maybe some modification is needed.
Well yeah. You'd have to do some mods to enable that testing.
On 12.02.2014 [16:16:11 -0600], Christoph Lameter wrote:
Here is another patch with some fixes. The additional logic is only
compiled in if CONFIG_HAVE_MEMORYLESS_NODES is set.
Subject: slub: Memoryless node support
Support memoryless nodes by tracking which allocations are failing.
Allocations targeted to the nodes without memory fall back to the
current available per cpu objects and if that is not available will
create a new slab using the page allocator to fallback from the
memoryless node to some other node.
Signed-off-by: Christoph Lameter <redacted>
On 18.02.2014 [10:57:09 -0600], Christoph Lameter wrote:
On Mon, 17 Feb 2014, Joonsoo Kim wrote:
quoted
On Wed, Feb 12, 2014 at 10:51:37PM -0800, Nishanth Aravamudan wrote:
quoted
Hi Joonsoo,
Also, given that only ia64 and (hopefuly soon) ppc64 can set
CONFIG_HAVE_MEMORYLESS_NODES, does that mean x86_64 can't have
memoryless nodes present? Even with fakenuma? Just curious.
x86_64 currently does not support memoryless nodes otherwise it would
have set CONFIG_HAVE_MEMORYLESS_NODES in the kconfig. Memoryless nodes are
a bit strange given that the NUMA paradigm is to have NUMA nodes (meaning
memory) with processors. MEMORYLESS nodes means that we have a fake NUMA
node without memory but just processors. Not very efficient. Not sure why
people use these configurations.
Well, on powerpc, with the hypervisor providing the resources and the
topology, you can have cpuless and memoryless nodes. I'm not sure how
"fake" the NUMA is -- as I think since the resources are virtualized to
be one system, it's logically possible that the actual topology of the
resources can be CPUs from physical node 0 and memory from physical node
2. I would think with KVM on a sufficiently large (physically NUMA
x86_64) and loaded system, one could cause the same sort of
configuration to occur for a guest?
In any case, these configurations happen fairly often on long-running
(not rebooted) systems as LPARs are created/destroyed, resources are
DLPAR'd in and out of LPARs, etc.
quoted
I don't know, because I'm not expert on NUMA system :)
At first glance, fakenuma can't be used for testing
CONFIG_HAVE_MEMORYLESS_NODES. Maybe some modification is needed.
Well yeah. You'd have to do some mods to enable that testing.
I might look into it, as it might have sped up testing these changes.
Thanks,
Nish
From: Christoph Lameter <hidden> Date: 2014-02-18 19:58:24
On Tue, 18 Feb 2014, Nishanth Aravamudan wrote:
Well, on powerpc, with the hypervisor providing the resources and the
topology, you can have cpuless and memoryless nodes. I'm not sure how
"fake" the NUMA is -- as I think since the resources are virtualized to
be one system, it's logically possible that the actual topology of the
resources can be CPUs from physical node 0 and memory from physical node
2. I would think with KVM on a sufficiently large (physically NUMA
x86_64) and loaded system, one could cause the same sort of
configuration to occur for a guest?
Ok but since you have a virtualized environment: Why not provide a fake
home node with fake memory that could be anywhere? This would avoid the
whole problem of supporting such a config at the kernel level.
Do not have a fake node that has no memory.
In any case, these configurations happen fairly often on long-running
(not rebooted) systems as LPARs are created/destroyed, resources are
DLPAR'd in and out of LPARs, etc.
Ok then also move the memory of the local node somewhere?
I might look into it, as it might have sped up testing these changes.
I guess that will be necessary in order to support the memoryless nodes
long term.
On 18.02.2014 [13:58:20 -0600], Christoph Lameter wrote:
On Tue, 18 Feb 2014, Nishanth Aravamudan wrote:
quoted
Well, on powerpc, with the hypervisor providing the resources and the
topology, you can have cpuless and memoryless nodes. I'm not sure how
"fake" the NUMA is -- as I think since the resources are virtualized to
be one system, it's logically possible that the actual topology of the
resources can be CPUs from physical node 0 and memory from physical node
2. I would think with KVM on a sufficiently large (physically NUMA
x86_64) and loaded system, one could cause the same sort of
configuration to occur for a guest?
Ok but since you have a virtualized environment: Why not provide a fake
home node with fake memory that could be anywhere? This would avoid the
whole problem of supporting such a config at the kernel level.
We use the topology provided by the hypervisor, it does actually reflect
where CPUs and memory are, and their corresponding performance/NUMA
characteristics.
Do not have a fake node that has no memory.
quoted
In any case, these configurations happen fairly often on long-running
(not rebooted) systems as LPARs are created/destroyed, resources are
DLPAR'd in and out of LPARs, etc.
Ok then also move the memory of the local node somewhere?
This happens below the OS, we don't control the hypervisor's decisions.
I'm not sure if that's what you are suggesting.
Thanks,
Nish
From: Christoph Lameter <hidden> Date: 2014-02-18 21:49:26
On Tue, 18 Feb 2014, Nishanth Aravamudan wrote:
We use the topology provided by the hypervisor, it does actually reflect
where CPUs and memory are, and their corresponding performance/NUMA
characteristics.
And so there are actually nodes without memory that have processors?
Can the hypervisor or the linux arch code be convinced to ignore nodes
without memory or assign a sane default node to processors?
quoted
Ok then also move the memory of the local node somewhere?
This happens below the OS, we don't control the hypervisor's decisions.
I'm not sure if that's what you are suggesting.
You could also do this from the powerpc arch code by sanitizing the
processor / node information that is then used by Linux.
On 18.02.2014 [15:49:22 -0600], Christoph Lameter wrote:
On Tue, 18 Feb 2014, Nishanth Aravamudan wrote:
quoted
We use the topology provided by the hypervisor, it does actually reflect
where CPUs and memory are, and their corresponding performance/NUMA
characteristics.
And so there are actually nodes without memory that have processors?
Virtually (topologically as indicated to Linux), yes. Physically, I
don't think they are, but they might be exhausted, which is we get sort
of odd-appearing NUMA configurations.
Can the hypervisor or the linux arch code be convinced to ignore nodes
without memory or assign a sane default node to processors?
I think this happens quite often, so I don't know that we want to ignore
the performance impact of the underlying NUMA configuration. I guess we
could special-case memoryless/cpuless configurations somewhat, but I
don't think there's any reason to do that if we can make memoryless-node
support work in-kernel?
quoted
quoted
Ok then also move the memory of the local node somewhere?
This happens below the OS, we don't control the hypervisor's decisions.
I'm not sure if that's what you are suggesting.
You could also do this from the powerpc arch code by sanitizing the
processor / node information that is then used by Linux.
From: Christoph Lameter <hidden> Date: 2014-02-19 16:11:38
On Tue, 18 Feb 2014, Nishanth Aravamudan wrote:
the performance impact of the underlying NUMA configuration. I guess we
could special-case memoryless/cpuless configurations somewhat, but I
don't think there's any reason to do that if we can make memoryless-node
support work in-kernel?
Well we can make it work in-kernel but it always has been a bit wacky (as
is the idea of numa "memory" nodes without memory).
From: David Rientjes <rientjes@google.com> Date: 2014-02-19 22:03:31
On Tue, 18 Feb 2014, Christoph Lameter wrote:
Ok but since you have a virtualized environment: Why not provide a fake
home node with fake memory that could be anywhere? This would avoid the
whole problem of supporting such a config at the kernel level.
By acpi, the abstraction of a NUMA node can include any combination of
cpus, memory, I/O resources, networking, or storage devices. This allows
two memoryless nodes, for example, to have different proximity to memory.
From: Christoph Lameter <hidden> Date: 2014-02-20 16:03:08
On Wed, 19 Feb 2014, David Rientjes wrote:
On Tue, 18 Feb 2014, Christoph Lameter wrote:
quoted
Its an optimization to avoid calling the page allocator to figure out if
there is memory available on a particular node.
Thus this patch breaks with memory hot-add for a memoryless node.
As soon as the per cpu slab is exhausted the node number of the so far
"empty" node will be used for allocation. That will be sucessfull and the
node will no longer be marked as empty.
From: Joonsoo Kim <hidden> Date: 2014-02-24 05:08:44
On Tue, Feb 18, 2014 at 10:38:01AM -0600, Christoph Lameter wrote:
On Mon, 17 Feb 2014, Joonsoo Kim wrote:
quoted
On Wed, Feb 12, 2014 at 04:16:11PM -0600, Christoph Lameter wrote:
quoted
Here is another patch with some fixes. The additional logic is only
compiled in if CONFIG_HAVE_MEMORYLESS_NODES is set.
Subject: slub: Memoryless node support
Support memoryless nodes by tracking which allocations are failing.
I still don't understand why this tracking is needed.
Its an optimization to avoid calling the page allocator to figure out if
there is memory available on a particular node.
quoted
All we need for allcation targeted to memoryless node is to fallback proper
node, that it, numa_mem_id() node of targeted node. My previous patch
implements it and use proper fallback node on every allocation code path.
Why this tracking is needed? Please elaborate more on this.
Its too slow to do that on every alloc. One needs to be able to satisfy
most allocations without switching percpu slabs for optimal performance.
I don't think that we need to switch percpu slabs on every alloc.
Allocation targeted to specific node is rare. And most of these allocations
may be targeted to either numa_node_id() or numa_mem_id(). My patch considers
these cases, so most of allocations are processed by percpu slabs. There is
no suboptimal performance.
quoted
quoted
Allocations targeted to the nodes without memory fall back to the
current available per cpu objects and if that is not available will
create a new slab using the page allocator to fallback from the
memoryless node to some other node.
And what about the next alloc? Assuem there are N allocs from a memoryless
node this means we push back the partial slab on each alloc and then fall
back?
This isn't enough.
Consider that allcation targeted to memoryless node.
It will not common get there because of the tracking. Instead a per cpu
object will be used.
quoted
get_partial_node() always fails even if there are some partial slab on
memoryless node's neareast node.
Correct and that leads to a page allocator action whereupon the node will
be marked as empty.
Why do we need to request to a page allocator if there is partial slab?
Checking whether node is memoryless or not is really easy, so we don't need
to skip this. To skip this is suboptimal solution.
quoted
We should fallback to some proper node in this case, since there is no slab
on memoryless node.
NUMA is about optimization of memory allocations. It is often *not* about
correctness but heuristics are used in many cases. F.e. see the zone
reclaim logic, zone reclaim mode, fallback scenarios in the page allocator
etc etc.
Okay. But, 'do our best' is preferable to me.
Thanks.
From: Christoph Lameter <hidden> Date: 2014-02-24 19:54:39
On Mon, 24 Feb 2014, Joonsoo Kim wrote:
quoted
It will not common get there because of the tracking. Instead a per cpu
object will be used.
quoted
get_partial_node() always fails even if there are some partial slab on
memoryless node's neareast node.
Correct and that leads to a page allocator action whereupon the node will
be marked as empty.
Why do we need to request to a page allocator if there is partial slab?
Checking whether node is memoryless or not is really easy, so we don't need
to skip this. To skip this is suboptimal solution.
The page allocator action is also used to determine to which other node we
should fall back if the node is empty. So we need to call the page
allocator when the per cpu slab is exhaused with the node of the
memoryless node to get memory from the proper fallback node.
On 24.02.2014 [13:54:35 -0600], Christoph Lameter wrote:
On Mon, 24 Feb 2014, Joonsoo Kim wrote:
quoted
quoted
It will not common get there because of the tracking. Instead a per cpu
object will be used.
quoted
get_partial_node() always fails even if there are some partial slab on
memoryless node's neareast node.
Correct and that leads to a page allocator action whereupon the node will
be marked as empty.
Why do we need to request to a page allocator if there is partial slab?
Checking whether node is memoryless or not is really easy, so we don't need
to skip this. To skip this is suboptimal solution.
The page allocator action is also used to determine to which other node we
should fall back if the node is empty. So we need to call the page
allocator when the per cpu slab is exhaused with the node of the
memoryless node to get memory from the proper fallback node.
Where do we stand with these patches? I feel like no resolution was
really found...
Thanks,
Nish
On 06.02.2014 [17:07:04 +0900], Joonsoo Kim wrote:
Currently, if allocation constraint to node is NUMA_NO_NODE, we search
a partial slab on numa_node_id() node. This doesn't work properly on the
system having memoryless node, since it can have no memory on that node and
there must be no partial slab on that node.
On that node, page allocation always fallback to numa_mem_id() first. So
searching a partial slab on numa_node_id() in that case is proper solution
for memoryless node case.
Signed-off-by: Joonsoo Kim <redacted>
Acked-by: Nishanth Aravamudan <redacted>
Joonsoo, would you send this one on to Andrew?
Thanks,
Nish
From: Joonsoo Kim <hidden> Date: 2014-05-19 02:39:13
On Fri, May 16, 2014 at 04:37:35PM -0700, Nishanth Aravamudan wrote:
On 06.02.2014 [17:07:04 +0900], Joonsoo Kim wrote:
quoted
Currently, if allocation constraint to node is NUMA_NO_NODE, we search
a partial slab on numa_node_id() node. This doesn't work properly on the
system having memoryless node, since it can have no memory on that node and
there must be no partial slab on that node.
On that node, page allocation always fallback to numa_mem_id() first. So
searching a partial slab on numa_node_id() in that case is proper solution
for memoryless node case.
Signed-off-by: Joonsoo Kim <redacted>
Acked-by: Nishanth Aravamudan <redacted>
Joonsoo, would you send this one on to Andrew?
From: David Rientjes <rientjes@google.com> Date: 2014-06-05 00:13:49
On Wed, 21 May 2014, Joonsoo Kim wrote:
quoted hunk
Currently, if allocation constraint to node is NUMA_NO_NODE, we search
a partial slab on numa_node_id() node. This doesn't work properly on the
system having memoryless node, since it can have no memory on that node and
there must be no partial slab on that node.
On that node, page allocation always fallback to numa_mem_id() first. So
searching a partial slab on numa_node_id() in that case is proper solution
for memoryless node case.
Acked-by: Nishanth Aravamudan <redacted>
Acked-by: David Rientjes <rientjes@google.com>
Acked-by: Christoph Lameter <redacted>
Signed-off-by: Joonsoo Kim <redacted>