Код занимает слишком много времени для обработки и занимает много памяти - PullRequest
1 голос
/ 30 апреля 2011

Этот код выполняется за 0,8 секунды и занимает 22 МБ памяти на моем компьютере.

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

Что можно сделать, чтобы ускорить его, но, что более важно, уменьшить объем памяти, который он потребляет в любой момент времени.

Ответы [ 4 ]

3 голосов
/ 30 апреля 2011

Ваша функция выполняет в общей сложности четверть миллиона итераций, это всегда будет довольно много 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);
}

Однако ни один из них не уменьшит объем памяти, поскольку создаваемая вами структура данных является принципиально большой.

Может быть, вы смотрите на эту проблему с неправильной стороны?Первое, о чем вы действительно должны спросить себя здесь: действительно ли вам нужна такая огромная структура данных, чтобы выполнить то, что вы хотите сделать?Развертывание цикла и использование более быстрого генератора случайных чисел принесут вам некоторое повышение производительности, но в итоге самый быстрый код, который вы можете получить, это код, который вы не пишете.Самым большим фактором в производительности любого данного алгоритма всегда является выбор алгоритма.Если вы переосмыслите, что именно вы хотите сделать, вы можете придумать что-то, что будет намного менее затратным из памяти вашего компьютера и ресурсов обработки.

2 голосов
/ 30 апреля 2011

Попробуйте следующий код (из 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 и посмотрите, как оно меняет использование памяти.

1 голос
/ 30 апреля 2011

Единственное улучшение, которое я вижу в вашем коде, - это не выделение одного и того же цвета более одного раза (в вашем случае 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() должно быть меньше памяти.


Я не уверен, что вы пытаетесь заархивировать, но, возможно, вам лучше использовать mt_rand() вместо:

rand() mt_rand()

1 голос
/ 30 апреля 2011

Судя по тому, что я могу сказать, кажется, что imagecreatetruecolor , вероятно, является наиболее вероятным виновником того, что он является боровом памяти.

Не могли бы вы использовать другой метод, например imagecreate, для создания изображения вместо?

...