Performance regression in scsi sequential throughput (iozone) dueto "e084b - page-allocator: preserve PFN ordering when __GFP_COLD is set"
From: Christian Ehrhardt
Date: Mon Dec 07 2009 - 09:40:05 EST
Hi,
I tracked a huge performance regression for a while and got it bisected
down to commit "e084b2d95e48b31aa45f9c49ffc6cdae8bdb21d4 -
page-allocator: preserve PFN ordering when __GFP_COLD is set".
The scenario I'm running is a low memory system (256M total), that does
sequential I/O with parallel iozone processes.
One process per disk, each process reading a 2Gb file. The disks I use
are fcp scsi disks attached to a s390 host. File system is ext2.
The regression appears as up to 76% loss in throughput at 16 processes
(processes are scaled from 1 to 64, performance is bad everywhere - 16
is just the peak - avg loss is about 40% throughput).
I already know that giving the system just a bit (~64m+) more memory
solves the issue almost completely, probably because there is almost no
"memory pressure" left in that cases.
I also know that using direct-I/O instead of I/O through page cache
doesn't have the problem at all.
Comparing sysstat data taken while running with the kernels just with &
without the bisected patch shows nothing obvious except that I/O seems
to take much longer (lower interrupt ratio etc).
The patch alone looks very reasonable, so I'd prefer understanding and
fixing the real issue instead of getting it eventually reverted due to
this regression being larger than the one it was intended to fix.
In the patch it is clear that hot pages (cold==0) freed in rmqueue_bulk
should behave like before. So maybe the question is "are our pages cold
while they shouldn't be"?
Well I don't really have a clue yet to explain how patch e084b exactly
causes that big regression, ideas welcome :-)
Kind regards,
Christian
P.S: The original patch is concise enough to attach it here to act as
reference without bloating the mail too much:
commit e084b2d95e48b31aa45f9c49ffc6cdae8bdb21d4
Author: Mel Gorman <mel@xxxxxxxxx>
Date: Wed Jul 29 15:02:04 2009 -0700
page-allocator: preserve PFN ordering when __GFP_COLD is set
Fix a post-2.6.24 performace regression caused by
3dfa5721f12c3d5a441448086bee156887daa961 ("page-allocator: preserve PFN
ordering when __GFP_COLD is set").
Narayanan reports "The regression is around 15%. There is no disk
controller
as our setup is based on Samsung OneNAND used as a memory mapped
device on a
OMAP2430 based board."
The page allocator tries to preserve contiguous PFN ordering when
returning
pages such that repeated callers to the allocator have a strong
chance of
getting physically contiguous pages, particularly when external
fragmentation
is low. However, of the bulk of the allocations have __GFP_COLD set
as they
are due to aio_read() for example, then the PFNs are in reverse PFN
order.
This can cause performance degration when used with IO controllers
that could
have merged the requests.
This patch attempts to preserve the contiguous ordering of PFNs for
users of
__GFP_COLD.
Signed-off-by: Mel Gorman <mel@xxxxxxxxx>
Reported-by: Narayananu Gopalakrishnan <narayanan.g@xxxxxxxxxxx>
Tested-by: Narayanan Gopalakrishnan <narayanan.g@xxxxxxxxxxx>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@xxxxxxxxxxxxxx>
Cc: <stable@xxxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index caa9268..ae28c22 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -882,7 +882,7 @@ retry_reserve:
*/
static int rmqueue_bulk(struct zone *zone, unsigned int order,
unsigned long count, struct list_head *list,
- int migratetype)
+ int migratetype, int cold)
{
int i;
@@ -901,7 +901,10 @@ static int rmqueue_bulk(struct zone *zone, unsigned
int order,
* merge IO requests if the physical pages are ordered
* properly.
*/
- list_add(&page->lru, list);
+ if (likely(cold == 0))
+ list_add(&page->lru, list);
+ else
+ list_add_tail(&page->lru, list);
set_page_private(page, migratetype);
list = &page->lru;
}
@@ -1119,7 +1122,8 @@ again:
local_irq_save(flags);
if (!pcp->count) {
pcp->count = rmqueue_bulk(zone, 0,
- pcp->batch, &pcp->list, migratetype);
+ pcp->batch, &pcp->list,
+ migratetype, cold);
if (unlikely(!pcp->count))
goto failed;
}
@@ -1138,7 +1142,8 @@ again:
/* Allocate more to the pcp list if necessary */
if (unlikely(&page->lru == &pcp->list)) {
pcp->count += rmqueue_bulk(zone, 0,
- pcp->batch, &pcp->list, migratetype);
+ pcp->batch, &pcp->list,
+ migratetype, cold);
page = list_entry(pcp->list.next, struct page, lru);
}
--
Grüsse / regards, Christian Ehrhardt
IBM Linux Technology Center, Open Virtualization
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/