ПРОЕКТЫ 


  АРХИВ 


Apache-Talk @lexa.ru 

Inet-Admins @info.east.ru 

Filmscanners @halftone.co.uk 

Security-alerts @yandex-team.ru 

nginx-ru @sysoev.ru 

  СТАТЬИ 


  ПЕРСОНАЛЬНОЕ 


  ПРОГРАММЫ 



ПИШИТЕ
ПИСЬМА














     АРХИВ :: Apache-Talk
Apache-Talk mailing list archive (apache-talk@lists.lexa.ru)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [apache-talk] mathopd ranges



On Thu, Dec 13, 2001 at 07:03:32PM +0300, Eugene B. Berdnikov wrote:
> On Thu, Dec 13, 2001 at 05:29:23PM +0300, AT wrote:
> > Ещё я исследовал поведение poll(2) и select(2) на линуксе, при небольшом
> > числе дескрипторов они работали примерно одинаково, а при большом --
> > select сильно обгонял poll. Вот какие данные примерно получались:
> > 
> >       select (empty)     3.030 usec    0.330 Mhz
> >    select (16 desc.)     3.048 usec    0.328 Mhz
> >   select (512 desc.)     4.055 usec    0.247 Mhz
> >         poll (empty)     1.180 usec    0.848 Mhz
> >      poll (16 desc.)    10.608 usec    0.094 Mhz
> >     poll (512 desc.)   122.048 usec    0.008 Mhz
> 
>  Что это за попугаи? Время возврата из сискола при одном активном fd?

Типа того! Вы будете смеяться: тест идёт на неинициализированных
дескрипторах. Т.е. на произвольном куске памяти. Но этого как раз и
хотелось посмотреть: насколько poll и select отличаются сами по себе,
помимо их общего знаменателя. Цифры даны для того, чтобы почувствовать
порядок разницы. Они подтверждают догадку о том, что узкое место --
копирование в ядро.

Тест прилагаю.

Что я хочу сказать: цифры эти не всегда имеют практическое значение.
poll начинает существенно проигрывать selet только при числе
одновременно открытых дескрипторов большем 16. При меньшем -- poll даже
выигрывает, но это несущественно.

Нужно только понимать, что 16 одновременных дескрипторов для httpd --
это трафик порядка 1Mbps и 100Gb в месяц. Т.е. это достаточно много. И
если такой нагрузки нет, то беспокоиться о преимуществе select над poll
совсем не стоит. :)

> 
>  Киньте этот тест, мы его сами погоняем. И линукс не забудем.
> -- 
>  Eugene Berdnikov

__
AT
/* by Michael Lee, 1997-01-23 */
/* Must compile with optimization off, e.g. "gcc speed.c -lm -o speed" */
/* For best results: run twice in a row, ignore first batch of results. */
/* This is not a benchmark in any way, shape or form. */

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>
#include <sys/select.h>
#include <sys/poll.h>

#define MIN_DURATION 10.0  /* repeat each text for at least this many seconds */
#define MIN_ITER  20      /* or at least this often, whichever is greater */
#define SIGDIGIT   5      /* don't round when first non-zero digit
                             of precision is at least this much */

/* CLK_TCK was documented in K&R2 first printing, but was later renamed. */
/* Old but otherwise okay C89 compilers may still use it */
#ifndef CLOCKS_PER_SEC
  #define CLOCKS_PER_SEC CLK_TCK
#endif

/* some variables used by the macros, below */
static clock_t op_start, op_end;
static double baseline, usec, resolution;
static int i, prec;

/* macros for starting and ending each particular test; made them
   into macros so the rest of the code isn't full of tedious bookkeeping 
   stuff. */
#define BEGIN_TEST(name) printf("%20s ", name); fflush(stdout);   i = 0; op_start = clock();   while(clock() == op_start) /* (busy) wait for clock to turn over */;   op_start = clock();   while ((op_end = clock()) - op_start < CLOCKS_PER_SEC * MIN_DURATION) {     int q;     for (q=0; q < MIN_ITER; q++) {

#define END_TEST(name)  i++; } }   usec =     1000000.0 * (double) (op_end - op_start - baseline * i) /     (double) CLOCKS_PER_SEC / (double) i;   /* just zero out anything too inherently noisy to be useful */   if (usec <= 0.0) usec = 0.0;   printf("%9.3f usec", usec);   if (usec > 0.0) printf("%9.3f Mhz\n", 1.0 / usec);              else printf("      n/a\n");

/* empty function, had to put it somewhere */
void funccall()
{
  return;
}

int main(argc, argv)
  int argc;
  char * argv[];
{
  double tempres;
  int x;
  char buf[80];
  float foo;
  float bar = 1.23456789;
  int able;
  int baker = 1234;
  char * charlie;
  FILE * fd;

  fd_set readfds[512];
  fd_set writefds[512];
  struct pollfd ufds[512];
  struct timeval timeout;

  srand(1);

  /* simple arithmetic to figure out how precise the measurements
     might be */
  printf("clocks_per_sec = %d\n", CLOCKS_PER_SEC);
  resolution = 1000000.0 / CLOCKS_PER_SEC / MIN_ITER;
  printf("worst case resolution = %5.4f usec\n", resolution);

  /* figure out how many significant digits to output */
  prec = 0;
  for (tempres = resolution; tempres < SIGDIGIT; tempres *= 10)
  {
    prec ++;
  }
  printf("precision = %d decimal digits\n", prec);

  /* this could happen, so we might as well check */
  if (clock() == -1)
  {
    fprintf(stderr, "clock() is broken.\n");
    exit(1);
  }

  baseline = 0;

  /* we need to do this because the first time through a program
     there is a significant penalty while the system loads needed
     resources. */
  BEGIN_TEST("(cache & vm load)");
  END_TEST("(cache & vm load)");

  /* figure out the loop overhead so that we can deduct it 
     from the remainder of the tests.  sometimes this measurement is
     noisy because it's so trivial.  increase MIN_DURATION if it's
     a problem */
  BEGIN_TEST("(loop overhead)");
    /* nothing */;
  END_TEST("(loop overhead)");

  baseline = (double) (op_end - op_start) / (double) i;

  BEGIN_TEST("memset overhead");
        memset(&timeout, 0, sizeof timeout);
  END_TEST("memset overhead");

  BEGIN_TEST("select (empty)");
        memset(&timeout, 0, sizeof timeout);
        select(0, readfds, writefds, NULL, &timeout);
  END_TEST("select (empty)");
  
  BEGIN_TEST("select (16 desc.)");
        memset(&timeout, 0, sizeof timeout);
        select(16, readfds, writefds, NULL, &timeout);
  END_TEST("select (16 desc.)");
  
  BEGIN_TEST("select (512 desc.)");
        memset(&timeout, 0, sizeof timeout);
        select(512, readfds, writefds, NULL, &timeout);
  END_TEST("select (512 desc.)");

  BEGIN_TEST("poll (empty)");
        poll(ufds, 0, 0);
  END_TEST("poll (empty)");
  
  BEGIN_TEST("poll (16 desc.)");
        poll(ufds, 16, 0);
  END_TEST("poll (16 desc.)");
  
  BEGIN_TEST("poll (512 desc.)");
        poll(ufds, 512, 0);
  END_TEST("poll (512 desc.)");
  
  return 0;
}


 




Copyright © Lexa Software, 1996-2009.