~ubuntu-branches/ubuntu/wily/libsereal-encoder-perl/wily

« back to all changes in this revision

Viewing changes to author_tools/bench.pl

  • Committer: Package Import Robot
  • Author(s): Alexandre Mestiashvili, Alexandre Mestiashvili, gregor herrmann
  • Date: 2015-04-29 11:12:18 UTC
  • mfrom: (17.1.6 sid)
  • Revision ID: package-import@ubuntu.com-20150429111218-v3ghc7ck5gcr38fu
Tags: 3.005.001-1
[ Alexandre Mestiashvili ]
* Imported Upstream version 3.005.001
* d/control: cme fix dpkg
* d/copyright: updated debian/* copyright year

[ gregor herrmann ]
* Mark package as autopkgtest-able.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
use warnings;
3
3
use blib;
4
4
use Benchmark qw(cmpthese :hireswallclock);
5
 
use Sereal::Decoder qw(decode_sereal);
6
 
use Sereal::Encoder qw(encode_sereal);
7
 
use JSON::XS qw(decode_json encode_json);
 
5
use Sereal::Decoder qw(decode_sereal sereal_decode_with_object);
 
6
use Sereal::Encoder qw(encode_sereal sereal_encode_with_object);
8
7
use Storable qw(nfreeze thaw);
9
 
use Data::Undump qw(undump);
10
8
use Data::Dumper qw(Dumper);
11
 
use Data::Dumper::Limited qw(DumpLimited);
12
 
use Data::MessagePack;
13
 
use CBOR::XS qw(encode_cbor decode_cbor);
 
9
 
 
10
 
14
11
use Getopt::Long qw(GetOptions);
15
 
 
16
 
my (
17
 
    $duration,
18
 
    $encoder,
19
 
    $decoder,
20
 
    $dump,
21
 
    $tiny_data,
22
 
    $small_data,
23
 
    $medium_data,
24
 
    $large_data,
25
 
    $very_large_data,
26
 
    $nobless,
27
 
    $diagrams,
28
 
    $diagram_output_dir,
29
 
);
30
 
BEGIN {
31
 
    my $sereal_only = 0;
32
 
    GetOptions(
33
 
        'duration=f' => \($duration=-3),
34
 
        'encoder'   => \$encoder,
35
 
        'decoder'   => \$decoder,
36
 
        'dump|d'    => \$dump,
37
 
        'tiny'      => \$tiny_data,
38
 
        'small'     => \$small_data,
39
 
        'medium'    => \$medium_data,
40
 
        'large'     => \$large_data,
41
 
        'very_large|very-large|verylarge' => \$very_large_data,
42
 
        'no_bless|no-bless|nobless'    => \$nobless,
43
 
        'sereal_only|sereal-only|serealonly' => \$sereal_only,
44
 
        'diagrams'  => \$diagrams,
45
 
        'diagram_output=s' => \$diagram_output_dir,
46
 
    );
47
 
    eval "sub SEREAL_ONLY () { $sereal_only }";
48
 
}
49
 
 
50
 
my $fail = do {no warnings; $tiny_data + $small_data + $medium_data + $very_large_data + $large_data - 1};
51
 
if ($fail and $fail > 0) {
 
12
require bytes;
 
13
 
 
14
GetOptions(
 
15
    'secs|duration=f'                    => \( my $duration           = -5 ),
 
16
    'encoder'                            => \( my $encoder            = 0 ),
 
17
    'decoder'                            => \( my $decoder            = 0 ),
 
18
    'dump|d'                             => \( my $dump               = 0 ),
 
19
    'only=s@'                            => \( my $only               = undef ),
 
20
    'exclude=s@'                         => \( my $exclude            = undef ),
 
21
    'tiny'                               => \( my $tiny_data          = 0 ),
 
22
    'small'                              => \( my $small_data         = 0 ),
 
23
    'medium'                             => \( my $medium_data        = 0 ),
 
24
    'large'                              => \( my $large_data         = 0 ),
 
25
    'very_large|very-large|verylarge'    => \( my $very_large_data    = 0 ),
 
26
    'no_bless|no-bless|nobless'          => \( my $nobless            = 0 ),
 
27
    'sereal_only|sereal-only|serealonly' => \( my $sereal_only        = 0 ),
 
28
    'diagrams'                           => \( my $diagrams           = 0 ),
 
29
    'diagram_output=s'                   => \( my $diagram_output_dir = "" ),
 
30
) or die "Bad option";
 
31
 
 
32
my $fail =
 
33
  $tiny_data + $small_data + $medium_data + $very_large_data + $large_data - 1;
 
34
if ( $fail and $fail > 0 ) {
52
35
    die "Only one of --tiny, --small, --medium, --large, --very-large allowed!";
53
36
}
54
37
$encoder = 1 if not $encoder and not $decoder;
55
38
 
56
 
our %opt = @ARGV;
57
 
 
58
 
our $mpo = Data::MessagePack->new();
 
39
#our %opt = @ARGV;
 
40
our %opt;
59
41
 
60
42
my $data_set_name;
61
43
srand(0);
62
 
my $chars = join("", "a".."z", "A".."Z") x 2;
 
44
my $chars = join( "", "a" .. "z", "A" .. "Z" ) x 2;
63
45
my @str;
64
 
push @str, substr($chars, int(rand(int(length($chars)/2+1))), 10) for 1..1000;
65
 
my @rand = map rand, 1..1000;
 
46
push @str, substr( $chars, int( rand( int( length($chars) / 2 + 1 ) ) ), 10 )
 
47
  for 1 .. 1000;
 
48
my @rand = map rand, 1 .. 1000;
 
49
 
 
50
our (
 
51
    $enc, $dec,
 
52
    $enc_snappy,        $dec_snappy,
 
53
    $enc_zlib_fast,     $dec_zlib_fast,
 
54
    $enc_zlib_small,    $dec_zlib_small,
 
55
    $jsonxs, $msgpack, $dd_noindent, $dd_indent, $cbor
 
56
);
 
57
my $storable_tag= "strbl";
 
58
my $sereal_tag= "srl";
 
59
my %meta = (
 
60
    jxs => {
 
61
        enc  => '$::jsonxs->encode($data);',
 
62
        dec  => '$::jsonxs->decode($encoded);',
 
63
        name => 'JSON::XS OO',
 
64
        init => sub {
 
65
            $jsonxs = JSON::XS->new()->allow_nonref();
 
66
        },
 
67
        use => 'use JSON::XS qw(decode_json encode_json);',
 
68
    },
 
69
    ddl => {
 
70
        enc  => 'DumpLimited($data);',
 
71
        dec  => 'Data::Undump::undump($encoded);',
 
72
        name => 'Data::Dump::Limited',
 
73
        use  => [
 
74
                    'use Data::Undump qw(undump);',
 
75
                    'use Data::Dumper::Limited qw(DumpLimited);',
 
76
                ],
 
77
    },
 
78
    mp => {
 
79
        enc  => '$::msgpack->pack($data);',
 
80
        dec  => '$::msgpack->unpack($encoded);',
 
81
        name => 'Data::MsgPack',
 
82
        use  => 'use Data::MessagePack;',
 
83
        init => sub {
 
84
            $msgpack = Data::MessagePack->new();
 
85
        },
 
86
    },
 
87
    cbor => {
 
88
        enc  => '$::cbor->encode($data);',
 
89
        dec  => '$::cbor->decode($encoded);',
 
90
        name => 'CBOR::XS',
 
91
        use => 'use CBOR::XS qw(encode_cbor decode_cbor);',
 
92
        init => sub {
 
93
            $cbor= CBOR::XS->new();
 
94
        },
 
95
    },
 
96
    dd_noind => {
 
97
        enc  => 'Data::Dumper->new([$data])->Indent(0)->Dump();',
 
98
        dec  => 'eval $encoded;',
 
99
        name => 'Data::Dumper no-indent',
 
100
    },
 
101
    dd => {
 
102
        enc  => 'Dumper($data);',
 
103
        dec  => 'eval $encoded;',
 
104
        name => 'Data::Dumper indented',
 
105
    },
 
106
    $storable_tag => {
 
107
        enc  => 'nfreeze($data);',
 
108
        dec  => 'thaw($encoded);',
 
109
        name => 'Storable',
 
110
    },
 
111
    srl_func => {
 
112
        enc  => 'encode_sereal($data, $opt);',
 
113
        dec  => 'decode_sereal($encoded, $opt);',
 
114
        name => 'Sereal functional',
 
115
    },
 
116
    srl_fwo => {
 
117
        enc  => 'sereal_encode_with_object($::enc,$data);',
 
118
        dec  => 'sereal_decode_with_object($::dec,$encoded);',
 
119
        name => 'Sereal functional with object',
 
120
    },
 
121
    $sereal_tag => {
 
122
        enc  => '$::enc->encode($data);',
 
123
        dec  => '$::dec->decode($encoded);',
 
124
        name => 'Sereal OO',
 
125
        init => sub {
 
126
            $enc = Sereal::Encoder->new( %opt ? \%opt : () );
 
127
            $dec = Sereal::Decoder->new( \%opt ? \%opt : () );
 
128
        },
 
129
    },
 
130
    srl_snpy => {
 
131
        enc  => '$::enc_snappy->encode($data);',
 
132
        dec  => '$::dec_snappy->decode($encoded);',
 
133
        name => 'Sereal OO snappy',
 
134
        init => sub {
 
135
            $enc_snappy = Sereal::Encoder->new(
 
136
                {
 
137
                    %opt,
 
138
                    compress => Sereal::Encoder::SRL_SNAPPY
 
139
                }
 
140
            );
 
141
            $dec_snappy = Sereal::Decoder->new( %opt ? \%opt : () );
 
142
        },
 
143
    },
 
144
    srl_zfast => {
 
145
        enc  => '$::enc_zlib_fast->encode($data);',
 
146
        dec  => '$::dec_zlib_fast->decode($encoded);',
 
147
        name => 'Sereal OO zlib fast',
 
148
        init => sub {
 
149
            $enc_zlib_fast = Sereal::Encoder->new(
 
150
                {
 
151
                    %opt,
 
152
                    compress           => Sereal::Encoder::SRL_ZLIB,
 
153
                    compress_level     => 1,
 
154
                    compress_threshold => 0,
 
155
                }
 
156
            );
 
157
            $dec_zlib_fast = Sereal::Decoder->new( %opt ? \%opt : () );
 
158
        },
 
159
    },
 
160
    srl_zbest => {
 
161
        enc  => '$::enc_zlib_small->encode($data);',
 
162
        dec  => '$::dec_zlib_small->decode($encoded);',
 
163
        name => 'Sereal OO zib best',
 
164
        init => sub {
 
165
            $enc_zlib_small = Sereal::Encoder->new(
 
166
                {
 
167
                    %opt,
 
168
                    compress           => Sereal::Encoder::SRL_ZLIB,
 
169
                    compress_level     => 10,
 
170
                    compress_threshold => 0,
 
171
                }
 
172
            );
 
173
            $dec_zlib_small = Sereal::Decoder->new( %opt ? \%opt : () );
 
174
        },
 
175
    },
 
176
);
 
177
if ($only) {
 
178
    my @pat= map { split /\s*,\s*/, $_ } @$only;
 
179
    $only = {};
 
180
    foreach my $key (keys %meta) {
 
181
        $key=~/$_/ and $only->{$key}= 1
 
182
            for @pat;
 
183
    }
 
184
    die "Only [@pat] produced no matches!" unless keys %$only;
 
185
}
 
186
if ($exclude) {
 
187
    my @pat= map { split /\s*,\s*/, $_ } @$exclude;
 
188
    $exclude = {};
 
189
    foreach my $key (keys %meta) {
 
190
        $key=~/$_/ and $exclude->{$key}= 1
 
191
            for @pat;
 
192
    }
 
193
    die "Exclude [@pat] produced no matches!" unless keys %$exclude;
 
194
}
 
195
 
66
196
our %data;
67
 
 
68
 
$data{$_}= make_data() for qw(sereal sereal_func dd1 dd2 ddl mp json_xs storable sereal_snappy sereal_zlib_fast sereal_zlib_small cbor);
69
 
 
70
 
our $enc = Sereal::Encoder->new(\%opt);
71
 
our $enc_snappy = Sereal::Encoder->new({%opt, compress => Sereal::Encoder::SRL_SNAPPY});
72
 
our $enc_zlib_fast = Sereal::Encoder->new({%opt, compress => Sereal::Encoder::SRL_ZLIB, compress_level => 1, compress_threshold => 0});
73
 
our $enc_zlib_small = Sereal::Encoder->new({%opt, compress => Sereal::Encoder::SRL_ZLIB, compress_level => 10, compress_threshold => 0});
74
 
our $dec = Sereal::Decoder->new(\%opt);
75
 
 
76
 
our ($json_xs, $dd1, $dd2, $ddl, $sereal, $storable, $mp, $sereal_snappy, $sereal_zlib_fast, $sereal_zlib_small, $cbor);
77
 
# do this first before any of the other dumpers "contaminate" the iv/pv issue
78
 
$sereal            = $enc->encode($data{sereal});
79
 
$sereal_snappy     = $enc_snappy->encode($data{sereal_snappy});
80
 
$sereal_zlib_fast  = $enc_zlib_fast->encode($data{sereal_zlib_fast});
81
 
$sereal_zlib_small = $enc_zlib_small->encode($data{sereal_zlib_small});
82
 
if (!SEREAL_ONLY) {
83
 
    $json_xs  = encode_json($data{json_xs}) if !$medium_data or $nobless;
84
 
    $dd1      = Data::Dumper->new([$data{dd1}])->Indent(0)->Dump();
85
 
    $dd2      = Dumper($data{dd2});
86
 
    $ddl      = DumpLimited($data{ddl}) if !$medium_data or $nobless;
87
 
    $mp       = $mpo->pack($data{mp}) if !$medium_data or $nobless;
88
 
    $cbor     = encode_cbor($data{cbor}) if !$medium_data or $nobless;
89
 
    $storable = nfreeze($data{storable});
 
197
our %encoded;
 
198
our %decoded;
 
199
our %enc_bench;
 
200
our %dec_bench;
 
201
foreach my $key ( sort keys %meta ) {
 
202
    my $info = $meta{$key};
 
203
    $info->{tag}= $key;
 
204
    next if $only    and not $only->{$key}    and $key ne $storable_tag;
 
205
    next if $exclude and     $exclude->{$key} and $key ne $storable_tag;
 
206
    if (my $use= $info->{use}) {
 
207
        $use= [$use] unless ref $use;
 
208
        $use= join ";\n", @$use, 1;
 
209
        unless (eval $use) {
 
210
            warn "Can't load dependencies for $info->{name}, skipping\n";
 
211
            next;
 
212
        }
 
213
    }
 
214
    $info->{enc}=~s/\$data/\$::data{$key}/g;
 
215
    $info->{dec}=~s/\$encoded/\$::encoded{$key}/g;
 
216
    $info->{enc}=~s/\$opt/%opt ? "\\%::opt" : ""/ge;
 
217
    $info->{dec}=~s/\$opt/%opt ? "\\%::opt" : ""/ge;
 
218
 
 
219
    $data{$key}    = make_data();
 
220
    $info->{init}->() if $info->{init};
 
221
    $encoded{$key} = eval $info->{enc}
 
222
      or die "Failed to eval $info->{enc}: $@";
 
223
    $decoded{$key} = eval '$::x = ' . $info->{dec} . '; 1'
 
224
      or die "Failed to eval $info->{dec}: $@\n$encoded{$key}\n";
 
225
    $info->{size}    = bytes::length( $encoded{$key} );
 
226
    next if $only    and not $only->{$key};
 
227
    next if $exclude and     $exclude->{$key};
 
228
    $enc_bench{$key} = '$::x_' . $key . ' = ' . $info->{enc};
 
229
    $dec_bench{$key} = '$::x_' . $key . ' = ' . $info->{dec};
90
230
}
 
231
 
 
232
my $sereal = $encoded{$sereal_tag};
91
233
print($sereal), exit if $dump;
92
234
 
93
 
my $sereal_len= bytes::length($sereal);
94
 
require bytes;
95
 
my @size_datasets;
96
 
if (!SEREAL_ONLY) {
97
 
    @size_datasets = (
98
 
        (($medium_data && !$nobless) ? () : (
99
 
            ["JSON::XS",  bytes::length($json_xs)],
100
 
            ["Data::Dumper::Limited", bytes::length($ddl)],
101
 
            ["Data::MessagePack", bytes::length($mp)],
102
 
            ["CBOR",  bytes::length($cbor)],
103
 
        )),
104
 
        ["Data::Dumper (1)", bytes::length($dd1)],
105
 
        ["Data::Dumper (2)", bytes::length($dd2)],
106
 
        ["Storable", bytes::length($storable)],
107
 
        ["Sereal::Encoder",  bytes::length($sereal)],
108
 
        ["Sereal::Encoder, Snappy",  bytes::length($sereal_snappy)],
109
 
        ["Sereal::Encoder, Zlib (fast)",  bytes::length($sereal_zlib_fast)],
110
 
        ["Sereal::Encoder, Zlib (small)",  bytes::length($sereal_zlib_small)],
111
 
    );
112
 
    for my $tuple (@size_datasets) {
113
 
        my ($name, $size) = @$tuple;
114
 
        printf "%-40s %12d bytes %.2f%% of sereal\n", $name, $size, $size/$sereal_len *100;
 
235
my $storable_len = bytes::length($encoded{$storable_tag});
 
236
foreach my $info (
 
237
    sort { $a->{size} <=> $b->{size} || $a->{name} cmp $b->{name} }
 
238
    grep { defined $_->{size} }
 
239
    values %meta
 
240
) {
 
241
    next unless $info->{size};
 
242
    if ($info->{tag} eq $storable_tag) {
 
243
        printf "%-40s %12d bytes\n",
 
244
            $info->{name} . " ($info->{tag})", $info->{size};
 
245
    } else {
 
246
        printf "%-40s %12d bytes %6.2f%% of $storable_tag\n",
 
247
            $info->{name} . " ($info->{tag})", $info->{size},
 
248
            $info->{size} / $storable_len * 100;
115
249
    }
116
250
}
117
251
 
118
252
our $x;
119
 
my ($encoder_result, $decoder_result);
 
253
my ( $encoder_result, $decoder_result );
120
254
if ($encoder) {
121
 
    $encoder_result = cmpthese(
122
 
        $duration,
123
 
        {
124
 
            (!SEREAL_ONLY
125
 
                ? (
126
 
                    ($medium_data && !$nobless ? () : (
127
 
                        json_xs => '$::x = encode_json($::data{json_xs});',
128
 
                        ddl => '$::x = DumpLimited($::data{ddl});',
129
 
                        msgpack => '$::x = $::mpo->pack($::data{mp});',
130
 
                        cbor => '$::x = encode_cbor($::data{cbor});',
131
 
                    )),
132
 
                    dd_noindent => '$::x = Data::Dumper->new([$::data{dd1}])->Indent(0)->Dump();',
133
 
                    dd => '$::x = Dumper($::data{dd2});',
134
 
                    storable => '$::x = nfreeze($::data{storable});',
135
 
                ) : ()),
136
 
            sereal_func => '$::x = encode_sereal($::data{sereal_func}, \%::opt);',
137
 
            sereal => '$::x = $::enc->encode($::data{sereal});',
138
 
            sereal_snappy => '$::x = $::enc_snappy->encode($::data{sereal_snappy});',
139
 
            sereal_zlib_fast => '$::x = $::enc_zlib_fast->encode($::data{sereal_zlib_fast});',
140
 
            sereal_zlib_small => '$::x = $::enc_zlib_small->encode($::data{sereal_zlib_small});',
141
 
        }
142
 
    );
 
255
    print "\n* Timing encoders\n";
 
256
    $encoder_result = cmpthese( $duration, \%enc_bench );
143
257
}
144
258
 
145
259
if ($decoder) {
146
 
    $decoder_result = cmpthese(
147
 
        $duration,
148
 
        {
149
 
            (!SEREAL_ONLY
150
 
                ? (
151
 
                    ($medium_data && !$nobless ? () : (
152
 
                        json_xs => '$::x = decode_json($::json_xs);',
153
 
                        undump_ddl => '$::x = Data::Undump::undump($::ddl);',
154
 
                        msgpack => '$::x = $::mpo->unpack($::mp);',
155
 
                        cbor => '$::x = decode_cbor($::cbor);',
156
 
                    )),
157
 
                    eval_dd => '$::x = eval $::dd1;',
158
 
                    storable => '$::x = thaw($::storable);',
159
 
                ) : ()),
160
 
            sereal_func => '$::x = decode_sereal($::sereal, \%::opt);',
161
 
            sereal => '$::x = $::dec->decode($::sereal);',
162
 
            sereal_snappy => '$::x = $::dec->decode($::sereal_snappy);',
163
 
            sereal_zlib_fast => '$::x = $::dec->decode($::sereal_zlib_fast);',
164
 
            sereal_zlib_small => '$::x = $::dec->decode($::sereal_zlib_small);',
165
 
        }
166
 
    );
 
260
    print "\n* Timing decoders\n";
 
261
    $decoder_result = cmpthese( $duration, \%dec_bench );
167
262
}
168
263
 
169
264
sub make_data {
173
268
    }
174
269
    elsif ($small_data) {
175
270
        $data_set_name = "small hash";
176
 
        return { foo=> 1, bar => [100,101,102], str => "this is a \x{df} string which has to be serialized" };
 
271
        return {
 
272
            foo => 1,
 
273
            bar => [ 100, 101, 102 ],
 
274
            str => "this is a \x{df} string which has to be serialized"
 
275
        };
177
276
    }
178
277
    elsif ($medium_data) {
179
278
        my @obj = (
180
 
            { foo => 1, bar => [100,101,102], str => "this is a \x{df} string which has to be serialized" },
181
 
            { foo => 2, bar => [103,103,106,999], str2 => "this is a \x{df} aaaaaastring which has to be serialized" },
182
 
            { foozle => 3, bar => [100], str3 => "this is a \x{df} string which haaaaadsadas to be serialized" },
183
 
            { foozle => 3, bar => [], st4r => "this is a \x{df} string which has to be sdassdaerialized" },
184
 
            { foo => 1, bar => [100,101,102], s5tr => "this is a \x{df} string which has to be serialized" },
185
 
            { foo => 2, bar => [103,103,106,999], str => "this is a \x{df} aaaaaastring which has to be serialized" },
186
 
            { foozle => 3, bar => [100], str => "this is a \x{df} string which haaaaadsadas to be serialized" },
187
 
            { foozle => 3, bar => [], str2 => "this is a \x{df} string which has to be sdassdaerialized" },
188
 
            { foo2 => -99999, bar => [100,101,102], str2 => "this is a \x{df} string which has to be serialized" },
189
 
            { foo2 => 213, bar => [103,103,106,999], str => "this is a \x{df} aaaaaastring which has to be serialized" },
190
 
            { foozle2 => undef, bar => [100], str => "this is a \x{df} string which haaaaadsadas to be serialized" },
191
 
            { foozle2 => undef, bar => [1..20], str => "this is a \x{df} string which has to be sdassdaerialized" },
 
279
            {
 
280
                foo => 1,
 
281
                bar => [ 100, 101, 102 ],
 
282
                str => "this is a \x{df} string which has to be serialized"
 
283
            },
 
284
            {
 
285
                foo => 2,
 
286
                bar => [ 103, 103, 106, 999 ],
 
287
                str2 =>
 
288
                  "this is a \x{df} aaaaaastring which has to be serialized"
 
289
            },
 
290
            {
 
291
                foozle => 3,
 
292
                bar    => [100],
 
293
                str3 =>
 
294
                  "this is a \x{df} string which haaaaadsadas to be serialized"
 
295
            },
 
296
            {
 
297
                foozle => 3,
 
298
                bar    => [],
 
299
                st4r =>
 
300
                  "this is a \x{df} string which has to be sdassdaerialized"
 
301
            },
 
302
            {
 
303
                foo  => 1,
 
304
                bar  => [ 100, 101, 102 ],
 
305
                s5tr => "this is a \x{df} string which has to be serialized"
 
306
            },
 
307
            {
 
308
                foo => 2,
 
309
                bar => [ 103, 103, 106, 999 ],
 
310
                str =>
 
311
                  "this is a \x{df} aaaaaastring which has to be serialized"
 
312
            },
 
313
            {
 
314
                foozle => 3,
 
315
                bar    => [100],
 
316
                str =>
 
317
                  "this is a \x{df} string which haaaaadsadas to be serialized"
 
318
            },
 
319
            {
 
320
                foozle => 3,
 
321
                bar    => [],
 
322
                str2 =>
 
323
                  "this is a \x{df} string which has to be sdassdaerialized"
 
324
            },
 
325
            {
 
326
                foo2 => -99999,
 
327
                bar  => [ 100, 101, 102 ],
 
328
                str2 => "this is a \x{df} string which has to be serialized"
 
329
            },
 
330
            {
 
331
                foo2 => 213,
 
332
                bar  => [ 103, 103, 106, 999 ],
 
333
                str =>
 
334
                  "this is a \x{df} aaaaaastring which has to be serialized"
 
335
            },
 
336
            {
 
337
                foozle2 => undef,
 
338
                bar     => [100],
 
339
                str =>
 
340
                  "this is a \x{df} string which haaaaadsadas to be serialized"
 
341
            },
 
342
            {
 
343
                foozle2 => undef,
 
344
                bar     => [ 1 .. 20 ],
 
345
                str =>
 
346
                  "this is a \x{df} string which has to be sdassdaerialized"
 
347
            },
192
348
        );
193
349
        my @classes = qw(Baz Baz Baz3 Baz2 Baz Baz Baz3 Baz2 Baz Baz Baz3 Baz2);
194
 
        if (!$nobless) {
195
 
            bless($obj[$_], $classes[$_]) for 0..$#obj;
 
350
        if ( $nobless ) {
 
351
            $data_set_name = "array of small hashes with relations";
 
352
        }
 
353
        else {
 
354
            bless( $obj[$_], $classes[$_] ) for 0 .. $#obj;
196
355
            $data_set_name = "array of small objects with relations";
197
356
        }
198
 
        else {
199
 
            $data_set_name = "array of small hashes with relations";
200
 
        }
201
 
        foreach my $i (1..$#obj) {
202
 
            $obj[$i]->{parent} = $obj[$i-1];
 
357
        foreach my $i ( 1 .. $#obj ) {
 
358
            $obj[$i]->{parent} = $obj[ $i - 1 ];
203
359
        }
204
360
        return \@obj;
205
361
    }
206
 
    elsif ($very_large_data) { # "large data"
 
362
    elsif ($very_large_data) {    # "large data"
207
363
        $data_set_name = "really rather large data structure";
208
364
        my @refs = (
209
 
            [1..10000], {@str}, {@str}, [1..10000],
 
365
            [ 1 .. 10000 ],
 
366
            {@str}, {@str}, [ 1 .. 10000 ],
210
367
            {@str}, [@rand], {@str}, {@str},
211
368
        );
212
369
        return [
213
 
            \@refs, \@refs, [map {[reverse 1..100]} (0..1000)], [map {+{foo => "bar", baz => "buz"}} 1..2000]
214
 
        ]
 
370
            \@refs, \@refs,
 
371
            [ map { [ reverse 1 .. 100 ] } ( 0 .. 1000 ) ],
 
372
            [ map { +{ foo => "bar", baz => "buz" } } 1 .. 2000 ]
 
373
        ];
215
374
    }
216
 
    else { # "large data"
 
375
    else {    # "large data"
217
376
        $data_set_name = "large data structure";
218
377
        return [
219
 
            [1..10000], {@str}, {@str}, [1..10000],
 
378
            [ 1 .. 10000 ], {@str}, {@str}, [ 1 .. 10000 ],
220
379
            {@str}, [@rand], {@str}, {@str},
221
 
        ]
 
380
        ];
222
381
    }
223
382
}
224
383
 
227
386
    SOOT::Init(0);
228
387
    SOOT->import(":all");
229
388
 
230
 
    my ($enc_data, $dec_data);
 
389
    my ( $enc_data, $dec_data );
231
390
    $enc_data = cmpthese_to_sanity($encoder_result) if $encoder_result;
232
391
    $dec_data = cmpthese_to_sanity($decoder_result) if $decoder_result;
233
392
 
234
 
    foreach my $dia (["Encoder performance [1/s]", $enc_data],
235
 
                     ["Decoder performance [1/s]", $dec_data],)
 
393
    foreach my $dia (
 
394
        [ "Encoder performance [1/s]", $enc_data ],
 
395
        [ "Decoder performance [1/s]", $dec_data ],
 
396
      )
236
397
    {
237
 
        my ($title, $d) = @$dia;
 
398
        my ( $title, $d ) = @$dia;
238
399
        next if not $d;
239
400
        $_->[0] =~ s/_/ /g, $_->[0] =~ s/sereal /sereal, / for @$d;
240
401
        make_bar_chart(
241
 
            substr($title, 0, 3),
 
402
            substr( $title, 0, 3 ),
242
403
            $d,
243
404
            {
244
 
                title => $title,
 
405
                title    => $title,
245
406
                filename => do {
246
407
                    my $x = $title;
247
408
                    $x =~ s/\[1\/s\]/per second/;
248
 
                    $data_set_name . " - " . $x
 
409
                    $data_set_name . " - " . $x;
249
410
                },
250
411
            }
251
412
        );
252
413
    }
253
414
 
254
415
    my %names = (
255
 
        "JSON::XS" => 'json xs',
256
 
        "Data::Dumper::Limited" => 'ddl',
257
 
        "Data::MessagePack" => "msgpack",
258
 
        "Data::Dumper (1)" => "dd noindent",
259
 
        "Data::Dumper (2)" => "dd",
260
 
        "Storable" => 'storable',
261
 
        "Sereal::Encoder" => 'sereal',
 
416
        "JSON::XS"                => 'json xs',
 
417
        "Data::Dumper::Limited"   => 'ddl',
 
418
        "Data::MessagePack"       => "msgpack",
 
419
        "Data::Dumper (1)"        => "dd noindent",
 
420
        "Data::Dumper (2)"        => "dd",
 
421
        "Storable"                => 'storable',
 
422
        "Sereal::Encoder"         => 'sereal',
262
423
        "Sereal::Encoder, Snappy" => 'sereal, snappy',
263
424
    );
264
425
 
265
426
    make_bar_chart(
266
427
        "size",
267
428
        [
268
 
            sort {$b->[1] <=> $a->[1]} map [ $names{$_->[0]}||die, $_->[1] ], @size_datasets
 
429
            sort { $b->[1] <=> $a->[1] }
 
430
            map { $_->{size} ? [ $_->{name}, $_->{size} ] : () } values %meta
269
431
        ],
270
432
        {
271
 
            title => "Encoded output sizes [bytes]",
272
 
            color => kRed(),
 
433
            title    => "Encoded output sizes [bytes]",
 
434
            color    => kRed(),
273
435
            filename => $data_set_name . " - Encoded output sizes in bytes",
274
436
        },
275
437
    );
277
439
}
278
440
 
279
441
sub make_bar_chart {
280
 
    my ($name, $data, $opts) = @_;
281
 
    my $h = TH1D->new($name, ($opts->{title}||$name), scalar(@$data), -0.5, scalar(@$data)-0.5);
 
442
    my ( $name, $data, $opts ) = @_;
 
443
    my $h = TH1D->new( $name, ( $opts->{title} || $name ),
 
444
        scalar(@$data), -0.5, scalar(@$data) - 0.5 );
282
445
    $h->keep;
283
 
    $h->SetFillColor($opts->{color} || kBlue());
 
446
    $h->SetFillColor( $opts->{color} || kBlue() );
284
447
    $h->SetBarOffset(0.12);
285
448
    $h->SetBarWidth(0.74);
286
449
    $h->SetStats(0);
287
450
    $h->GetXaxis()->SetLabelSize(0.06);
288
451
    $h->GetXaxis()->SetLabelOffset(0.009);
289
 
    $h->GetYaxis()->SetTitle($opts->{title}) if defined $opts->{title};
 
452
    $h->GetYaxis()->SetTitle( $opts->{title} ) if defined $opts->{title};
290
453
    $h->GetYaxis()->SetTitleSize(0.045);
291
 
    for my $i (1..@$data) {
292
 
        my ($label, $rate) = @{ $data->[$i-1] };
293
 
        $h->GetXaxis()->SetBinLabel($i, $label);
294
 
        $h->SetBinContent($i, 0+$rate);
 
454
 
 
455
    for my $i ( 1 .. @$data ) {
 
456
        my ( $label, $rate ) = @{ $data->[ $i - 1 ] };
 
457
        $h->GetXaxis()->SetBinLabel( $i, $label );
 
458
        $h->SetBinContent( $i, 0 + $rate );
295
459
    }
296
460
    my $c = TCanvas->new->keep;
297
461
    $c->GetPad(0)->SetBottomMargin(0.175);
302
466
    if ($diagram_output_dir) {
303
467
        require File::Path;
304
468
        File::Path::mkpath($diagram_output_dir);
305
 
        my $file = $opts->{filename} || do {my $f = $opts->{title}; $f =~ s/[^a-zA-Z0-9_\ ]/_/g; $f};
 
469
        my $file = $opts->{filename}
 
470
          || do { my $f = $opts->{title}; $f =~ s/[^a-zA-Z0-9_\ ]/_/g; $f };
306
471
        $c->SaveAs("$diagram_output_dir/$file.png");
307
472
    }
308
473
}
309
474
 
310
475
sub cmpthese_to_sanity {
311
 
    my $res = shift;
 
476
    my $res  = shift;
312
477
    my @rows = map {
313
478
        my $rate = $_->[1];
314
 
        if (not $rate =~ s/\s*\/\s*s$//) {
315
 
            $rate = 1/$rate;
 
479
        if ( not $rate =~ s/\s*\/\s*s$// ) {
 
480
            $rate = 1 / $rate;
316
481
        }
317
 
        [$_->[0], $rate]
318
 
    } grep {defined $_->[0] and $_->[0] =~ /\S/} @$res;
 
482
        [ $_->[0], $rate ]
 
483
    } grep { defined $_->[0] and $_->[0] =~ /\S/ } @$res;
319
484
    return \@rows;
320
485
}
321
 
 
 
486
print "\n";