LINUX.ORG.RU

История изменений

Исправление gh0stwizard, (текущая версия) :

О чём это сообщение?

О том, что вы ничего не поняли в СОП. Вы процитировали Марка, это здорово.

Never call ->recv on a condition variable unless you know that the ->send method has been called on it already. This is because it will stall the whole program, and the whole point of using events is to stay interactive.

http://search.cpan.org/~mlehmann/AnyEvent-7.04/lib/AnyEvent.pm#WHAT_TO_DO_IN_...

А вот в деталях что происходит:

$ perl -MEV -MAnyEvent -e 'AE::cv->recv'

1. Заменяем вызов _poll из AnyEvent::Impl::EV

sub _poll {
   EV::run EV::RUN_ONCE;
}

2. Место где происходит блокировка и съедание на 100% cpu (AnyEvent.pm)

sub AnyEvent::CondVar::Base::_wait {
   EV::run EV::RUN_ONCE until exists $_[0]{_ae_sent};
}

3. Злощастный вызов

sub recv {
   unless ($_[0]{_ae_sent}) {
      $WAITING
         and Carp::croak "AnyEvent::CondVar: recursive blocking wait attempted";

      local $WAITING = 1;
      $_[0]->_wait; # блокировка наступает здесь
   }
#
# далее в нашем случае никогда не произойдет
#
   $_[0]{_ae_croak}
      and Carp::croak $_[0]{_ae_croak};

   wantarray
      ? @{ $_[0]{_ae_sent} }
      : $_[0]{_ae_sent}[0]
}

4. Совместим все выше сказанное для кратости и ясности

sub recv {
  EV::run EV::RUN_ONCE until exists $_[0]{_ae_sent};
}

Теперь разберемся почему в вашем случае происходит, а в моем - нет:

$ perl -MEV -MAnyEvent -e '$cv = AE::cv; $t = AE::timer 10, 10, sub { }; $cv->recv'

EV::RUN_ONCE block at most once (wait, but do not loop)

http://search.cpan.org/~mlehmann/EV-4.15/EV.pm#BASIC_INTERFACE

А теперь слегка изменим мой код, чтобы явно доказать, что вы ничего не поняли в СОП:

$ perl -MEV -MAnyEvent -e '$cv = AE::cv; $t = AE::timer 10, 0, sub { undef $t; }; $cv->recv'

Выводы из последнего кода:

1. Первый 10 секунд нагрузка на cpu будет менее 1%, т.к. «EV::run EV::RUN_ONCE» будет ждать события от AE::timer, цитирую еще раз:

wait, but do not loop

2. Через 10 секунд мы сносим единственного «стража» и поведение резко меняется, теперь это программа не написана в стиле СОП!

EV::run EV::RUN_ONCE until exists $_[0]{_ae_sent};

Поставьте вместо EV::run EV::RUN_ONCE все что угодно и cpu будет жраться на все 100%, это просто PP!

localtime until exists $_[0]{_ae_sent};

3. Вывод: в больших программах, где используются любые другие «стражи» эта строчка «AE::cv->recv» безобидна. И она не всегда ест 100% cpu, а только тогда когда вы превратили программу во что-то другое, но не СОП.

Исправление gh0stwizard, :

О чём это сообщение?

О том, что вы ничего не поняли в СОП. Вы процитировали Марка, это здорово.

Never call ->recv on a condition variable unless you know that the ->send method has been called on it already. This is because it will stall the whole program, and the whole point of using events is to stay interactive.

http://search.cpan.org/~mlehmann/AnyEvent-7.04/lib/AnyEvent.pm#WHAT_TO_DO_IN_...

А вот в деталях что происходит:

$ perl -MEV -MAnyEvent -e 'AE::cv->recv'

1. Заменяем вызов _poll из AnyEvent::Impl::EV

sub _poll {
   EV::run EV::RUN_ONCE;
}

2. Место где происходит блокировка и съедание на 100% cpu (AnyEvent.pm)

sub AnyEvent::CondVar::Base::_wait {
   EV::run EV::RUN_ONCE until exists $_[0]{_ae_sent};
}

3. Злощастный вызов

sub recv {
   unless ($_[0]{_ae_sent}) {
      $WAITING
         and Carp::croak "AnyEvent::CondVar: recursive blocking wait attempted";

      local $WAITING = 1;
      $_[0]->_wait; # блокировка наступает здесь
   }
#
# далее в нашем случае никогда не произойдет
#
   $_[0]{_ae_croak}
      and Carp::croak $_[0]{_ae_croak};

   wantarray
      ? @{ $_[0]{_ae_sent} }
      : $_[0]{_ae_sent}[0]
}

4. Совместим все выше сказанное для кратости и ясности

sub recv {
  EV::run EV::RUN_ONCE until exists $_[0]{_ae_sent};
}

Теперь разберемся почему в вашем случае происходит, а в моем - нет:

$ perl -MEV -MAnyEvent -e '$cv = AE::cv; $t = AE::timer 10, 10, sub { }; $cv->recv'

EV::RUN_ONCE block at most once (wait, but do not loop)

http://search.cpan.org/~mlehmann/EV-4.15/EV.pm#BASIC_INTERFACE

А теперь слегка изменим мой код, чтобы явно доказать, что вы ничего не поняли в СОП:

$ perl -MEV -MAnyEvent -e '$cv = AE::cv; $t = AE::timer 10, 0, sub { undef $t; }; $cv->recv'

Выводы из последнего кода:

1. Первый 10 секунд нагрузка на cpu будет менее 1%, т.к. «EV::run EV::RUN_ONCE» будет ждать события от AE::timer цитирую еще раз:

wait, but do not loop

2. Через 10 секунд мы сносим единственного «стража» и поведение резко меняется, теперь это программа не написана в стиле СОП!

EV::run EV::RUN_ONCE until exists $_[0]{_ae_sent};

Поставьте вместо EV::run EV::RUN_ONCE все что угодно и cpu будет жраться на все 100%, это просто PP!

localtime until exists $_[0]{_ae_sent};

3. Вывод: в больших программах, где используются любые другие «стражи» эта строчка «AE::cv->recv» безобидна. И она не всегда ест 100% cpu, а только тогда когда вы превратили программу во что-то другое, но не СОП.

Исходная версия gh0stwizard, :

О чём это сообщение?

О том, что вы ничего не поняли в СОП. Вы процитировали Марка, это здорово.

Never call ->recv on a condition variable unless you know that the ->send method has been called on it already. This is because it will stall the whole program, and the whole point of using events is to stay interactive.

http://search.cpan.org/~mlehmann/AnyEvent-7.04/lib/AnyEvent.pm#WHAT_TO_DO_IN_...

А вот в деталях что происходит:

$ perl -MEV -MAnyEvent -e 'AE::cv->recv'

1. Заменяем вызов _poll из AnyEvent::Impl::EV

sub _poll {
   EV::run EV::RUN_ONCE;
}

2. Место где происходит блокировка и съедание на 100% cpu (AnyEvent.pm)

sub AnyEvent::CondVar::Base::_wait {
   EV::run EV::RUN_ONCE until exists $_[0]{_ae_sent};
}

3. Злощастный вызов

sub recv {
   unless ($_[0]{_ae_sent}) {
      $WAITING
         and Carp::croak "AnyEvent::CondVar: recursive blocking wait attempted";

      local $WAITING = 1;
      $_[0]->_wait; # блокировка наступает здесь
   }
#
# далее в нашем случае никогда не произойдет
#
   $_[0]{_ae_croak}
      and Carp::croak $_[0]{_ae_croak};

   wantarray
      ? @{ $_[0]{_ae_sent} }
      : $_[0]{_ae_sent}[0]
}

4. Совместим все выше сказанное для кратости и ясности

sub recv {
  EV::run EV::RUN_ONCE until exists $_[0]{_ae_sent};
}

Теперь разберемся почему в вашем случае происходит, а в моем - нет:

$ perl -MEV -MAnyEvent -e '$cv = AE::cv; $t = AE::timer 10, 10, sub { }; $cv->recv'

EV::RUN_ONCE block at most once (wait, but do not loop)

http://search.cpan.org/~mlehmann/EV-4.15/EV.pm#BASIC_INTERFACE

А теперь слегка изменим мой код, чтобы явно доказать, что вы ничего не поняли в СОП:

$ perl -MEV -MAnyEvent -e '$cv = AE::cv; $t = AE::timer 10, 0, sub { undef $t; }; $cv->recv'

Выводы из последнего кода:

1. Первый 10 секунд нагрузка на cpu будет менее 1%, т.к. «EV::run EV::RUN_ONCE» будет ждать события от AE::timer цитирую еще раз:

wait, but do not loop

2. Через 10 секунд мы сносим единственного «стража» и поведение резко меняется, теперь это программа не написана в стиле СОП!

EV::run EV::RUN_ONCE until exists $_[0]{_ae_sent};

Поставьте вместо EV::run EV::RUN_ONCE все что угодно и cpu будет жраться на все 100%, это просто PP!

localtime until exists $_[0]{_ae_sent};

3. Вывод: в больших программах? где используются любые другие «стражи» эта строчка «AE::cv->recv» безобидна. И она не всегда ест 100% cpu, а только тогда когда вы превратили программу во что-то другое, но не СОП.