Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Shouldn't JSON be faster?

by sflitman (Hermit)
on May 31, 2010 at 00:12 UTC ( [id://842313]=perlquestion: print w/replies, xml ) Need Help??

sflitman has asked for the wisdom of the Perl Monks concerning the following question:

I wrote the following benchmark to prove to myself that my JSON::XS installation was working well enough to replace my homebrew config file handling code. This is on a quad-core Xeon 3 GHz server running Fedora 7. The config format I use is very simple:
key: value key:: multiline value (blank line)
JSON is obviously more involved, but could instantiate key values as hashes or arrays where I have to subsequently split strings to make a hash or array which happens a lot with my production codebase. Here's the benchmark script:
#!/usr/bin/perl # jsonbench - which is faster, load_config or JSON::XS use strict; use warnings; use vars qw/%cfg $fileConfig $fileJson/; use Benchmark qw/:all/; use Fcntl qw/LOCK_EX LOCK_UN/; use JSON; print JSON->backend->is_xs ? 'JSON::XS' : 'JSON:PP',"\n"; $fileConfig='local.dat'; $fileJson='local.json'; unless (-r $fileConfig) { # create original config file for my $n1 ('a'..'z') { for my $n2 ('a'..'z') { for my $n3 ('a'..'z') { $cfg{"$n1$n2$n3"}="Test 1 2 3"; } } } save_config(); } unless (-r $fileJson) { # create json file from fileConfig load_config(); my $json=JSON->new->encode(\%cfg); die "No data" unless $json; open(FILE,'>',$fileJson) || die "$fileJson: $!"; print FILE $json; close FILE; } cmpthese( 1000, { 'load_json' => \&load_json, 'load_config' => \&load_config }); exit; sub load_json { %cfg=(); open(FILE,$fileJson) || die("Can't open $fileJson: $!"); undef $/; my $json=<FILE>; close FILE; %cfg=%{JSON->new->decode($json)}; } sub load_config { %cfg=(); open(CFGFILE,$fileConfig) || die("Can't open $fileConfig: $!"); flock(CFGFILE,LOCK_EX); my $key; while (<CFGFILE>) { chop; if (!$_ and $key) { # end of multiline definition $key=''; } elsif (/^([^:]+)::\s+(.*)$/) { # multiline definition $key=$1; $cfg{$key}=$2; } elsif ($key) { $cfg{$key}.="\n$_"; } elsif (/^([^:]+):\s+(.*)$/) { # single-line definition $cfg{$1}=$2; } } flock(CFGFILE,LOCK_UN); close CFGFILE; } sub save_config { umask 0111; open(CFGFILE,'>',$fileConfig) || die("Couldn't write $fileConfig: $ +!"); flock(CFGFILE,LOCK_EX); print CFGFILE "# $fileConfig, last modified ".scalar(localtime)."\n +"; for my $key (keys %cfg) { if (index($cfg{$key},"\n")>-1) { print CFGFILE "$key\:: $cfg{$key}\n\n"; } else { print CFGFILE "$key: $cfg{$key}\n"; } } flock(CFGFILE,LOCK_UN); close CFGFILE; }
The results of 1000 runs:
JSON::XS Rate load_config load_json load_config 13.7/s -- -37% load_json 21.8/s 59% --
So, fellow Monks, why is load_json so unimpressively superior? Shouldn't it be freakin' blazing compared to my lame pure perl code? Note JSON::XS is definitely loaded and is being used. The generated files are only slightly bigger for JSON:
-rw-rw-rw- 1 sflitman sflitman 281268 2010-05-30 16:09 local.dat -rw-rw-rw- 1 sflitman sflitman 333945 2010-05-30 16:09 local.json
As always, all comments are welcome, I'm probably doing something stupid. Also, can anyone tell me how to load an existing hash with JSON rather than the hash assignment in load_json above?

SSF

Replies are listed 'Best First'.
Re: Shouldn't JSON be faster?
by jettero (Monsignor) on May 31, 2010 at 00:27 UTC
    Looks to me like most of what you're measuring is open() and flock(); Try the comparison again using strings in memory. Also, XS isn't necessarily faster. You're only going to notice huge speedups if the code you're doing in C has a *lot* to do before it hands it back to perl. If most of the code is handing things to perl, it may (probably not, but possibly) even slow it down compared to just doing things natively.

    You may notice ad hoc parsing of short strings is faster in native perl and JSON::XS is only faster for large-ish js inputs. I suspect JSON::XS is usually faster though. It really depends how much parsing your ad hoc format requires.

    -Paul

      Thanks, I'll try doing it without file I/O
      SSF
Re: Shouldn't JSON be faster?
by Your Mother (Archbishop) on May 31, 2010 at 00:30 UTC

    I think you're doing apples and oranges and most of the time is in the file stuff. You will get a decent boost if you drop the OO interface and copying the hash.

    # decode_json($json); Rate load_config load_json load_config 13.8/s -- -79% load_json 66.1/s 380% --

      That's interesting, I was able to show the same benefit. Why is OO interface slow?

      SSF

        OO uses methods instead of straight subs/functions and they (in the past at least) introduce an overhead of like 30%. OO is fantastic where appropriate but for stuff like this I think the functional interface is better.

        What are you talking about? load_json is faster than load_config, and load_json is the only OO code shown
Re: Shouldn't JSON be faster?
by Anonymous Monk on May 31, 2010 at 06:23 UTC
    more than twice as fast is unimpressive? and you're also getting free maintenance and a test suite

      BWAH! Support? on this module? Forget it. I'm a big fan of CPAN, and free support and good test suites are true for most modules, but this author is not willing to comply to the standards that perl requires (e.g. full ANSI-C89). If a reported bug is not to his liking, he just deletes it. All other bugs are rejected. He hates RT and insults people that use it.

      End-of-rant. But I seriously do not see this as support, and am very willing to trade speed for usefulness! I'm using JSON on a daily basis. No way I'm going to install JSON::XS.


      Enjoy, Have FUN! H.Merijn

        As an impartial observer reading your evidence; he is right and you are wrong.

        Expecting programmers to cater to the vagaries of every ancient C compiler that ever ran on any platform Perl has been ported to is quite ridiculous.

        You have the choice not to use his modules. You have the choice to upgrade to a compiler that complies with a more modern specification. His only choice is to ignore or delete your ridiculous demands of his source code.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        I went back and read all the stuff in that deleted "bug report." Marc was predictably/unnecessarily abusive, but he was right. You are wrong. If you really want C89 support, you could fork and make JSON::XS_C89, but you didn't, you chose to whine and cry and complain on perlmonks (utterly inexplicable). What is wrong with you?

        -Paul

      A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://842313]
Front-paged by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (4)
As of 2024-04-25 05:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found