23
votes

I'm using the JMS Serializer. And I found out that the performance is really bad when I use big data. I've the following object structure displayed as an array:

$jsonData = array(
    'message' => 'this is a nice message', 
    'data' => array(
        0 => array(
          'firstname' => 'achim',
          'lastname' => 'menzel' 
        )
    )
);

This is how I serialize the data:

$serializer = $this->get('serializer');
$encodedJson = $serializer->serialize($jsonData, 'json');

$response = new Response($encodedJson);
$response->headers->set('Content-Type', 'application/json');

Data can be a list of 1 till n objects. When I have more than 500 objects in data, the performance is very very slow (more then 5sec.). When i use json_encode() directly, it tooks not more then 1 second.

How can I improve the usage of JMS Serializer? I don't think that jms serializer cannot handle big data.

This is the main class which will be used for serializing:

class JsonData {

  public $success = false;
  public $message = '';
  public $data;
  public $responseCode = 200;
  public $contentType = 'application/json';
}

And currently this object is inside $data:

class GuestDTO {

  private $userid;
  private $firstname;
  private $lastname;
  private $birthday;
  private $picturemedium;
  private $picturelarge;
  private $gender;
  private $modifydate;
  private $entries = array(); 
}

And $entries is a list of objects from this class:

class GuestlistentryDTO extends AbstractGuestDTO{

  private $guestlistentryid;
  private $guestlistid;
  private $arrivedat;
  private $bouncername;
  private $rejectionreason;
  private $companioncount;
  private $companioncountcheckin;    
  private $winner;
  private $vip;  
}

Without any annotations because I prepared my dto's for using the data as I need.

3
Have you tried inspecting which parts of JMSSerializer are slowing down the whole thing with xhprof or xdebug and cachegrind/kcachegrind/webgrind? Do you have antything special included in your serialization with JMS serializer - like filtering values or virtual fields ? - Nicolai Fröhlich
I dont think you will ever be able to achieve the performance of the json_ecode/decode with the JMS serializer for a number of reasons. JMS serializer deals with Objects so inherently it will produce A LOT of garbage for the GC, while the native serializers do it in C on arrays which are very cheap in PHP. If performance is what you need doing serilization/deserialization in PHP WILL BE SLOW. I dont think theres anything that will come even close to the native encoder/decoder unfortunately. - Feras
I just ran into the same issue. Apparently it's not JMS Serializer who is to blame, but Symfony's Serializer component (JMS relies on it). Will investigate further and, if I find a solution, I will post it here. - Radu Murzea
@DimitryK Not really. We abandoned the idea of using JMS and therefore we didn't pursue the investigation further. Sorry for not providing a more helpful answer... - Radu Murzea
Another great option is Fractal fractal.thephpleague.com - softius

3 Answers

2
votes

Unfortunately this library is inherently pretty slow. There's a lot of recursion in there.

A couple of things you can do however is query cache everything using either Redis or Memcache. You can also be smart with your SQL queries, try to trim the fat. Only give the serializer the important data you need so it isn't trawling through lots of data that won't be getting used anyway.

1
votes

Are you using partial responses? your problem seems actually quite obvious. In my opinion your client should ask for a limited number of items and ask for more when necessary...

1
votes

I've hit the same issue too and the "best workaround" has been to create a cache for the generated json output in Redis and plug CRUD Doctrine events on specific entities to flush the cache.

Some help came from fine tuned mix of groups and inclusion/exclusion rules for referenced collections