Skip to content

Instantly share code, notes, and snippets.

@nrdvana
Last active November 29, 2021 19:14
Show Gist options
  • Save nrdvana/7b5724745f553a22860589aa45a51edd to your computer and use it in GitHub Desktop.
Save nrdvana/7b5724745f553a22860589aa45a51edd to your computer and use it in GitHub Desktop.
#! /usr/bin/env perl
use strict;
use warnings;
use Benchmark qw( :hireswallclock cmpthese );
{
package OP_Point;
use v5.26;
use Object::Pad;
class OP_Point {
has $x :param :accessor = 0;
has $y :param :accessor = 0;
method move {
$x += $_[0];
$y += $_[1];
}
}
}
{
package Moo_Point;
use v5.26;
use Class::XSAccessor;
use Moo;
has x => is => 'rw';
has y => is => 'rw';
sub move {
$_[0]->x($_[0]->x + $_[1]);
$_[0]->y($_[0]->y + $_[2]);
}
}
{
package XSA_Point;
use v5.26;
use Class::XSAccessor
constructor => "new",
accessors => ["x","y"];
sub move {
$_[0]->x($_[0]->x + $_[1]);
$_[0]->y($_[0]->y + $_[2]);
}
}
{
package XSAA_Point;
use v5.26;
use Class::XSAccessor::Array
accessors => { x => 0, y => 1 };
sub new { my $class= shift; my %p= @_; bless [$p{x}, $p{y}], $class; }
sub move {
$_[0]->x($_[0]->x + $_[1]);
$_[0]->y($_[0]->y + $_[2]);
}
}
{
package PP_Point;
use v5.26;
sub new {
bless { @_[1..$#_] }, $_[0]
}
sub x { $_[0]{x}= $_[1] if @_ > 1; $_[0]{x} }
sub y { $_[0]{y}= $_[1] if @_ > 1; $_[0]{y} }
sub move {
$_[0]{x}+= $_[1];
$_[0]{y}+= $_[2];
}
}
{
package PPA_Point;
use v5.26;
sub new {
my ($class, %p)= @_;
bless [ $p{x}, $p{y} ], $class;
}
sub x { $_[0][0]= $_[1] if @_ > 1; $_[0][0] }
sub y { $_[0][1]= $_[1] if @_ > 1; $_[0][1] }
sub move {
$_[0][0] += $_[1];
$_[0][1] += $_[2];
}
}
cmpthese(1000000, {
OP_Point => 'my $p= OP_Point->new(x => 10, y => 10); $p->move(1,1) for 1..3; ($p->x, $p->y) for 1..10',
Moo_Point => 'my $p= Moo_Point->new(x => 10, y => 10); $p->move(1,1) for 1..3; ($p->x, $p->y) for 1..10',
XSA_Point => 'my $p= XSA_Point->new(x => 10, y => 10); $p->move(1,1) for 1..3; ($p->x, $p->y) for 1..10',
XSAA_Point=> 'my $p= XSAA_Point->new(x => 10, y => 10);$p->move(1,1) for 1..3; ($p->x, $p->y) for 1..10',
PP_Point => 'my $p= PP_Point->new(x => 10, y => 10); $p->move(1,1) for 1..3; ($p->x, $p->y) for 1..10',
PPA_Point => 'my $p= PPA_Point->new(x => 10, y => 10); $p->move(1,1) for 1..3; ($p->x, $p->y) for 1..10',
});
@nrdvana
Copy link
Author

nrdvana commented Nov 29, 2021

My Results:

               Rate  OP_Point Moo_Point  PP_Point PPA_Point XSAA_Point XSA_Point
OP_Point   174520/s        --      -40%      -44%      -47%       -56%      -56%
Moo_Point  293255/s       68%        --       -6%      -11%       -26%      -27%
PP_Point   311526/s       79%        6%        --       -5%       -22%      -22%
PPA_Point  328947/s       88%       12%        6%        --       -17%      -18%
XSAA_Point 398406/s      128%       36%       28%       21%         --       -0%
XSA_Point  400000/s      129%       36%       28%       22%         0%        --

For some analysis, Cass::XSAccessor::Array doesn't have an XS constructor, so I had to write one in pure-perl. This is probably why it shows in the benchmark as slower than Class::XSAccessor. I picked the loop numbers as a rough estimate of how someone would use a point: create it, perform some translations on it, then use its coordinates a few times. Adjusting those loop numbers can give you a feel for how much constructor, method, and accessor play into the overall performance.

Moo is documented to use Class::XSAccessor when available, but I didn't verify whether it is doing this.

It's also worth noting that Moo_Point, XSA_Point, and XSAA_Point could all run faster if I used direct field access instead of accessors inside of the move() method. But OP_Point is already using it's fastest field access...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment