lkml.org 
[lkml]   [2006]   [Nov]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [take22 0/4] kevent: Generic event handling mechanism.
    zhou drangon a écrit :
    > performance is great, and we are exciting at the result.
    >
    > I want to know why there can be so much improvement, can we improve
    > epoll too ?

    Why did you remove most of CC addresses but lkml ?
    Dont do that please...

    Good question :)

    Hum, I think I can look into epoll and see how it can be improved (if necessary)

    This is not to say we dont need kevent ! Please Evgeniy continue your work !

    Just to remind you that according to
    http://www.xmailserver.org/linux-patches/nio-improve.html David Libenzi had to
    wait 18 months before epoll being officialy added into kernel.

    At that time, many applications were using epoll, and we were patching our
    kernels for that.


    I cooked a very simple program (attached in this mail), using pipes and epoll,
    and got 250.000 events received per second on an otherwise lightly loaded
    machine (dual opteron 246 , 2GHz, 1MB cache per cpu) with 10.000 pipes (20.000
    handles)

    It could be nice to add support for other event providers in this program
    (AF_INET & AF_UNIX sockets for example), and also add support for kevent, so
    that we really can compare epoll/kevent without a complex setup.
    I should extend the program to also add/remove sources during lifetime, not
    only insert at setup time.

    # gcc -O2 -o epoll_pipe_bench epoll_pipe_bench.c -lpthread
    # ulimit -n 1000000
    # epoll_pipe_bench -n 10000
    ^C after a while...

    oprofile results say that ep_poll_callback() and sys_epoll_wait() use 20% of
    cpu time.
    Even if we gain a two factor in cpu time or cache usage, we wont eliminate
    other costs...

    oprofile results gave :

    Counted CPU_CLK_UNHALTED events (Cycles outside of halt state) with a unit
    mask of 0x00 (No unit mask) count 50000
    samples % symbol name
    2015420 11.1309 ep_poll_callback
    1867431 10.3136 pipe_writev
    1791872 9.8963 sys_epoll_wait
    1357297 7.4962 fget_light
    1277515 7.0556 pipe_readv
    998447 5.5143 current_fs_time
    801597 4.4271 __mark_inode_dirty
    755268 4.1713 __wake_up
    587065 3.2423 __write_lock_failed
    582931 3.2195 system_call
    297132 1.6410 iov_fault_in_pages_read
    296136 1.6355 sys_write
    290106 1.6022 __wake_up_common
    270692 1.4950 bad_pipe_w
    261516 1.4443 do_pipe
    257208 1.4205 tg3_start_xmit_dma_bug
    254917 1.4079 pipe_poll
    252925 1.3969 copy_user_generic_c
    234212 1.2935 generic_pipe_buf_map
    228659 1.2629 ret_from_sys_call
    212541 1.1738 sysret_check
    166529 0.9197 sys_read
    160038 0.8839 vfs_write
    151091 0.8345 pipe_ioctl
    136301 0.7528 file_update_time
    107173 0.5919 tg3_poll
    77846 0.4299 ipt_do_table
    75081 0.4147 schedule
    73059 0.4035 vfs_read
    69787 0.3854 get_task_comm
    63923 0.3530 memcpy
    60019 0.3315 touch_atime
    57490 0.3175 eventpoll_release_file
    56152 0.3101 tg3_write_flush_reg32
    54468 0.3008 rw_verify_area
    47833 0.2642 generic_pipe_buf_unmap
    47777 0.2639 __switch_to
    44106 0.2436 bad_pipe_r
    41824 0.2310 proc_nr_files
    41319 0.2282 pipe_iov_copy_from_user


    Eric

    /*
    * How to stress epoll
    *
    * This program uses many pipes and two threads.
    * First we open as many pipes we can. (see ulimit -n)
    * Then we create a worker thread.
    * The worker thread will send bytes to random pipes.
    * The main thread uses epoll to collect ready pipes and read them.
    * Each second, a number of collected bytes is printed on stderr
    *
    * Usage : epoll_bench [-n X]
    */
    #include <pthread.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/epoll.h>
    #include <signal.h>
    #include <unistd.h>
    #include <sys/time.h>

    int nbpipes = 1024;

    struct pipefd {
    int fd[2];
    } *tab;

    int epoll_fd;

    static int alloc_pipes()
    {
    int i;

    epoll_fd = epoll_create(nbpipes);
    if (epoll_fd == -1) {
    perror("epoll_create");
    return -1;
    }
    tab = malloc(sizeof(struct pipefd) * nbpipes);
    if (tab ==NULL) {
    perror("malloc");
    return -1;
    }
    for (i = 0 ; i < nbpipes ; i++) {
    struct epoll_event ev;
    if (pipe(tab[i].fd) == -1)
    break;
    ev.events = EPOLLIN | EPOLLOUT | EPOLLHUP | EPOLLPRI | EPOLLET;
    ev.data.u64 = (uint64_t)i;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, tab[i].fd[0], &ev);
    }
    nbpipes = i;
    printf("%d pipes setup\n", nbpipes);
    return 0;
    }


    unsigned long nbhandled;
    static void timer_func()
    {
    char buffer[32];
    size_t len;
    static unsigned long old;
    unsigned long delta = nbhandled - old;
    old = nbhandled;
    len = sprintf(buffer, "%lu\n", delta);
    write(2, buffer, len);
    }

    static void timer_setup()
    {
    struct itimerval it;
    struct sigaction sg;

    memset(&sg, 0, sizeof(sg));
    sg.sa_handler = timer_func;
    sigaction(SIGALRM, &sg, 0);
    it.it_interval.tv_sec = 1;
    it.it_interval.tv_usec = 0;
    it.it_value.tv_sec = 1;
    it.it_value.tv_usec = 0;
    if (setitimer(ITIMER_REAL, &it, 0))
    perror("setitimer");
    }

    static void * worker_thread_func(void *arg)
    {
    int fd;
    char c = 1;
    for (;;) {
    fd = rand() % nbpipes;
    write(tab[fd].fd[1], &c, 1);
    }
    }


    int main(int argc, char *argv[])
    {
    char buff[1024];
    pthread_t tid;
    int c;

    while ((c = getopt(argc, argv, "n:")) != EOF) {
    if (c == 'n') nbpipes = atoi(optarg);
    }
    alloc_pipes();
    pthread_create(&tid, NULL, worker_thread_func, (void *)0);
    timer_setup();

    for (;;) {
    struct epoll_event events[128];
    int nb = epoll_wait(epoll_fd, events, 128, 10000);
    int i, fd;
    for (i = 0 ; i < nb ; i++) {
    fd = tab[events[i].data.u64].fd[0];
    if (read(fd, buff, 1024) > 0)
    nbhandled++;
    }
    }
    }
    \
     
     \ /
      Last update: 2006-11-02 08:49    [W:0.067 / U:60.272 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site