Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save martinpopel/bea01d8037d6baee01b8825e84e40c41 to your computer and use it in GitHub Desktop.
Save martinpopel/bea01d8037d6baee01b8825e84e40c41 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
use warnings;
use strict;
use Carp qw{ confess };
use List::Util qw{ shuffle };
use Test::More tests => 5;
use Benchmark qw{ cmpthese };
my @ATTRS;
my (
$ORD, $ROOT, $PARENT, $FIRSTCHILD, $NEXTSIBLING, $MISC, # both root and node
$FORM, $LEMMA, $UPOS, $XPOS, $FEATS, $DEPREL, $DEPS, # node only
);
BEGIN {
@ATTRS = qw(ord root parent firstchild nextsibling misc
form lemma upos xpos feats deprel deps);
($ORD, $ROOT, $PARENT, $FIRSTCHILD, $NEXTSIBLING, $MISC) = (0..5);
($FORM, $LEMMA, $UPOS, $XPOS, $FEATS, $DEPREL, $DEPS) = (6..12);
}
my $self = [ 'a'..'z' ];
sub ternary {
map {
$_ eq 'ord' ? $self->[$ORD]
: $_ eq 'form' ? $self->[$FORM]
: $_ eq 'lemma' ? $self->[$LEMMA]
: $_ eq 'upos' ? $self->[$UPOS]
: $_ eq 'xpos' ? $self->[$XPOS]
: $_ eq 'feats' ? $self->[$FEATS]
: $_ eq 'deprel' ? $self->[$DEPREL]
: $_ eq 'deps' ? $self->[$DEPS]
: $_ eq 'misc' ? $self->[$MISC]
: confess "Unknown attribute '$_'";
} @_;
}
{ my %h = ( ord => $ORD,
form => $FORM,
lemma => $LEMMA,
upos => $UPOS,
xpos => $XPOS,
feats => $FEATS,
deprel => $DEPREL,
deps => $DEPS,
misc => $MISC,
);
sub hash {
map {$self->[$h{$_} // confess("Unknown attribute '$_'")]} @_
}
}
my @values = shuffle qw( ord form lemma upos xpos feats deprel deps misc );
is_deeply [ ternary(@values) ], [ hash(@values) ], 'same values';
my $exception_regex = qr/^Unknown attribute 'x' at/;
isnt eval { ternary('x'); 1 }, 1, 'ternary dies';
like $@, $exception_regex, 'ternary exception';
isnt eval { hash('x'); 1 }, 1, 'hash dies';
like $@, $exception_regex, 'hash exception';
cmpthese( -5,
{ ternary => sub { ternary(@values) },
hash => sub { hash(@values) },
}
);
# Rate ternary hash
# ternary 142172/s -- -41%
# hash 241986/s 70% --
@martinpopel
Copy link
Author

The original comparison showed hash is 191% faster than ternary, but it was wrong:

  • ternary did an extra copy to @values (it makes the original subroutine get_attrs more readable when checking undefs; it should be either in both ternary and hash or in none).
  • hash did not access $self, but unfortunately this bug remained unnoticed because of the special values 0..12 assigned as values (so the values were the same as indices of the attributes).

Now, ternary is "just" 70% faster. So thanks @choroba for the suggestion, I will update the code.

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