Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the reference count of an object in PHP?

Tags:

php

I realize the knee-jerk response to this question is that "you dont.", but hear me out.

Basically I am running on an active-record system on a SQL, and in order to prevent duplicate objects for the same database row I keep an 'array' in the factory with each currently loaded object (using an autoincrement 'id' as the key).

The problem is that when I try to process 90,000+ rows through this system on the odd occasion, PHP hits memory issues. This would very easily be solved by running a garbage collect every few hundred rows, but unfortunately since the factory stores a copy of each object - PHP's garbage collection won't free any of these nodes.

The only solution I can think of, is to check if the reference count of the objects stored in the factory is equal to one (i.e. nothing is referencing that class), and if so free them. This would solve my issue, however PHP doesn't have a reference count method? (besides debug_zval_dump, but thats barely usable).

like image 216
Josh Avatar asked Sep 21 '10 21:09

Josh


People also ask

How do you count elements in an object in PHP?

The count() function is used to count the elements of an array or the properties of an object. Note: For objects, if you have SPL installed, you can hook into count() by implementing interface Countable. The interface has exactly one method, Countable::count(), which returns the return value for the count() function.

How does count () work in PHP?

PHP count() function is an in-built function available in PHP, which counts and returns the number of elements in an array. It also counts the number of properties in an object. The count() function may return 0 for the variable, which has been declared with an empty array or for the variable which is not set.

Does PHP pass objects by reference?

In PHP, objects are passed by references by default. Here, reference is an alias, which allows two different variables to write to the same value. An object variable doesn't contain the object itself as value. It only contains an object identifier which allows using which the actual object is found.

How do I find the length of an array of objects in PHP?

The sizeof() function returns the number of elements in an array. The sizeof() function is an alias of the count() function.


1 Answers

Sean's debug_zval_dump function looks like it will do the job of telling you the refcount, but really, the refcount doesn't help you in the long run.

You should consider using a bounded array to act as a cache; something like this:

<?php
class object_cache {
   var $objs = array();
   var $max_objs = 1024; // adjust to fit your use case

   function add($obj) {
      $key = $obj->getKey();
      // remove it from its old position
      unset($this->objs[$key]);
      // If the cache is full, retire the eldest from the front
      if (count($this->objs) > $this->max_objs) {
         $dead = array_shift($this->objs);
         // commit any pending changes to db/disk
         $dead->flushToStorage();
      }
      // (re-)add this item to the end
      $this->objs[$key] = $obj;
   }

   function get($key) {
      if (isset($this->objs[$key])) {
          $obj = $this->objs[$key];
          // promote to most-recently-used
          unset($this->objs[$key]);
          $this->objs[$key] = $obj;
          return $obj;
      }
      // Not cached; go and get it
      $obj = $this->loadFromStorage($key);
      if ($obj) {
          $this->objs[$key] = $obj;
      }
      return $obj;
   }
}

Here, getKey() returns some unique id for the object that you want to store. This relies on the fact that PHP remembers the order of insertion into its hash tables; each time you add a new element, it is logically appended to the array.

The get() function makes sure that the objects you access are kept at the end of the array, so the front of the array is going to be least recently used element, and this is the one that we want to dispose of when we decide that space is low; array_shift() does this for us.

This approach is also known as a most-recently-used, or MRU cache, because it caches the most recently used items. The idea is that you are more likely to access the items that you have accessed most recently, so you keep them around.

What you get here is the ability to control the maximum number of objects that you keep around, and you don't have to poke around at the php implementation details that are deliberately difficult to access.

like image 137
Wez Furlong Avatar answered Sep 27 '22 15:09

Wez Furlong