开发者

Code take too long to process and has a big memory footprint

This code executes in 0.8seconds and takes up 22Mb of memory on my machine.

   $x=500;
   $y=500;

   $im = imagecreatetruecolor($x,$y);
   $ia=array();
   for ($i = 0; $i < $x; $i++) {
    for ($j = 0; $j < $y; $j++) {
        $r=rand(0,96);
        $g=rand(0,128);
        $b=rand(0,255);
        $ia[$i][$j]=ImageColorAllocate($im,$r,$g,$b);
    }
   }

What can be done to speed开发者_C百科 it up, but more importantly lower the memory footprint it eats at any given time.


Your function is doing a quarter of a million iterations total, that's always going to be rather a lot of a PHP script to be doing.

However, there are things you can do.

First, mt_rand() is faster than rand(), use that instead.

Secondly, you could possibly get some speed increase if you use loop unrolling on the inner loop. I'm not sure how effective that would actually be in PHP but you can benchmark it to see how effective it is.

for ($j=0;$j<$y;$j+=10) {
    $r=mt_rand(0,96);
    $g=mt_rand(0,128);
    $b=mt_rand(0,255);
    $ia[$i][$j]=ImageColorAllocate($im,$r,$g,$b);
    $r=mt_rand(0,96);
    $g=mt_rand(0,128);
    $b=mt_rand(0,255);
    $ia[$i][$j + 1]=ImageColorAllocate($im,$r,$g,$b);
    $r=mt_rand(0,96);
    $g=mt_rand(0,128);
    $b=mt_rand(0,255);
    $ia[$i][$j + 2]=ImageColorAllocate($im,$r,$g,$b);
    $r=mt_rand(0,96);
    $g=mt_rand(0,128);
    $b=mt_rand(0,255);
    $ia[$i][$j + 3]=ImageColorAllocate($im,$r,$g,$b);
    $r=mt_rand(0,96);
    $g=mt_rand(0,128);
    $b=mt_rand(0,255);
    $ia[$i][$j + 4]=ImageColorAllocate($im,$r,$g,$b);
    $r=mt_rand(0,96);
    $g=mt_rand(0,128);
    $b=mt_rand(0,255);
    $ia[$i][$j + 5]=ImageColorAllocate($im,$r,$g,$b);
    $r=mt_rand(0,96);
    $g=mt_rand(0,128);
    $b=mt_rand(0,255);
    $ia[$i][$j + 6]=ImageColorAllocate($im,$r,$g,$b);
    $r=mt_rand(0,96);
    $g=mt_rand(0,128);
    $b=mt_rand(0,255);
    $ia[$i][$j + 7]=ImageColorAllocate($im,$r,$g,$b);
    $r=mt_rand(0,96);
    $g=mt_rand(0,128);
    $b=mt_rand(0,255);
    $ia[$i][$j + 8]=ImageColorAllocate($im,$r,$g,$b);
    $r=mt_rand(0,96);
    $g=mt_rand(0,128);
    $b=mt_rand(0,255);
    $ia[$i][$j + 9]=ImageColorAllocate($im,$r,$g,$b);
}

However, neither of these will reduce the memory footprint because the data structure you are building is fundamentally a big one.

Maybe you are looking at this problem from the wrong direction? The first thing you should really be asking yourself here is, do you really need such a huge data structure to accomplish what it is you want to do? Loop unrolling and using a faster random number generator will get you some performance boost, but in the end the fastest code you can have is code you don't write. The biggest factor in performance of any given algorithm is always choice of algorithm. If you rethink what it is that you want to do, you might come up with something that is a lot less wasteful of your computer's memory and processing resources.


Try the following code (from http://php.net/manual/en/function.imagecolorallocate.php) instead of your direct colour assignment:

function createcolor($pic,$c1,$c2,$c3) {
   $color = imagecolorexact($pic, $c1, $c2, $c3);
   if($color==-1) {
      if(imagecolorstotal($pic)>=1000) {
         $color = imagecolorclosest($pic, $c1, $c2, $c3);
      } else {
         $color = imagecolorallocate($pic, $c1, $c2, $c3);
      }
   }
   return $color;
 }

Also, try making the function call in 1 line:

$ia[$i][$j] = createcolor($im, mt_rand(0,96), mt_rand(0,128), mt_rand(0,255));

Fiddle with the hardcoded value 1000, and see how it changes memory usage.


From what I can tell, it seems that imagecreatetruecolor is probably the most likely culprit for being the memory hog.

Could you use another method, like imagecreate, to create an image instead?


The only improvement I can see in your code is not allocating the same color more than once (in your case 3.203.328 colors for 500.000 pixels), which should reduce your memory footprint:

$x = 500;
$y = 500;

$image = ImageCreateTrueColor($x, $y);
$matrix = array();
$colors = array();

for ($i = 0; $i < $x; $i++)
{
    for ($j = 0; $j < $y; $j++)
    {
        $rand = array(rand(0, 96), rand(0, 128), rand(0, 255));

        if (isset($colors[implode('|', $rand)]) !== true)
        {
            $colors[implode('|', $rand)] = ImageColorAllocate($im, $rand[0], $rand[1], $rand[2]);
        }

        $ia[$i][$j] = $colors[implode('|', $rand)];
    }
}

Also, if you don't need a true color image ImageCreate() should be less of a memory hog.


I'm not sure what you're trying to archive but maybe you would be better with mt_rand() instead:

Code take too long to process and has a big memory footprint

Code take too long to process and has a big memory footprint

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜