2011-04-30 120 views
1

该代码在0.8秒内执行,占用我机器上22Mb的内存。代码耗时过长,内存占用量大

$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); 
    } 
    } 

什么可以做,以加快步伐,但更重要的是降低了内存占用它吃在任何给定的时间。

+0

你可以预填充的颜色随机列表,并从这些颜色中进行选择,而不是每次创建一个新实例。虽然,我不确定php的内存分配和收集是如何工作的。 – 2011-04-30 16:02:54

+0

随机颜色在这里不是问题,这只是一些代码来填补阵列与问题的目的。问题在于迭代和数组占用的内存。答案中不需要覆盖颜色托盘。 – 2011-04-30 16:09:23

+0

如果更改'$ x'和'$ y',内存使用情况如何改变? – Davidann 2011-04-30 16:13:59

回答

2

试试下面的代码(从http://php.net/manual/en/function.imagecolorallocate.php),而不是你直接的颜色分配:

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; 
} 

另外,尽量使函数调用1行:

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

拨弄硬编码,值1000 ,并了解它如何改变内存使用情况。

+0

这会更慢(并且不等价),但它会消耗更少的内存。 – 2011-04-30 17:22:28

+1

@Alix,我想这是值得一试的,因为它可能只对速度稍有影响,但会减少内存消耗的一个更大的因素,尽管OP尚未评论,所以这只是猜测......尽管这不是等价的,尽管如果保存的内存很大,则可能值得丢失调色板大小。 – davin 2011-04-30 17:40:16

+0

的确,我误解了你的代码。这几乎是我的答案,只是它不需要(另一个)巨大的数组+1。 – 2011-04-30 19:26:58

3

您的函数总共进行了25万次迭代,这总是要做很多PHP脚本。

但是,有些事情可以做。

首先,mt_rand()比rand()快,用它代替。其次,如果在内部循环中使用循环展开,则可能会提高一些速度。我不确定PHP在实际中的效果如何,但是您可以对其进行基准测试,看看它的效果如何。

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); 
} 

但是,因为你正在构建的数据结构基本上是一个大的它们都将减少内存占用。

也许你正从错误的方向看待这个问题?你应该真正问自己的第一件事是,你是否真的需要这么庞大的数据结构来完成你想要做的事情?循环展开和使用更快的随机数生成器会让你的性能有所提升,但最终最快的代码是你不写的代码。任何给定算法的性能的最大因素是总是选择算法。如果你重新考虑你想要做什么,你可能会想出一些对计算机内存和处理资源的浪费少得多的东西。

+0

首先,我认为你的意思是循环增量是'$ j + = 10'。其次,不是用一个丑陋的硬编码(本身可能会降低性能)展开,它可能具有相同的运行时间,只有一个变量具有某些模数算术并将循环体保留为原来的4行。我怀疑这两种技术在一起会改变运行时间,尽管... – davin 2011-04-30 16:16:54

+2

每个PHP变量最少需要68个字节。由于您使用的是二维数组,因此您只是为了存储数组而导致“x * y * 68”字节(在您的情况下为500 * 500 * 68 = 17 MB)的内存消耗。直接操作位图会提高内存效率。 – jmz 2011-04-30 16:37:01

+1

似乎这增加了时间和内存使用是相同的,顺便说一句:代码已经优化,因为v1.0。意图是创建更大的图像,并会吃掉大量的内存,所以...寻求其他选择 – 2011-04-30 16:40:01

1

从我所知道的看来,imagecreatetruecolor可能是成为记忆猪的最可能的罪魁祸首。

您可以使用另一种方法,如imagecreate来创建图像吗?

+0

在阵列中分配250.000种颜色*可能*也会吃一点*小*内存... – 2011-04-30 17:24:21

1

我可以在代码中看到的唯一的改善是不分配相同的颜色不止一次(在你的情况3.203.328颜色500.000像素),这应该降低内存占用:

$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)]; 
    } 
} 

而且,如果你不需要真正的彩色图像ImageCreate()应该少一个内存猪。


我不知道你想什么存档,但也许you would be better with mt_rand()代替:

rand() mt_rand()