http://www.perlmonks.org?node_id=1021294

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

Hi Monks,

I have a strange issue and I am not sure if anyone has seen anything similar before. I have a web app running on windows and I am porting it to mod_perl to give it a massive performance boost.

I am all but done, however I am hitting an issue with the JSON module when the service is put under load and it is puzzling me something stupid.

I make quite extensive use of JSON::true and JSON::false in my application, but it seems that under load in mod_perl it can in some cases return null instead of true or false.

I have run a simple script which proves the point I am having. This just creates a simple data structure including a JSON::true and then encodes it and prints the results.

In CGI mode this works fine and in mod_perl it works *most* of the time. When placed under load with apache bench the result of success some times comes out as null when it should say true. This breaks my application and is the only thing that is stopping me going forward with mod_perl. This is the test script I use;

use JSON; my $json = JSON->new(); $json->convert_blessed(1); $json->allow_blessed(1); my $data = { success => JSON::true, test=>'Hello' }; print "Content-type: text/html\n\n"; print $json->encode($data);

This prints out the following all of the time in cgi mode but only some of the time in mod_perl. {"success":true,"test":"Hello"}

An example from Apache Bench shows the following when I have 50 concurrent users requesting 1000 pages.

LOG: header received: HTTP/1.1 200 Date: Fri, 01 Mar 2013 16:09:11 Server: Apache/2.2.23 (Win32) mod_auth_sspi/1.0.5 mod_perl/2.0.7 Perl/ Connection: Content-Type: text/html {"success":true,"test":"Hello"} LOG: header received: HTTP/1.1 200 OK Date: Fri, 01 Mar 2013 16:09:11 GMT Server: Apache/2.2.23 (Win32) mod_auth_sspi/1.0.5 mod_perl/2.0.7 Perl/ +v5.16.1 Connection: close Content-Type: text/html {"success":null,"test":"Hello"} LOG: header received: HTTP/1.1 200 OK Date: Fri, 01 Mar 2013 16:09:11 GMT Server: Apache/2.2.23 (Win32) mod_auth_sspi/1.0.5 mod_perl/2.0.7 Perl/ +v5.16.1 Connection: close Content-Type: text/html {"success":null,"test":"Hello"} LOG: header received: HTTP/1.1 200 OK Date: Fri, 01 Mar 2013 16:09:11 GMT Server: Apache/2.2.23 (Win32) mod_auth_sspi/1.0.5 mod_perl/2.0.7 Perl/ +v5.16.1 Connection: close Content-Type: text/html {"success":null,"test":"Hello"} LOG: header received: HTTP/1.1 200 OK Date: Fri, 01 Mar 2013 16:09:11 GMT Server: Apache/2.2.23 (Win32) mod_auth_sspi/1.0.5 mod_perl/2.0.7 Perl/ +v5.16.1 Connection: close Content-Type: text/html {"success":true,"test":"Hello"} LOG: header received: HTTP/1.1 200 OK Date: Fri, 01 Mar 2013 16:09:11 GMT Server: Apache/2.2.23 (Win32) mod_auth_sspi/1.0.5 mod_perl/2.0.7 Perl/ +v5.16.1 Connection: close Content-Type: text/html {"success":true,"test":"Hello"}

As you can see some times the success value comes back as null and I have no idea why? I can only assume that there is an issue with JSON::XS in one of the threads within apache.

If I remove JSON::XS and use JSON::PP then the issue goes away and all of the bool values come back as expected however there is the big performance hit here so I do not see that as a solution.

I am currently running Apache 2.2.23 with mod_perl 2.0.7 and running ActivePerl v5.16.1. The JSON::XS module installed is the latest which is 2.23 and the JSON core is 2.53 which came with ActivePerl.

Has any one seen this behavior in the past or have any suggestions as to what could be causing this issue?

Many Thanks,
Alistair

Replies are listed 'Best First'.
Re: JSON::XS Bool issue in mod_perl (XS--)
by tye (Sage) on Mar 01, 2013 at 19:06 UTC

    XS code is almost always buggy (and the bugs are a huge pain in being very "weird" and tending to be huge consumers of a developer's time). JSON::PP uses an algorithm that is efficient in C but is especially slow in Perl. You might have the best luck with some other non-XS implementation. Try JSON::Tiny or some other JSON module.

    It should be fairly easy to efficiently parse JSON in Perl, but there are also some typical traps to avoid so many JSON parsing approaches in Perl will be less efficient, so let us know how efficient are the modules that you try.

    It is too bad that the author of JSON::XS didn't know that one should thoroughly avoid manipulating Perl data structures from XS code. Creating Perl data structures in XS code is an even worse idea. But this is a case where it actually would be quite hard to do the parsing in XS while creating the Perl data structures in Perl.

    But I (wrongly) recall looking at the code and thinking that the creation of the 'true' and 'false' values should've been done in Perl. I guess my instincts were right about that, even though we haven't noticed this problem (also common for XS bugs).

    - tye        

      But I recall looking at the code and thinking that the creation of the 'true' and 'false' values should've been done in Perl.

      JSON::XS does create true and false in Perl.

      our $true = do { bless \(my $dummy = 1), "JSON::XS::Boolean" }; our $false = do { bless \(my $dummy = 0), "JSON::XS::Boolean" }; sub true() { $true } sub false() { $false }

      So many the problem can be solved by upgrading the module the OP has installed? In any case, the docs say "This module is not guaranteed to be thread safe".

      Thanks Davido and Tye for your replies. I will have a look at JSON::Tiny and see if that shows the same issue.

      I have just seen in the JSON documentation the following commend;

      This module is not guaranteed to be thread safe and there are no plans to change this until Perl gets thread support (as opposed to the horribly slow so-called "threads" which are simply slow and bloated process simulations - use fork, it's much faster, cheaper, better).

      I guess that mod_perl comes under threads due to the way that the module is reused over and over so I am not sure it's worth reporting as a bug.

      if worst comes to worst I guess I could just use PP for now however some of the objects I need to encode can get quite big and will be slow but I am not sure if that will be noticeable due to the massive performance gains I get from mod_perl.

      I will have to run some benchmarks next week to see which method will be the easiest. Thankfully all of the JSON code in my application is centralised so changing the JSON encoder is not a massive issue if XS will not work

        mod_perl doesn't have to use threads (it usually doesn't, in my experience -- but "ActivePerl" might imply MS Windows which might mean Apache is more likely to be configured to use threads). Even if mod_perl uses threads, that doesn't need to mean that it lets its instances of Perl bounce between threads. So it doesn't need to mean any Perl stuff has to be thread safe.

        But I find that people are often confused about these issues (like insisting that one needs to build a threaded Perl to embed it into a threaded application, even when I know the application doesn't share Perl instances between threads). So maybe mod_perl (stupidly) shares Perl instances between threads and this causes your problem.

        - tye        

Re: JSON::XS Bool issue in mod_perl (try \0 \1)
by Anonymous Monk on Mar 01, 2013 at 22:54 UTC

    You could try using \0 and \1 for false and true, and see how that works out

    If you're sending a bug report to the author, please send it to his email , and not rt://JSON-XS