Skip to contentSkip to conversation

6 sys_poll/sys_select performance patches

RFC In review Manfred Spraul 3 participants 3 messages Nov 20, 2002 – Nov 21, 2002 VFS

lore
Share & tools
lore
#0 lore raw

RFC 1/1 6 sys_poll/sys_select performance patches

Attached are 6 patches that try to improve the performance of sys_poll and sys_select:

- avoid dynamic memory allocations, stack storage is sufficient for most callers and faster.
- use the wakeup callbacks and use that info to speed up the 2nd scan for new events.

What do you think? Are there any apps/tests/benchmarks that stress sys_poll or sys_select?

The first 3 patches replace dynamic memory allocations with stack storage. The 4th and 5th patch use wait queue callbacks for a more efficient 2nd scan. The 6th patch merges common code.

The patch is against 2.5.48 - they do boot on my laptop, but that's all I can guarantee.

--
Manfred

// $Header$
// Kernel Version:

//  VERSION = 2
//  PATCHLEVEL = 5
//  SUBLEVEL = 48
//  EXTRAVERSION =
include/linux/poll.h +11 -1
@@ -35,10 +35,20 @@
 /*
  * Structures and helpers for sys_poll/sys_poll
  */
+struct poll_table_entry {
+	struct file *filp;
+	wait_queue_t wait;
+	wait_queue_head_t *wait_address;
+};
+
+#define POLL_TABLE_INTERNAL	6
+
 struct poll_wqueues {
 	poll_table pt;
-	struct poll_table_page * table;
 	int error;
+	int nr;
+	struct poll_table_entry internal[POLL_TABLE_INTERNAL];
+	struct poll_table_page *table;
 };
 
 extern void poll_initwait(struct poll_wqueues *pwq);
fs/select.c +48 -33

121 lines not on this page · raw message

// $Header$
// Kernel Version:

//  VERSION = 2
//  PATCHLEVEL = 5
//  SUBLEVEL = 48
//  EXTRAVERSION =
fs/select.c +11 -5
@@ -62,6 +62,7 @@
  * - the poll table contains 6 wait queue entries. This means that no dynamic
  *   memory allocation is necessary for the wait queues if one of the first
  *   6 file descriptors has new data.
+ * - sys_select saves 192 bytes on the stack, enough for 256 file descriptors.
  * <[email protected]>
  */
 
@@ -261,14 +262,18 @@
 	return retval;
 }
 
-static void *select_bits_alloc(int size)
+#define SELECT_INLINE_BYTES	32
+static inline void *select_bits_alloc(int size, void *internal)
 {
+	if(size <= SELECT_INLINE_BYTES)
+		return internal;
 	return kmalloc(6 * size, GFP_KERNEL);
 }
 
-static void select_bits_free(void *bits, int size)
+static inline void select_bits_free(void *bits, void *internal)
 {
-	kfree(bits);
+	if(bits != internal)
+		kfree(bits);
 }
 
 /*
@@ -286,6 +291,7 @@
 sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
 {
 	fd_set_bits fds;
+	char ibuf[6*SELECT_INLINE_BYTES];
 	char *bits;
 	long timeout;
 	int ret, size, max_fdset;
@@ -325,7 +331,7 @@
 	 */
 	ret = -ENOMEM;
 	size = FDS_BYTES(n);
-	bits = select_bits_alloc(size);
+	bits = select_bits_alloc(size, ibuf);
 	if (!bits)
 		goto out_nofds;
 	fds.in      = (unsigned long *)  bits;
@@ -370,7 +376,7 @@
 	set_fd_set(n, exp, fds.res_ex);
 
 out:
-	select_bits_free(bits, size);
+	select_bits_free(bits, ibuf);
 out_nofds:
 	return ret;
 }

// $Header$
// Kernel Version:

//  VERSION = 2
//  PATCHLEVEL = 5
//  SUBLEVEL = 48
//  EXTRAVERSION =
fs/select.c +72 -66

186 lines not on this page · raw message

// $Header$
// Kernel Version:

//  VERSION = 2
//  PATCHLEVEL = 5
//  SUBLEVEL = 48
//  EXTRAVERSION =
include/linux/poll.h +4 -0
@@ -37,6 +37,8 @@
  */
 struct poll_table_entry {
 	struct file *filp;
+	int woken;
+	void *handle;
 	wait_queue_t wait;
 	wait_queue_head_t *wait_address;
 };
@@ -47,8 +49,10 @@
 	poll_table pt;
 	int error;
 	int nr;
+	void *handle;
 	struct poll_table_entry internal[POLL_TABLE_INTERNAL];
 	struct poll_table_page *table;
+	struct poll_table_page *last;
 };
 
 extern void poll_initwait(struct poll_wqueues *pwq);
fs/select.c +102 -38

189 lines not on this page · raw message

// $Header$
// Kernel Version:

//  VERSION = 2
//  PATCHLEVEL = 5
//  SUBLEVEL = 48
//  EXTRAVERSION =
fs/select.c +61 -16

131 lines not on this page · raw message

// $Header$
// Kernel Version:

//  VERSION = 2
//  PATCHLEVEL = 5
//  SUBLEVEL = 48
//  EXTRAVERSION =
fs/select.c +54 -76

175 lines not on this page · raw message

#1 lore raw
Quoted 10 lines · Manfred Spraul

Attached are 6 patches that try to improve the performance of sys_poll and sys_select:

- avoid dynamic memory allocations, stack storage is sufficient for most callers and faster.
- use the wakeup callbacks and use that info to speed up the 2nd scan for new events.

What do you think? Are there any apps/tests/benchmarks that stress sys_poll or sys_select?

You can try Ben's pipetest ...

- Davide

#2 lore raw
Quoted 4 lines · --On Wednesday, November 20, 2002 04:29:16 PM -0800 Davide Libenzi…
Quoted 2 lines

What do you think? Are there any apps/tests/benchmarks that stress sys_poll or sys_select?

You can try Ben's pipetest ...

The pointer for which can be found (with detailed testing instructions)
at: http://lse.sf.net/epoll

Hanna