Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep memory low when using a hierarchical object structure

Tags:

object

php

memory

I have a simple object thing that is able to have children of the same type.

This object has a toHTML method, which does something like:

$html  = '<div>' . $this->name . '</div>';
$html .= '<ul>';

foreach($this->children as $child)
  $html .= '<li>' . $child->toHTML() . '</li>';

$html .= '</ul>';

return $html;

The problem is that when the object is complex, like lots of children with children with children etc, memory usage skyrockets.

If I simply print_r the multidimensional array that feeds this object I get like 1 MB memory usage, but after I convert the array to my object and do print $root->toHtml() it takes 10 MB !!

How can I fix this?

====================================

Made a simple class that is similar to my real code (but smaller):

class obj{
  protected $name;
  protected $children = array();    
  public function __construct($name){
    $this->name = $name;
  }
  public static function build($name, $array = array()){
    $obj = new self($name);
    if(is_array($array)){
      foreach($array as $k => $v)
        $obj->addChild(self::build($k, $v));
    }  
    return $obj;
  }
  public function addChild(self $child){
    $this->children[] = $child;
  }
  public function toHTML(){
    $html  = '<div>' . $this->name . '</div>';
    $html .= '<ul>';
    foreach($this->children as $child)
      $html .= '<li>' . $child->toHTML() . '</li>';
    $html .= '</ul>';

    return $html;    
  }
}

And tests:

$big = array_fill(0, 500, true);
$big[5] = array_fill(0, 200, $big);

print_r($big);
// memory_get_peak_usage() shows 0.61 MB

$root = obj::build('root', $big);
// memory_get_peak_usage() shows 18.5 MB wtf lol

print $root->toHTML();
// memory_get_peak_usage() shows 24.6 MB
like image 446
Alex Avatar asked Jun 22 '13 16:06

Alex


People also ask

Which storage unit is lowest in memory hierarchy?

Most modern computer systems use a hard drive made of magnetic or solid-state storage as the lowest level in the memory hierarchy (see Figure 8.4).

How do hierarchies help memory?

The hierarchies' theory contends that long-term memory is organized through a hierarchical arrangements of concepts. Concepts may represent physical objects, events, attributes, or abstractions. These concepts are arranged from general to more specific classes. Also, these concepts can be simple or complex.

What are the levels of memory hierarchy?

The computer memory can be divided into 5 major hierarchies that are based on use as well as speed. A processor can easily move from any one level to some other on the basis of its requirements. These five hierarchies in a system's memory are register, cache memory, main memory, magnetic disc, and magnetic tape.

Is memory structure hierarchical?

The memory in a computer can be divided into five hierarchies based on the speed as well as use. The processor can move from one level to another based on its requirements. The five hierarchies in the memory are registers, cache, main memory, magnetic discs, and magnetic tapes.


1 Answers

The problem is that you're buffering all the data in memory, which you don't actually need to do, as you're just outputting the data, rather than actually processing it.

Rather than buffering everything in memory, if all you want to do is output it you should just output it to wherever it's going to:

public function toHTMLOutput($outputStream){
    fwrite($outputStream, '<div>' . $this->name . '</div>';
    fwrite($outputStream, '<ul>');

    foreach($this->children as $child){
      fwrite($outputStream, '<li>');
      $child->toHTMLOutput($outputStream);
      fwrite($outputStream, '</li>');}
    } 

    fwrite($outputStream, '</ul>');
}

$stdout = fopen('php://stdout', 'w');
print $root->toHTMLOutput($stdout);

or if you want to save the output to a file

$stdout = fopen('htmloutput.html', 'w');
print $root->toHTMLOutput($stdout);

Obviously I've only implemented it for the toHTML() function but the same principle should be done for the build function, which could lead to you skipping a separate toHTML function at all.

like image 117
Danack Avatar answered Oct 31 '22 07:10

Danack