Re: [PATCH][CFT] dcache-ac6-D - dcache threading

From: kumon@flab.fujitsu.co.jp
Date: Sun Jun 04 2000 - 08:43:07 EST


Andi Kleen writes:
> On Sun, Jun 04, 2000 at 05:24:11AM +0900, kumon@flab.fujitsu.co.jp wrote:
> > Some part of kmalloc/kfree overhead is come from do_select, and it is
> > easily eliminated using small array on a stack. Which I've already
> > posted. IMHO per CPU skb will not reduce the kmalloc overhead,
>
> Funny, Linux before 2.2 did that, but it was changed to allow fd set size
> extensions. There were actually patches that tried stack alloc and
> dynamic depending on the size, but they were rejected because of the
> complexity.

The attached patch allocates an array on a stack which can hold at least
64 fds. The array size is 48B for do_select and 32B for do_poll.
This adds almost no overhead and eliminates all kmalloc() from
do_select/do_poll of tipical cases.

Is it complex enough?
Yes, it contains weird magic number 64. But it is practical and
useful.

diff -rc linux-2.4.0-test1-smp/fs/select.c work/fs/select.c
*** linux-2.4.0-test1-smp/fs/select.c Sat Apr 22 04:53:45 2000
--- work/fs/select.c Thu Jun 1 15:46:36 2000
***************
*** 252,257 ****
--- 252,258 ----
   */
  #define MAX_SELECT_SECONDS \
          ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
+ #define MAX_SELECT_BITS_ON_STACK 64
  
  asmlinkage long
  sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
***************
*** 260,265 ****
--- 261,268 ----
          char *bits;
          long timeout;
          int ret, size;
+ /* can hold MAX_SELECT_BITS_ON_STACK fds on stack */
+ char bits_on_stack[6 * FDS_BYTES(MAX_SELECT_BITS_ON_STACK)];
  
          timeout = MAX_SCHEDULE_TIMEOUT;
          if (tvp) {
***************
*** 294,302 ****
           */
          ret = -ENOMEM;
          size = FDS_BYTES(n);
! bits = kmalloc(6 * size, GFP_KERNEL);
! if (!bits)
! goto out_nofds;
          fds.in = (unsigned long *) bits;
          fds.out = (unsigned long *) (bits + size);
          fds.ex = (unsigned long *) (bits + 2*size);
--- 297,308 ----
           */
          ret = -ENOMEM;
          size = FDS_BYTES(n);
! bits = bits_on_stack;
! if (6 * size > sizeof(bits_on_stack)) {
! bits = kmalloc(6 * size, GFP_KERNEL);
! if (!bits)
! goto out_nofds;
! }
          fds.in = (unsigned long *) bits;
          fds.out = (unsigned long *) (bits + size);
          fds.ex = (unsigned long *) (bits + 2*size);
***************
*** 339,345 ****
          set_fd_set(n, exp, fds.res_ex);
  
  out:
! kfree(bits);
  out_nofds:
          return ret;
  }
--- 345,352 ----
          set_fd_set(n, exp, fds.res_ex);
  
  out:
! if (bits != bits_on_stack)
! kfree(bits);
  out_nofds:
          return ret;
  }
***************
*** 400,411 ****
--- 407,422 ----
          return count;
  }
  
+ #define MAX_POLL_FDS_ON_STACK 64
+
  asmlinkage long sys_poll(struct pollfd * ufds, unsigned int nfds, long timeout)
  {
          int i, j, fdcount, err;
          struct pollfd **fds;
          poll_table *wait = NULL;
          int nchunks, nleft;
+ /* fds_on_stack can hold up to MAX_POLL_FDS_ON_STACK fds. */
+ struct pollfd *fds_on_stack[1 + (MAX_POLL_FDS_ON_STACK - 1) / POLLFD_PER_PAGE];
  
          /* Do a sanity check on nfds ... */
          if (nfds > current->files->max_fds)
***************
*** 426,438 ****
          }
          err = -ENOMEM;
  
! fds = NULL;
          if (nfds != 0) {
! fds = (struct pollfd **)kmalloc(
! (1 + (nfds - 1) / POLLFD_PER_PAGE) * sizeof(struct pollfd *),
! GFP_KERNEL);
! if (fds == NULL)
! goto out;
          }
  
          nchunks = 0;
--- 437,450 ----
          }
          err = -ENOMEM;
  
! fds = fds_on_stack;
          if (nfds != 0) {
! unsigned int pollfdsz = 1 + (nfds - 1) / POLLFD_PER_PAGE * sizeof(struct pollfd *);
! if (pollfdsz > sizeof(fds_on_stack)) {
! fds = (struct pollfd **)kmalloc(pollfdsz, GFP_KERNEL);
! if (fds == NULL)
! goto out;
! }
          }
  
          nchunks = 0;
***************
*** 480,486 ****
  out_fds:
          for (i=0; i < nchunks; i++)
                  free_page((unsigned long)(fds[i]));
! if (nfds != 0)
                  kfree(fds);
  out:
          free_wait(wait);
--- 492,498 ----
  out_fds:
          for (i=0; i < nchunks; i++)
                  free_page((unsigned long)(fds[i]));
! if (fds != fds_on_stack)
                  kfree(fds);
  out:
          free_wait(wait);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed Jun 07 2000 - 21:00:18 EST