Выполняю код
<?php
$arr = file('arr.txt');
$sum = 0;
foreach ($arr as $key => $value) {
$sum = array_sum(array_slice($arr,$key,30));
if($sum > 50) {
echo $key . ' ' . $sum . "<br>";
}
}
?>
То есть, поясняю:
Суммирую по порядку диапазоны:
Сумма значений с 0 по 30
Сумма значений с 1 по 31
Сумма значений с 2 по 32
Сумма значений с 3 по 33
Сумма значений с 4 по 34
..
И так до конца.
Получаю ошибку:
Fatal error: Maximum execution time of 180 seconds exceeded in E:\OSPanel\domains\arr\index.php on line 6
Файл arr.txt - это 200к целых чисел (0-100 примерно)
можно оптимизировать, ускорить функцию? Желательно без усложнений кода - итак с головы выпадает всё. если нельзя - как дать время на выполнение?
В общем говоря, при наличии достаточно большого файла, каким бы оптимальным ни был алгоритм, вы все равно будете упираться в таймлимит, Для заведомо больших задач его отключают.
Давайте посмотрим, что и как влияет на производительность. Я сгенерировал массив из 200к значений и записал его в файл. На момент конца генерации объем использованной памяти (memory_get_usage()
) составил 29 Мбайт.
Далее я отключил тайм лимит (set_time_limit(0)
) и запустил ваш скрипт, дабы проверить, сколько же он будет выполняться, и завершился тон через 770 секунд.
Предполагаем, что основная причина долгой обработки в том, что 200к раз выполняется slice (долгий не сам по себе слайс, а вероятно то, что менеджер памяти постоянно что-то выделяет, а коллектор уничтожает). Если заменить array_sum(array_slice( ... ))
на функцию, считающую сумму элементов вручную
$rangeSum = function($data, $s) use ($count){
$sum = 0;
$end = min($s+30, $count);
while($s < $end){
$sum += $data[$s++];
}
return $sum;
};
время работы - 1.4 секунды.
Следующий вариант - посчитать сумму первых 30 элементов. А дальше двигаться по массиву. Вычесть первый, добавить следующий:
$i = 0;
while($i < 30) $sum += $arr[$i++];
$x = $sum > 50 ? 1 : 0;
for($i = 30; $i < $count; $i++){<-->
$sum += -$arr[$i-30] + $arr[$i];
if($sum > 50) $x++;
}
Тут я немного пренебрег концом массива, и фактически последние 30 сумм не считает, но результат - 0.25 сек.
Есть еще вариант - читать файл построчно. Но т.к. вам потребуется хранить текущие 30 элементов в массиве и каждый раз делать shift/push (чтобы хранить этот -30 элемент), то его производительность будет ниже ~0.35сек, зато вы всегда храните только 30 значений, а не 200тыс, поэтому потребление памяти будет минимально.
while( ($v = fgets($f)) !== false){
$m = array_shift($values);
$sum += -$m + $v;
$values[] = $v;
if($sum > 50) $x++;
}
предварительно мы тут уже считали первые 30 строк и просуммировали.
зы: весь приведенный код вырван из контекста и не полон, просто для передачи смысла
Ну, если ничего не перепутал, то можно так -
<?php
$arr = file('arr.txt');
$sum = array_sum(array_slice($arr,0,30));
for($i = 1; $i<count($arr); $i++) {
if($sum > 50) {
echo ($i-1) . ' ' . $sum . "<br>";
}
$sum = $sum + $arr[$i] - $arr[$i-1] ;
}
?>
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
мой вопрос теоретическийВеб-приложение будет работать только с Word файлами (буду делать в учебных для меня целях СЭД) и загрузить-то с проверкой...
Всем привет! Не получается сделать отправку писем на сайте через AJAXНажимаю на кнопку отправить и ничего не происходит
Хотел бы поинтересоваться, как преобразовать объект, получаемый от АПИ ТелеграммаНиже моя попытка: