Russian Apache Switch to English
Switch to Russian koi8-r
windows=1251
cp-866
iso8859-5
Russian Apache Как это работает Рекоммендации Где взять Как установить Как настроить Статус и поддержка
Краткий обзор FAQ Список рассылки Благодарности Поиск по серверу Powered by Russian Apache
Russian Apache mailing list archive (apache-rus@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;
}





Спонсоры сайта:

[ Russian Apache ] [ Как это работает ] [ Рекомендации ] [ Где взять ] [ Как установить ] [ Как настроить ] [ Статус и поддержка ] [ Краткий обзор ] [ FAQ ] [ Список рассылки ] [ Благодарности ] [ Поиск по серверу ] [ Powered by Russian Apache ] [ Apache-talk archive ]

"Russian Apache" includes software developed by the Apache Group for use in the Apache HTTP server project (http://www.apache.org/) See Apache LICENSE.
Copyright (C) 1995-2001 The Apache Group. All rights reserved.
Copyright (C) 1996 Dm. Kryukov; Copyright (C) 1997-2009 Alex Tutubalin. Design (C) 1998 Max Smolev.