Функция PHP выполняет очень медленно на большой кусок данных и вывода. Как сделать это быстро, не меняя настройки php.ini или max_execution_server - PullRequest
0 голосов
/ 16 января 2019

У меня большой индексированный массив, где элемент массива может варьироваться от 1 до 2 * 10 ^ 5, а функция php выходит за пределы Max_execution_timeout. как сделать это быстро или заставить работать должным образом, не внося изменений в любой другой документ напрямую (если есть способ увеличить время выполнения в пределах функции). функция работает правильно с небольшим фрагментом данных.

вот прикрепленный файл https://drive.google.com/file/d/1egyzLQWV69IDKjbMzS1ZG3e-bPy3qjjM/view?usp=sharing

<?php
 // $count = array of element

function activityNotifications($expenditure, $d) {

    $size = sizeof($expenditure);
    $count = 0 ;
    for($i=0;$i<$size-$d;$i++){
        $median = array();
        for($k=0;$k<$d;$k++){ 
            $median[$k] = $expenditure[$i+$k];
        }
        sort($median);

        if($d%2 == 1){
            $middle = $median[floor($d/2)];
        } else if($d%2 == 0){ 
            $value = $d/2;
            $middle = $median[$value] + $median[$value-1];
            $middle = $middle/2;
        }
        $value = $middle*2;

        if($value<=$expenditure[$d+$i]){
            $count++;
        }
    }
    return $count;
}

echo activityNotifications($count2,$d);

?>

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Некоторые предложения по улучшению производительности:

Вместо:

for($k=0;$k<$d;$k++){ 
    $median[$k] = $expenditure[$i+$k];
}

Использование:

$median = array_slice($expenditure, $i, $d);

В общем случае функции массива будут выполняться быстрее, чем циклы.

Другая отличная идея - снизить стоимость функции sort(). Вы можете сделать это, поддерживая массив $median, в основном отсортированный по всему. Таким образом, вместо того, чтобы брать срез каждый раз, вы нажимаете одно значение и извлекаете одно значение. Что-то вроде:

$median[$i+$d] = $expenditure[$i+$d]; // append a value
unset($median[$i]); // remove a value

Затем используйте asort, чтобы отсортировать и поддерживать ассоциации ключей:

asort($median);

По сути, $median всегда будет окном в $expenditure размера d и поддерживает ключевые ассоциации. Вы можете инициализировать $median с самого начала, сначала взяв срез, используя: $median = array_slice($expenditure, $i, $d); вне цикла.

Очень грубо (сам не проверял):

function activityNotifications($expenditure, $d) {

    $size = sizeof($expenditure);
    $count = 0 ;
    $median = array_slice($expenditure, 0, $d, TRUE); // initial slice with keys
    for($i=$d;$i<$size;$i++){

        $median[$i]=$expenditure[$i];
        unset($median[$i-$d]);
        asort($median);

        $median_values = array_values($median);
        if($d%2 == 1){
            $middle = $median_values[floor($d/2)];
        } else if($d%2 == 0){ 
            $value = $d/2;
            $middle = $median_values[$value] + $median_values[$value-1];
            $middle = $middle/2;
        }
        $value = $middle*2;

        if($value<=$expenditure[$d+$i]){
            $count++;
        }
    }
    return $count;
}

Обратите внимание, что приведенный выше код не будет работать напрямую, поскольку при извлечении значения средней точки ключи не будут в порядке. Таким образом, вам может понадобиться сначала использовать array_values (я добавил это выше).

0 голосов
/ 16 января 2019

Так как $d действует как константа в этой функции, общее улучшение заключается в извлечении фиксированных данных вне цикла.

Важная часть, которую я считаю, - объявить $median один раз и использовать ее повторно, это может уменьшить некоторые издержки GC.

function activityNotifications($expenditure, $d)
{
    $size = sizeof($expenditure);
    $count = 0 ;
    $median = array_fill(0, $d, 0); #create an array with predefined size
    $d_divide_by_2 = $d/2;
    $d_divide_by_2_int = floot($d_divide_by_2);

    if($d%2 == 1)
    {
        for($i=0;$i<$size-$d;$i++)
        {
            for($k=0;$k<$d;$k++)
            { 
                $median[$k] = $expenditure[$i+$k];
            }
            sort($median);

            $value = $median[$d_divide_by_2_int]*2;

            if($value<=$expenditure[$d+$i]){
                $count++;
            }
        }
    }
    else
    {
        for($i=0;$i<$size-$d;$i++)
        {
            for($k=0;$k<$d;$k++)
            { 
                $median[$k] = $expenditure[$i+$k];
            }
            sort($median);

            $value = $median[$d_divide_by_2] + $median[$d_divide_by_2-1];

            if($value<=$expenditure[$d+$i]){
                $count++;
            }
        }
    }

    return $count;
}
...