diff -rc2 ../squid-hno/src/cache_cf.c ./src/cache_cf.c
*** ../squid-hno/src/cache_cf.c	Mon Jan 10 19:56:42 2000
--- ./src/cache_cf.c	Mon Mar 20 23:36:39 2000
***************
*** 342,345 ****
--- 342,353 ----
  	Config.Wais.peer->http_port = Config.Wais.relayPort;
      }
+     if (Config.max_small_object_target != 0 && Config.max_small_object_target < 1000) {
+ 	debug(3, 0) ("WARNING: disabling 'max_small_object_target'\n");
+ 	Config.max_small_object_target = 0;
+     }
+     if (Config.small_object_max_size < 10000) {
+ 	debug(3, 0) ("WARNING: resetting 'small_object_max_size' to 10000\n");
+ 	Config.small_object_max_size = 10000;
+     }
  }
  
diff -rc2 ../squid-hno/src/cf.data.pre ./src/cf.data.pre
*** ../squid-hno/src/cf.data.pre	Mon Jan 10 19:56:42 2000
--- ./src/cf.data.pre	Mon Mar 20 23:31:57 2000
***************
*** 1173,1176 ****
--- 1173,1206 ----
  DOC_END
  
+ NAME: max_small_object_target
+ TYPE: int
+ LOC: Config.max_small_object_target
+ DEFAULT: 0
+ DOC_START
+ 	When using a very large disk cache, the referenceAge can become
+ 	so large that an inordinate amount of small objects is cached.
+ 	When byte hit rate is more important than Squids CPU usage,
+ 	setting a target maximum for the number of small objects can help
+ 	keeping Squids memory footprint down, while keeping large objects
+ 	in the cache longer.
+ 
+ 	Default is 0 (disabled). It is suggested to disable this feature
+ 	first, and watch the number of objects in the cache until Squid
+ 	runs out of memory, then set the target at two thirds of that
+ 	amount.
+ 	
+ max_small_object_target 0
+ DOC_END
+ 
+ NAME: small_object_max_size
+ TYPE: int
+ LOC: Config.small_object_max_size
+ DEFAULT: 0
+ DOC_START
+ 	The maximum size for an object to be eligible for premature
+ 	discarding with the max_small_object_target setting enabled.
+ 
+ small_object_max_size 100000
+ DOC_END
  
  NAME: quick_abort_min
diff -rc2 ../squid-hno/src/squid.conf ./src/squid.conf
diff -rc2 ../squid-hno/src/store.c ./src/store.c
*** ../squid-hno/src/store.c	Mon Jan 10 19:56:42 2000
--- ./src/store.c	Mon Mar 20 23:32:58 2000
***************
*** 76,79 ****
--- 76,80 ----
   * local function prototypes
   */
+ static void storeRemoveSmallObjects(void);
  static int storeCheckExpired(const StoreEntry *);
  static int storeEntryLocked(const StoreEntry *);
***************
*** 721,724 ****
--- 722,726 ----
      double f;
      static time_t last_warn_time = 0;
+     static int times_run = 0;
      /* We can't delete objects while rebuilding swap */
      if (store_rebuilding) {
***************
*** 765,768 ****
--- 767,773 ----
      debug(20, 3) ("  %6d were locked\n", locked);
      debug(20, 3) ("  %6d were expired\n", expired);
+     times_run++;
+     if (Config.max_small_object_target > 0 && (times_run % 60) == 0)
+ 	storeRemoveSmallObjects();
      if (store_swap_size < Config.Swap.maxSize)
  	return;
***************
*** 772,775 ****
--- 777,833 ----
  	store_swap_size, Config.Swap.maxSize);
      last_warn_time = squid_curtime;
+ }
+ 
+ /* 
+  * This routine is to be called by storeMaintainSwapSpace at most
+  * once per minute, and only when safe.
+  * It removes small objects using a fairly deep traversal.
+  * Returns the number of objects removed
+  *
+  * This should get called 1/s from main().
+  */
+ static void
+ storeRemoveSmallObjects(void)
+ {
+     dlink_node *m;
+     dlink_node *prev = NULL;
+     StoreEntry *e = NULL;
+     int scanned = 0;
+     int locked = 0;
+     int expired = 0;
+     int toobig = 0;
+     int max_scan;
+     int target;
+ 
+     if (memInUse(MEM_STOREENTRY) < Config.max_small_object_target)
+ 	return;
+ 
+     max_scan = memInUse(MEM_STOREENTRY) / 2;
+     target = memInUse(MEM_STOREENTRY) - Config.max_small_object_target;
+     for (m = store_list.tail; m; m = prev) {
+ 	prev = m->prev;
+ 	e = m->data;
+ 	scanned++;
+ 	if (storeEntryLocked(e)) {
+ 	    locked++;
+ 	} else if (e->swap_file_sz > Config.small_object_max_size) {
+ 	    toobig++;
+ 	} else {
+ 	    expired++;
+ 	    target--;
+ 	    storeRelease(e);
+ 	}
+ 	if (target <= 0)
+ 	    break;
+ 	if (scanned >= max_scan)
+ 	    break;
+     }
+ 	/* XXX Change level back to 3 */
+     debug(20, 1) ("storeRemoveSmallObjects stats:\n");
+     debug(20, 1) ("  %6d objects\n", memInUse(MEM_STOREENTRY));
+     debug(20, 1) ("  %6d were scanned\n", scanned);
+     debug(20, 1) ("  %6d were locked\n", locked);
+     debug(20, 1) ("  %6d were expired\n", expired);
+     debug(20, 1) ("  %6d were too big\n", toobig);
  }
  
diff -rc2 ../squid-hno/src/structs.h ./src/structs.h
*** ../squid-hno/src/structs.h	Mon Jan 10 19:56:42 2000
--- ./src/structs.h	Mon Mar 20 23:06:32 2000
***************
*** 455,458 ****
--- 455,460 ----
      char *coredump_dir;
      char *chroot_dir;
+     int max_small_object_target;
+     int small_object_max_size;
  };
  
