Как решить проблему с Allowed memory size в плагине Worpress?
В одном плагине есть вкладка "Логи" при переходе в которую я получаю ошибку нехватки памяти, хотя там всего несколько строк и памяти выделено по максимуму. Как можно оптимизировать код, чтобы не потребляло много памяти?
Ошибка по строке:
$page_counter = 1; while( $total_pages > 0 ){ if( $page_counter === $page ){ $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page_counter, ) ) ) . '" class="wpwh-btn wpwh-btn--primary wpwh-btn--sm mr-1">' . $page_counter . '</a>'; } else { $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page_counter, ) ) ) . '" class="btn--secondary">' . $page_counter . '</a>'; } $page_counter++; } |
$page_counter = 1; while( $total_pages > 0 ){ if( $page_counter === $page ){ $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page_counter, ) ) ) . '" class="wpwh-btn wpwh-btn--primary wpwh-btn--sm mr-1">' . $page_counter . '</a>'; } else { $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page_counter, ) ) ) . '" class="btn--secondary">' . $page_counter . '</a>'; } $page_counter++; }
Полный код метода:
public function pagination( $args = array() ) { $per_page = isset( $args['per_page'] ) ? intval( $args['per_page'] ) : 10; $page = isset( $args['log_page'] ) ? intval( $args['log_page'] ) : 1; $page_counter = 1; $log_count = $this->get_log_count(); $total_pages = ceil( $log_count / $per_page ); $current_url = LOGPLUG()->helpers->get_current_url(false); if( $page > $total_pages ){ $page = $total_pages; } if( $page < 1 ){ $page = 1; } $pagination_links_out = array(); $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => 1, ) ) ) . '" class="btn--sm mr-1">' . LOGPLUG()->helpers->translate( '<<', 'logs' ) . '</a>'; if( $page <= 1 ){ $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => 1, ) ) ) . '" class="btn--sm mr-1">' . LOGPLUG()->helpers->translate( '<', 'logs' ) . '</a>'; } else { $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => ($page-1), ) ) ) . '" class="btn--sm mr-1">' . LOGPLUG()->helpers->translate( '<', 'logs' ) . '</a>'; } if( $total_pages > 3 ){ if( $page === 1 ){ $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => 1, ) ) ) . '" class="primary btn--sm mr-1">' . 1 . '</a>'; $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => 2, ) ) ) . '" class="secondary btn--sm mr-1">' . 2 . '</a>'; $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => 3, ) ) ) . '" class="secondary btn--sm mr-1">' . 3 . '</a>'; } elseif( $page >= $total_pages ){ $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page-2, ) ) ) . '" class="secondary btn--sm mr-1">' . ($page-2) . '</a>'; $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page-1, ) ) ) . '" class="secondary btn--sm mr-1">' . ($page-1) . '</a>'; $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page, ) ) ) . '" class="primary btn--sm mr-1">' . $page . '</a>'; } else { $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page-1, ) ) ) . '" class="secondary btn--sm mr-1">' . ($page-1) . '</a>'; $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page, ) ) ) . '" class="primary btn--sm mr-1">' . $page . '</a>'; $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page+1, ) ) ) . '" class="secondary btn--sm mr-1">' . ($page+1) . '</a>'; } } else { $page_counter = 1; while( $total_pages > 0 ){ if( $page_counter === $page ){ $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page_counter, ) ) ) . '" class="primary btn--sm mr-1">' . $page_counter . '</a>'; } else { $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page_counter, ) ) ) . '" class="secondary btn--sm mr-1">' . $page_counter . '</a>'; } $page_counter++; } } if( $page >= $total_pages ){ $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $total_pages, ) ) ) . '" class="btn--sm mr-1">' . LOGPLUG()->helpers->translate( '>', 'logs' ) . '</a>'; } else { $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => ($page+1), ) ) ) . '" class="btn--sm mr-1">' . LOGPLUG()->helpers->translate( '>', 'logs' ) . '</a>'; } $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $total_pages, ) ) ) . '" class="btn--sm mr-1">' . LOGPLUG()->helpers->translate( '>>', 'logs' ) . '</a>'; return implode( '', $pagination_links_out ); } |
public function pagination( $args = array() ) { $per_page = isset( $args['per_page'] ) ? intval( $args['per_page'] ) : 10; $page = isset( $args['log_page'] ) ? intval( $args['log_page'] ) : 1; $page_counter = 1; $log_count = $this->get_log_count(); $total_pages = ceil( $log_count / $per_page ); $current_url = LOGPLUG()->helpers->get_current_url(false); if( $page > $total_pages ){ $page = $total_pages; } if( $page < 1 ){ $page = 1; } $pagination_links_out = array(); $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => 1, ) ) ) . '" class="btn--sm mr-1">' . LOGPLUG()->helpers->translate( '<<', 'logs' ) . '</a>'; if( $page <= 1 ){ $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => 1, ) ) ) . '" class="btn--sm mr-1">' . LOGPLUG()->helpers->translate( '<', 'logs' ) . '</a>'; } else { $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => ($page-1), ) ) ) . '" class="btn--sm mr-1">' . LOGPLUG()->helpers->translate( '<', 'logs' ) . '</a>'; } if( $total_pages > 3 ){ if( $page === 1 ){ $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => 1, ) ) ) . '" class="primary btn--sm mr-1">' . 1 . '</a>'; $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => 2, ) ) ) . '" class="secondary btn--sm mr-1">' . 2 . '</a>'; $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => 3, ) ) ) . '" class="secondary btn--sm mr-1">' . 3 . '</a>'; } elseif( $page >= $total_pages ){ $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page-2, ) ) ) . '" class="secondary btn--sm mr-1">' . ($page-2) . '</a>'; $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page-1, ) ) ) . '" class="secondary btn--sm mr-1">' . ($page-1) . '</a>'; $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page, ) ) ) . '" class="primary btn--sm mr-1">' . $page . '</a>'; } else { $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page-1, ) ) ) . '" class="secondary btn--sm mr-1">' . ($page-1) . '</a>'; $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page, ) ) ) . '" class="primary btn--sm mr-1">' . $page . '</a>'; $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page+1, ) ) ) . '" class="secondary btn--sm mr-1">' . ($page+1) . '</a>'; } } else { $page_counter = 1; while( $total_pages > 0 ){ if( $page_counter === $page ){ $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page_counter, ) ) ) . '" class="primary btn--sm mr-1">' . $page_counter . '</a>'; } else { $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $page_counter, ) ) ) . '" class="secondary btn--sm mr-1">' . $page_counter . '</a>'; } $page_counter++; } } if( $page >= $total_pages ){ $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $total_pages, ) ) ) . '" class="btn--sm mr-1">' . LOGPLUG()->helpers->translate( '>', 'logs' ) . '</a>'; } else { $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => ($page+1), ) ) ) . '" class="btn--sm mr-1">' . LOGPLUG()->helpers->translate( '>', 'logs' ) . '</a>'; } $pagination_links_out[] = '<a href="' . LOGPLUG()->helpers->built_url( $current_url, array_merge( $_GET, array( 'item_count' => $per_page, 'log_page' => $total_pages, ) ) ) . '" class="btn--sm mr-1">' . LOGPLUG()->helpers->translate( '>>', 'logs' ) . '</a>'; return implode( '', $pagination_links_out ); }
Дополнительно:
Ошибка по строке:
Вообще-то ничего не значит. Память кто-то сожрал раньше, просто этой части кода уже не хватило. Только профилированием можно точно найти место утечки. Ну или угадать, загрузив в мозг весь код от начала до места, где память кончилась.
Страниц на сайте много? Предположу, что проблема в пагинации...
Еще интересный момент в том, что цикл while создает ссылки для каждой страницы.
Я в php не силен, но быстрой гуглежкой нашел вариант логирования. Посмотрите, что будет писать и какое время займет различные части выполнения Вашего кода:
- Пишем сообщение непосредственно в файл журнала ошибок сервера:
error_log('Лог переменной: ' . print_r($var, true)); |
error_log('Лог переменной: ' . print_r($var, true));
- Получение временных меток перед и после выполнения кода:
microtime(true)
- благодарю, я как-то не подумал про логирование
- Minusator, так это первое, что необходимо делать при написание кода, чтобы хотя бы понимать, где ноги протянули ;)
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос

В показанном фрагменте главная проблема, скорее всего, в цикле пагинации. Если
$total_pagesбольшое или считается неправильно, код создаёт огромный массив$pagination_links_outсо ссылками на все страницы. Даже если логов несколько строк, ошибка может быть не в логах, а в генерации тысяч или миллионов ссылок.Сначала проверьте условие цикла. В норме должно быть ограничение по номеру страницы:
$page_counter = 1; while ($page_counter <= $total_pages) { // link $page_counter++; }
Если у вас условие выглядит как
while ($total_pages > 0), но внутри$total_pagesне уменьшается, это бесконечный цикл и память закончится неизбежно.Вторая проблема — не нужно выводить ссылки на все страницы, если их много. Делайте окно вокруг текущей страницы:
$start = max(1, $page - 2); $end = min($total_pages, $page + 2); for ($i = $start; $i <= $end; $i++) { $pagination_links_out[] = my_build_log_page_link($i); }
Третье: не используйте весь
$_GETбез фильтрации. Соберите только разрешённые параметры, иначе можно раздуть URL и получить мусорные ссылки.И ещё важный момент: логи нельзя грузить целиком в память. Читайте только нужную страницу через SQL
LIMIT/OFFSETили построчно из файла. Тогда вкладка “Логи” будет открываться быстро даже при большом количестве записей.