Re: [PATCH 6/9] clockpro-clockpro.patch

IWAMOTO Toshihiro
2006-01-24T06:30:13Z

At Fri, 06 Jan 2006 18:01:35 +0900,
IWAMOTO Toshihiro wrote:
>
> At Thu, 5 Jan 2006 08:32:19 -0500 (EST),
> Rik van Riel wrote:
> >
> > On Thu, 5 Jan 2006, IWAMOTO Toshihiro wrote:
>
> > > In my understanding of CLOCK-Pro, such lapping causes sudden increase
> > > in the distance between Hhot and Hcold. As that distance is an
> > > important parameter of page aging/replacement decisions, I'm afraid
> > > that such lapping would result in incorrect page aging and bad
> > > performance.
> >
> > Hcold only manipulates cold pages, Hhot only manipulates hot
> > pages and the test bit on cold pages. Having one hand overtake
> > the other should not disturb things at all, since they both do
> > something different.
>
> I don't think so. Hhot turns unreferenced hot pages into cold ones,
> and those are freed if they aren't referenced before Hcold passes.
> So, the distance between those hands is a sort of "expiry timer" of
> such pages.
> The distance also affects aging of newly inserted pages.

I've added the following code to count lappings.
I also measured speeds of hands from pgrefill* and pgscan* in
/proc/vmstat.

While executing

$ while true; do cksum zero; done

, where zero is a 1100MB file and the amount of the system RAM is 1GB,
Hcold was almost twice faster than Hhot in ZONE_DMA32 (the system was
x86_64), and Hcold was steadily overtaking Hhot.
(Interestingly, in ZONE_DMA, Hhot was faster than Hcold. I think this
can be ignored for now.)

I thought this situation means that page access frequencies cannot be
correctly compared and leads to suboptimal performance, but I couldn't
prove that. However, I've managed to create an example workload where
clockpro performs worse. I'm not sure if the example is related to
this hand problem. I'll describe it in the next mail.

diff -urp linux-2.6.15-rc5-clockpro-orig/mm/clockpro.c linux-2.6.15-rc5-clockpro-20051231/mm/clockpro.c
--- linux-2.6.15-rc5-clockpro-orig/mm/clockpro.c 2006-01-24 15:05:01.000000000 +0900
+++ linux-2.6.15-rc5-clockpro-20051231/mm/clockpro.c 2006-01-13 16:36:16.000000000 +0900
@@ -119,8 +119,13 @@ static void swap_lists(struct zone *zone
static inline
void __select_list_hand(struct zone *zone, struct list_head *list)
{
- if (list_empty(list))
+ if (list_empty(list)) {
swap_lists(zone);
+ if (list == &zone->list_hand[hand_hot])
+ zone->handswapcnt++;
+ else
+ zone->handswapcnt--;
+ }
}

/*
@@ -589,6 +594,7 @@ static int stats_show(struct seq_file *m
seq_printf(m, " zone->nr_cold: %lu\n", zone->nr_cold);
seq_printf(m, " zone->nr_cold_target: %lu\n", zone->nr_cold_target);
seq_printf(m, " zone->nr_nonresident_scale: %lu\n", zone->nr_nonresident_scale);
+ seq_printf(m, " zone->handswapcnt: %ld\n", zone->handswapcnt);
seq_printf(m, " zone->present_pages: %lu\n", zone->present_pages);
seq_printf(m, " zone->free_pages: %lu\n", zone->free_pages);
seq_printf(m, " zone->pages_min: %lu\n", zone->pages_min);
diff -urp linux-2.6.15-rc5-clockpro-orig/include/linux/mmzone.h linux-2.6.15-rc5-clockpro-20051231/include/linux/mmzone.h
--- linux-2.6.15-rc5-clockpro-orig/include/linux/mmzone.h 2006-01-24 15:05:01.000000000 +0900
+++ linux-2.6.15-rc5-clockpro-20051231/include/linux/mmzone.h 2006-01-13 16:33:32.000000000 +0900
@@ -146,6 +146,7 @@ struct zone {
unsigned long nr_cold;
unsigned long nr_cold_target;
unsigned long nr_nonresident_scale;
+ long handswapcnt;

unsigned long pages_scanned; /* since last reclaim */
int all_unreclaimable; /* All pages pinned */
diff -urp linux-2.6.15-rc5-clockpro-orig/include/linux/page-flags.h linux-2.6.15-rc5-clockpro-20051231/include/linux/page-flags.h
--- linux-2.6.15-rc5-clockpro-orig/include/linux/page-flags.h 2006-01-24 15:05:01.000000000 +0900
+++ linux-2.6.15-rc5-clockpro-20051231/include/linux/page-flags.h 2006-01-16 18:17:19.000000000 +0900
@@ -155,7 +155,7 @@ extern void __mod_page_state(unsigned lo
#define mod_page_state_zone(zone, member, delta) \
do { \
unsigned offset; \
- if (is_highmem(zone)) \
+ if (is_highmem(zone) || zone == zone->zone_pgdat->node_zones + ZONE_DMA32) \
offset = offsetof(struct page_state, member##_high); \
else if (is_normal(zone)) \
offset = offsetof(struct page_state, member##_normal); \

--
IWAMOTO Toshihiro