Date: Tue, 17 Oct 2000 01:42:40 -0700
From: "David S. Miller" <davem@redhat.com>
Subject: Re: close() slow on socketpairs?
In-reply-to: <39EBDEEF.2D4DA765@alumni.caltech.edu>
 (message from Dan Kegel on Mon, 16 Oct 2000 22:09:03 -0700)
To: dank@alumni.caltech.edu
Cc: linux-kernel@vger.kernel.org
Message-id: <200010170842.BAA21746@pizda.ninka.net>
References: <39EBDEEF.2D4DA765@alumni.caltech.edu>


Please try this 2.2.x patch.  It fixes the 2.2.x performance
problem with your example code for me.

--- ./include/net/af_unix.h.~1~	Fri Apr 11 21:30:23 1997
+++ ./include/net/af_unix.h	Tue Oct 17 00:04:32 2000
@@ -7,7 +7,7 @@
 typedef struct sock unix_socket;
 extern void unix_gc(void);
 
-#define UNIX_HASH_SIZE	16
+#define UNIX_HASH_SIZE	256
 
 extern unix_socket *unix_socket_table[UNIX_HASH_SIZE+1];
 
--- ./net/unix/af_unix.c.~1~	Fri May 26 21:46:44 2000
+++ ./net/unix/af_unix.c	Tue Oct 17 01:49:47 2000
@@ -110,6 +110,8 @@
 
 #define min(a,b)	(((a)<(b))?(a):(b))
 
+extern int unix_tot_inflight;
+
 int sysctl_unix_delete_delay = HZ;
 int sysctl_unix_destroy_delay = 10*HZ;
 int sysctl_unix_max_dgram_qlen = 10;
@@ -130,7 +132,6 @@
 {
 	hash ^= hash>>16;
 	hash ^= hash>>8;
-	hash ^= hash>>4;
 	return hash;
 }
 
@@ -240,7 +241,7 @@
 {
 	unix_socket *s;
 
-	for (s=unix_socket_table[(hash^type)&0xF]; s; s=s->next)
+	for (s=unix_socket_table[(hash^type)&(UNIX_HASH_SIZE-1)]; s; s=s->next)
 	{
 		if(s->protinfo.af_unix.addr->len==len &&
 		   memcmp(s->protinfo.af_unix.addr->name, sunname, len) == 0 &&
@@ -257,7 +258,7 @@
 {
 	unix_socket *s;
 
-	for (s=unix_socket_table[i->i_ino & 0xF]; s; s=s->next)
+	for (s=unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]; s; s=s->next)
 	{
 		struct dentry *dentry = s->protinfo.af_unix.dentry;
 
@@ -344,7 +345,8 @@
 	 *	  What the above comment does talk about? --ANK(980817)
 	 */
 
-	unix_gc();		/* Garbage collect fds */	
+	if (unix_tot_inflight)
+		unix_gc();		/* Garbage collect fds */	
 	return 0;
 }
 	
@@ -519,7 +521,7 @@
 
 	sk->protinfo.af_unix.addr = addr;
 	unix_remove_socket(sk);
-	sk->protinfo.af_unix.list = &unix_socket_table[(addr->hash ^ sk->type)&0xF];
+	sk->protinfo.af_unix.list = &unix_socket_table[(addr->hash ^ sk->type)&(UNIX_HASH_SIZE - 1)];
 	unix_insert_socket(sk);
 	return 0;
 }
@@ -607,7 +609,7 @@
 		}
 		unix_remove_socket(sk);
 		sk->protinfo.af_unix.addr = addr;
-		sk->protinfo.af_unix.list = &unix_socket_table[(hash^sk->type)&0xF];
+		sk->protinfo.af_unix.list = &unix_socket_table[(hash^sk->type)&(UNIX_HASH_SIZE - 1)];
 		unix_insert_socket(sk);
 		return 0;
 	}
@@ -628,7 +630,7 @@
 			return err;
 	}
 	unix_remove_socket(sk);
-	sk->protinfo.af_unix.list = &unix_socket_table[dentry->d_inode->i_ino & 0xF];
+	sk->protinfo.af_unix.list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE - 1)];
 	sk->protinfo.af_unix.dentry = dentry;
 	unix_insert_socket(sk);
 
--- ./net/unix/garbage.c.~1~	Tue Mar 23 17:03:06 1999
+++ ./net/unix/garbage.c	Tue Oct 17 01:49:11 2000
@@ -108,6 +108,8 @@
 	return u_sock;
 }
 
+int unix_tot_inflight;
+
 /*
  *	Keep the number of times in flight count for the file
  *	descriptor if it is for an AF_UNIX socket.
@@ -116,15 +118,19 @@
 void unix_inflight(struct file *fp)
 {
 	unix_socket *s=unix_get_socket(fp);
-	if(s)
+	if (s) {
 		s->protinfo.af_unix.inflight++;
+		unix_tot_inflight++;
+	}
 }
 
 void unix_notinflight(struct file *fp)
 {
 	unix_socket *s=unix_get_socket(fp);
-	if(s)
+	if (s) {
 		s->protinfo.af_unix.inflight--;
+		unix_tot_inflight--;
+	}
 }
 
 




