Skip to contentSkip to conversation

zoned and jiffies based vm

PATCH New Roger Larsson 1 participant 1 message Jun 22, 2000

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 zoned and jiffies based vm

This is an attempt to try to solve the performance and CPU usage problems in vm subsystem.

During the development of this patch I have found some interesting things:

* Most read pages will end up as Referenced even if the PG_referenced bit is cleared when inserted into LRU - this is probably due to the pages being read ahead, and thus later referred...

Improvements/bugs in patch:

* does not handle age wrap of really old pages.

* does not use reused pointer.

* could use another counter (incremented at use) or mechanism instead (function that ages all pages at once).

* I am not sure how it will handle mmap002, forgot to run it before connecting to internet...

I am sending it as is since I will be away this weekend...

/RogerL

--
Home page:
http://www.norran.net/nra02596/

include/linux/mm.h +4 -1
diff -aur linux/include/linux/mm.h roger/include/linux/mm.h
@@ -148,6 +148,8 @@
 	atomic_t count;
 	unsigned long flags;	/* atomic flags, some possibly updated asynchronously */
 	struct list_head lru;
+        unsigned long lru_born; /* at jiffies */
+        long lru_reused;         /* no of times reused */
 	wait_queue_head_t wait;
 	struct page **pprev_hash;
 	struct buffer_head * buffers;
@@ -196,7 +198,8 @@
 #define SetPageError(page)	set_bit(PG_error, &(page)->flags)
 #define ClearPageError(page)	clear_bit(PG_error, &(page)->flags)
 #define PageReferenced(page)	test_bit(PG_referenced, &(page)->flags)
-#define SetPageReferenced(page)	set_bit(PG_referenced, &(page)->flags)
+#define SetPageReferenced(page)	{(page)->lru_born = jiffies; set_bit(PG_referenced, &(page)->flags);}
+#define ClearPageReferenced(page)	clear_bit(PG_referenced, &(page)->flags)
 #define PageTestandClearReferenced(page)	test_and_clear_bit(PG_referenced, &(page)->flags)
 #define PageDecrAfter(page)	test_bit(PG_decr_after, &(page)->flags)
 #define SetPageDecrAfter(page)	set_bit(PG_decr_after, &(page)->flags)
include/linux/mmzone.h +3 -0
diff -aur linux/include/linux/mmzone.h roger/include/linux/mmzone.h
@@ -32,6 +32,9 @@
 	char			zone_wake_kswapd;
 	unsigned long		pages_min, pages_low, pages_high;
 
+        int                     nr_lru_pages;
+        struct list_head        lru_cache;
+
 	/*
 	 * free areas of different sizes
 	 */
include/linux/swap.h +6 -4
diff -aur linux/include/linux/swap.h roger/include/linux/swap.h
@@ -67,7 +67,6 @@
 FASTCALL(unsigned int nr_free_pages(void));
 FASTCALL(unsigned int nr_free_buffer_pages(void));
 FASTCALL(unsigned int nr_free_highpages(void));
-extern int nr_lru_pages;
 extern atomic_t nr_async_pages;
 extern struct address_space swapper_space;
 extern atomic_t page_cache_size;
@@ -165,16 +164,19 @@
  */
 #define	lru_cache_add(page)			\
 do {						\
+        zone_t *zone = (page)->zone;            \
 	spin_lock(&pagemap_lru_lock);		\
-	list_add(&(page)->lru, &lru_cache);	\
-	nr_lru_pages++;				\
+	list_add(&(page)->lru, &zone->lru_cache);	\
+        page->lru_born = jiffies;               \
+        page->lru_reused = 1;                   \
+	zone->nr_lru_pages++;				\
 	spin_unlock(&pagemap_lru_lock);		\
 } while (0)
 
 #define	__lru_cache_del(page)			\
 do {						\
 	list_del(&(page)->lru);			\
-	nr_lru_pages--;				\
+	(page)->zone->nr_lru_pages--;		\
 } while (0)
 
 #define	lru_cache_del(page)			\
mm/filemap.c +114 -23

187 lines not on this page · raw message

mm/page_alloc.c +23 -5
diff -aur linux/mm/page_alloc.c roger/mm/page_alloc.c
@@ -25,7 +25,6 @@
 #endif
 
 int nr_swap_pages;
-int nr_lru_pages;
 pg_data_t *pgdat_list;
 
 static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" };
@@ -313,6 +312,22 @@
 }
 
 /*
+ * Total amount of free (allocatable) RAM:
+ */
+unsigned int nr_lru_pages (void)
+{
+	unsigned int sum;
+	zone_t *zone;
+	int i;
+
+	sum = 0;
+	for (i = 0; i < NUMNODES; i++)
+		for (zone = NODE_DATA(i)->node_zones; zone < NODE_DATA(i)->node_zones + MAX_NR_ZONES; zone++)
+			sum += zone->nr_lru_pages;
+	return sum;
+}
+
+/*
  * Amount of free RAM allocatable as buffer memory:
  */
 unsigned int nr_free_buffer_pages (void)
@@ -321,10 +336,10 @@
 	zone_t *zone;
 	int i;
 
-	sum = nr_lru_pages;
+	sum = 0;
 	for (i = 0; i < NUMNODES; i++)
 		for (zone = NODE_DATA(i)->node_zones; zone <= NODE_DATA(i)->node_zones+ZONE_NORMAL; zone++)
-			sum += zone->free_pages;
+			sum += zone->free_pages + zone->nr_lru_pages;
 	return sum;
 }
 
@@ -356,7 +371,7 @@
 
 	printk("( Free: %d, lru_cache: %d (%d %d %d) )\n",
 		nr_free_pages(),
-		nr_lru_pages,
+		nr_lru_pages(),
 		freepages.min,
 		freepages.low,
 		freepages.high);
@@ -497,7 +512,6 @@
 	freepages.min += i;
 	freepages.low += i * 2;
 	freepages.high += i * 3;
-	memlist_init(&lru_cache);
 
 	/*
 	 * Some architectures (with lots of mem and discontinous memory
@@ -543,6 +557,10 @@
 		zone->lock = SPIN_LOCK_UNLOCKED;
 		zone->zone_pgdat = pgdat;
 		zone->free_pages = 0;
+
+		zone->nr_lru_pages = 0;
+		memlist_init(&zone->lru_cache);
+
 		if (!size)
 			continue;
 
mm/vmscan.c +37 -26

94 lines not on this page · raw message