Производительность Ооп-Пакетов В Perl

Как вы знаете, Perl не имеет очень удобной поддержки объектно-ориентированного программирования.

Если вы хотите программировать с помощью классов, вам придется многое делать вручную.

Однако Perl обладает очень богатыми возможностями расширения, поэтому со временем появилось множество библиотек (пакетов), обеспечивающих поддержку классов, методов и свойств с синтаксисом разной степени удобства.

Но как оказалось, эти пакеты проигрывают в производительности по сравнению с ручной реализацией ООП-проектов.

Те.

с одной стороны ими приятно пользоваться, но с другой стороны они замедляют работу кода.

Мне всегда хотелось знать, насколько медленнее становится код и какие из этих пакетов стоит использовать, а какие нет. Поэтому я решил провести небольшое исследование.



Обзор пакетов ООП
Во-первых, давайте сделаем краткий обзор доступных ООП-пакетов для Perl. Просто Перл Без каких-либо пакетов класс Perl можно создать следующим образом:
  
  
  
  
   
 
               Rate moose_sig     moose    moosex   vanilla
 moose_sig 104102/s        --       -0%       -0%      -74%
 moose     104383/s        0%        --       -0%      -74%
 moosex    104592/s        0%        0%        --      -74%
 vanilla   401924/s      286%      285%      284%        --
 
Тогда такой класс можно использовать следующим образом:
 
               Rate    moosex     moose moose_sig   vanilla
 moosex      8596/s        --      -94%      -94%      -95%
 moose     148055/s     1622%        --       -0%      -17%
 moose_sig 148516/s     1628%        0%        --      -17%
 vanilla   178254/s     1974%       20%       20%        --
 
лось Основы пакета лось идеи из Perl6. С его помощью создавать классы становится намного проще.

Предыдущий пример, переписанный с использованием Moose, будет выглядеть намного лучше:

  
 
                Rate    moosex moose_sig     moose   vanilla
 moosex    1503608/s        --       -1%       -1%      -17%
 moose_sig 1517928/s        1%        --       -0%      -16%
 moose     1517928/s        1%        0%        --      -16%
 vanilla   1815063/s       21%       20%       20%        --
 
Как видите, вам больше не нужно явно создавать метод. новый , и свойства теперь описываются гораздо проще и естественнее.

Но пока не все гладко.

Нам придется вручную распаковать параметр $self в каждом методе класса.

И в целом методы остались просто перловыми процедурами.

Хотелось бы, чтобы они больше походили на обычные методы.

Метод::Сигнатуры И тут нам на помощь приходит этот замечательный пакет: Метод::Сигнатуры .

Советую прочитать документацию по нему — там много приятных сюрпризов.

Это делает наш код еще лучше:

  
 
 Subroutine Dog::method redefined at /opt/local/lib/perl5/site_perl/5.14.1/darwin-thread-multi-2level/Devel/Declare/MethodInstaller/Simple.pm line 17.
 Prototype mismatch: sub Dog::method: none vs (&) at /opt/local/lib/perl5/site_perl/5.14.1/darwin-thread-multi-2level/Devel/Declare/MethodInstaller/Simple.pm line 17.
 
MooseX::Объявить Пытливые умы приверженцев Perl не остановились на этом, а пошли гораздо дальше и написали MooseX::Объявить .

Действительно замечательный комплект, если бы не один недостаток (об этом позже).

Теперь мы можем достичь полной нирваны в описании нашего класса.

Собака :

 
                Rate     moosex moosex_sig  moose_sig      moose    vanilla
 moosex       8651/s         --       -94%       -94%       -94%       -95%
 moosex_sig 146152/s      1589%         --        -1%        -3%       -18%
 moose_sig  148025/s      1611%         1%         --        -2%       -17%
 moose      150866/s      1644%         3%         2%         --       -16%
 vanilla    179200/s      1971%        23%        21%        19%         --
 


Производительность ООП-пакетов
Perl позволяет добиться практически полной естественности описания классов.

Но не радуйтесь.

Оказывается, эта естественность приводит к потере продуктивности.

Чтобы узнать, сколько стоит, сравним следующие характеристики:

  • Создание объекта класса.

  • Вызов метода.

  • Доступ к собственности.

Итак, давайте начнем.

Пакет будет использоваться для тестирования.

Контрольный показатель .

В результатах испытаний обозначения следующие:

  • vanilla — чистый Perl без дополнительных пакетов,
  • лось - с пакетом Moose,
  • moose_sig — с пакетом Moose и Method::Signatures,
  • moosex — с пакетом MooseX.
Создание объекта

package Dog; sub new { my ($class, %self) = @_; bless \%self, $class; return \%self; } sub make_noise { my $self = shift; say $self->{name}, " says: ruff-ruff!"; } 1;

Как видите, создание объектов с использованием всех пакетов ООП происходит почти в 4 раза медленнее, чем с использованием чистого Perl. Но есть одна хорошая новость: операция создания объекта с помощью Moose и MooseX::Declare занимает одинаковое время.

Поэтому, если вы используете один из этих пакетов, то предпочтение следует отдать MooseX::Declare. Вызов метода Перейдем к следующему пункту — вызову метода.

Здесь картина не столь примечательна:

use Dog; my $dog = Dog->new(name => "Snoopy"); $dog->make_noise();

MooseX проигрывает Moose (с подписями или без них) в 16 раз! Это, конечно, большой сюрприз.

Если вы покопаетесь в Интернете, то обнаружите, что причина такой большой разницы в производительности — пакет MooseX::Method::Signatures. Поэтому до тех пор, пока ситуация не улучшится, MooseX в таком виде использовать нельзя.

Однако хорошая новость заключается в том, что Moose + Method::Signatures всего на 20% медленнее, чем чистый Perl. Поэтому вы можете смело использовать эти пакеты без существенной потери производительности.

Доступ к собственности Перейдем к последнему пункту тестов, обращению к свойству объекта:

package Dog; use Moose; has name => (is => 'ro', isa => 'Str'); sub make_noise { my $self = shift; say $self->name(), " says: ruff-ruff!"; } __PACKAGE__->meta->make_immutable;

Опять же, потеря всех пакетов по сравнению с чистым Perl составляет всего 20%.

Как видите, здесь MooseX оказался не хуже других пакетов.

Если бы не MooseX::Method::Signatures.

Исправление MooseX
Я очень хочу использовать MooseX, но это очень больно.

Попробуем настроить его так, чтобы он был хоть немного лучше при вызове методов.

Первое, что приходит на ум, — использовать Method::Signatures вместе с MooseX::Declare. Давайте перепишем код Собака следующим образом:

package Dog; use Moose; use Method::Signatures; has name => (is => 'ro', isa => 'Str'); method make_noise() { say $self->name(), " says: ruff-ruff!"; } __PACKAGE__->meta->make_immutable;

Этот подход работает, но приводит к неприятному предупреждению:

use MooseX::Declare; class Dog { has name => (is => 'ro', isa => 'Str'); method make_noise() { say $self->name(), " says: ruff-ruff!"; } }

Это факт метод — это простая функция Perl, определенная как MooseX::Method::Signatures, так и Method::Signatures. Но они определены с разными прототипами, поэтому и возникает предупреждение.

К сожалению, я не нашел, как убрать это предупреждение.

Поэтому мне пришлось придумать другое решение.

Метод::Сигнатуры::Простой Что может быть проще! Метод::Сигнатуры::Простой — это упрощенная версия Method::Signatures, имеющая одно хорошее свойство.

Здесь вы можете задать собственное имя для функции метод , что позволяет избежать конфликта с MooseX::Method::Signatures. Используя этот пакет Собака будет выглядеть так:

use MooseX::Declare; class Dog { use Method::Signatures; has name => (is => 'ro', isa => 'Str'); method make_noise() { say $self->name(), " says: ruff-ruff!"; } }

Разница в том, что вместо метод мы сейчас пишем защита (как в Python).

Посмотрим, улучшилась ли производительность нашего кода (moosex_sig):

use MooseX::Declare; class Dog { use Method::Signatures::Simple name => 'def'; has name => (is => 'ro', isa => 'Str'); def make_noise() { say $self->name(), " says: ruff-ruff!"; } }

Наши ожидания оправдались.

MooseX::Declare + Method::Signature::Simple обеспечивает ту же производительность, что и Moose + Method::Signatures.

Заключение
Несмотря на все богатство выбора, альтернатива вырисовывается только одна.

На сегодняшний день моя лучшая рекомендация по использованию ООП в Perl — это комбинация пакетов MooseX::Declare и Method::Signatures::Simple. Он позволяет естественным образом описывать классы и имеет не очень высокую, можно даже сказать, вполне приемлемую цену с точки зрения производительности.

Приложение: Исходный код тестов доступен на github: github.com/alexeiz/oopbench Теги: #perl #ООП #производительность #perl #производительность #perl

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.