読者です 読者をやめる 読者になる 読者になる

Data::YUID::Generator を 32bit マシンでも使えるように

Perl

Data::YUID::Generator が 32bit でも動くように Math::BigInt 使ってみた。

ベンチマーク。new() が遅い。

# new->get_id
            Rate   bigint original
bigint    2635/s       --     -95%
original 51945/s    1872%       --

# get_id
             Rate   bigint original
bigint    79591/s       --     -70%
original 267101/s     236%       --
--- Generator.pm.orig	2009-05-27 13:21:21.000000000 +0900
+++ Generator.pm	2009-05-27 13:53:50.000000000 +0900
@@ -1,6 +1,6 @@
 # $Id: Generator.pm 1 2007-12-19 22:39:22Z miyagawa $
 
-package Data::YUID::Generator;
+package Data::YUID::Generator::BigInt;
 use strict;
 use warnings;
 no warnings qw(deprecated); # for fields
@@ -8,6 +8,7 @@
 use vars qw{$VERSION};
 $VERSION = "0.01";
 
+use Math::BigInt lib => "GMP";
 use fields qw(host_id start_time current_time min_id max_id ids);
 
 use constant EPOCH_OFFSET => 946684800; # Sat, Jan 1 2000 00:00 GMT
@@ -19,17 +20,17 @@
 use constant TIME_SHIFT => HOST_ID_BITS + SERIAL_BITS;
 use constant SERIAL_SHIFT => HOST_ID_BITS;
 
-use constant SERIAL_INCREMENT => 1 << SERIAL_SHIFT;
+use constant SERIAL_INCREMENT => Math::BigInt->new(1) << SERIAL_SHIFT;
 
-use constant HOST_ID_MAX => (1 << HOST_ID_BITS) - 1;
-use constant TIME_MAX => (1 << TIME_BITS) - 1;
+use constant HOST_ID_MAX => (Math::BigInt->new(1) << HOST_ID_BITS) - 1;
+use constant TIME_MAX => (Math::BigInt->new(1) << TIME_BITS) - 1;
 use constant TIME_MAX_SHIFTED => TIME_MAX << TIME_SHIFT;
-use constant SERIAL_MAX => (1 << SERIAL_BITS) - 1;
+use constant SERIAL_MAX => (Math::BigInt->new(1) << SERIAL_BITS) - 1;
 use constant SERIAL_MAX_SHIFTED => SERIAL_MAX << SERIAL_SHIFT;
 
 
 sub new {
-    my Data::YUID::Generator $self = shift;
+    my Data::YUID::Generator::BigInt $self = shift;
     $self = fields::new( $self ) unless ref $self;
     
     my $host_id = shift;
@@ -63,7 +64,7 @@
 sub _make_id ($) {
     my $self = shift;
     my $serial = shift || 0;
-    return (($self->{ current_time } - EPOCH_OFFSET) << TIME_SHIFT) |
+    return ( Math::BigInt->new($self->{ current_time } - EPOCH_OFFSET) << TIME_SHIFT) |
         ($serial << SERIAL_SHIFT) | $self->{ host_id };
         
 }