Эффективность функций PHP - PullRequest
1 голос
/ 29 июня 2009

Есть ли таблица того, сколько "работы" требуется для выполнения данной функции в PHP? Я не специалист по компьютерным технологиям, поэтому у меня, возможно, нет формального фона, чтобы знать, что «о да, строки работают с дольше, чем целые числа» или что-то в этом роде. Все ли шаги / строки в программе созданы равными? Я просто не знаю, с чего начать.

В настоящее время я задаю несколько вопросов по Project Euler, в которых я уверен, что мой ответ сработает, но я по минутам синхронизирую свой локальный сервер Apache с моими запросами (и PE сказал, что все проблемы могут быть решены) <1 минута) Я не знаю, как / с чего начать оптимизацию, поэтому было бы полезно узнать больше о PHP и о том, как он использует память. Для чего это стоит, вот мой код для <a href="http://projecteuler.net/index.php?section=problems&id=206" rel="nofollow noreferrer"> вопрос 206 :

<?php
$start = time();
for ($i=1010374999; $i < 1421374999; $i++) { 
$a = number_format(pow($i,2),0,".","");
$c = preg_split('//', $a, -1, PREG_SPLIT_NO_EMPTY);
if ($c[0]==1) {
    if ($c[2]==2) {
        if ($c[4]==3) {
            if ($c[6]==4) {
                if ($c[8]==5) {
                    if ($c[10]==6) {
                        if ($c[12]==7) {
                            if ($c[14]==8) {
                                if ($c[16]==9) {
                                    if ($c[18]==0) {
                                        echo $i;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
}
$end = time();
$elapsed = ($end-$start);
echo "<br />The time to calculate was $elapsed seconds";
?>

Если это вики-вопрос об оптимизации, просто дайте мне знать, и я перенесу его. Опять же, не ища ответа, просто помогите узнать, как эффективно использовать мой код (хотя поверхностные подсказки не будут отвергнуты, и я понимаю, что, возможно, существуют более изящные математические способы решения проблемы)

Ответы [ 5 ]

6 голосов
/ 29 июня 2009

Нет такой таблицы, которая бы указала, сколько времени занимает выполнение каждой функции PHP, поскольку время выполнения будет сильно варьироваться в зависимости от ввода.

Посмотрите, что делает ваш код. Вы создали цикл, который будет выполняться 411 000 000 раз. Поскольку код должен завершиться менее чем за 60 секунд (минута), для решения проблемы вы предполагаете, что каждое прохождение цикла займет менее (приблизительно) .000000145 секунд. Это неразумно, и никакое использование «правильной» функции не решит ваш вызов. Попробуйте свой цикл с ничего там

for ($i=1010374999; $i < 1421374999; $i++) { 

}

Если у вас нет доступа к фантастическим компьютерам, это, вероятно, не завершит выполнение менее чем за 60 секунд. Итак, вы знаете, что этот подход никогда не сработает.

Это известное решение проблемы методом грубой силы. Цель Project Euler - научить вас творчески, с точки зрения математики и программирования, решать проблемы. Вы хотите уменьшить количество поездок, которые вам нужно пройти через этот цикл. Очевидное решение никогда не будет здесь ответом.

Я не хочу рассказывать вам о решении, потому что цель всего этого - продумать свой путь и стать лучшим программистом алгоритмов. Изучите проблему, подумайте об ее ограничениях и подумайте о том, как сократить общее количество проверяемых номеров.

2 голосов
/ 29 июня 2009

Хорошим инструментом для просмотра времени выполнения вашего кода является xDebug: http://xdebug.org/docs/profiler

Это устанавливаемое расширение PHP, которое можно настроить для вывода полной разбивки вызовов функций и времени выполнения вашего сценария. Используя это, вы сможете увидеть, что в вашем коде занимает больше всего времени для выполнения, и попробовать разные подходы.

РЕДАКТИРОВАТЬ: теперь, когда я на самом деле смотрю ваш код, вы выполняете 400 миллионов + регулярных вызовов! Я ничего не знаю о проекте Euler, но мне трудно поверить, что этот код может быть реализован менее чем за минуту на обычном оборудовании.

1 голос
/ 29 июня 2009

preg_split, вероятно, будет медленным, потому что он использует регулярное выражение. Разве нет лучшего способа сделать эту строку?

Подсказка: вы можете получить доступ к символам в такой строке:

$str = 'This is a test.';
echo $str[0];
0 голосов
/ 29 июня 2009

Во-первых, вот немного более чистая версия вашей функции с выводом отладки

<?php
$start = time();
$min = (int)floor(sqrt(1020304050607080900));
$max = (int)ceil(sqrt(1929394959697989990));

for ($i=$min; $i < $max; $i++) {
$c = $i * $i;
echo $i, ' => ', $c, "\n";
if ($c[0]==1
    && $c[2]==2
        && $c[4]==3
        && $c[6]==4
        && $c[8]==5
        && $c[10]==6
        && $c[12]==7
        && $c[14]==8
        && $c[16]==9
        && $c[18]==0)
  {
    echo $i;
        break;
  }
}
$end = time();
$elapsed = ($end-$start);
echo "<br />The time to calculate was $elapsed seconds";

А вот первые 10 строк вывода:

1010101010 => 1020304050403020100
1010101011 => 1020304052423222121
1010101012 => 1020304054443424144
1010101013 => 1020304056463626169
1010101014 => 1020304058483828196
1010101015 => 1020304060504030225
1010101016 => 1020304062524232256
1010101017 => 1020304064544434289
1010101018 => 1020304066564636324
1010101019 => 1020304068584838361

Похоже, что это действительно вдохновляет на возможную оптимизацию вашего алгоритма. Обратите внимание, что мы даже не близки, начиная с 6-й записи (1020304060504030225) - у нас есть 6 в позиции, где нам нужно 5!

Фактически, многие из следующих записей будут бесполезны, пока мы не вернемся к точке, где у нас будет 5 в этой позиции. Зачем беспокоиться о подсчете промежуточных ценностей? Если мы сможем выяснить, как, мы должны перейти к 1010101060, где эта цифра снова станет 5 ... Если мы сможем пропустить десятки итераций в такое время, мы сэкономим более 90% времени выполнения. !

Обратите внимание, что это может не быть практическим подходом вообще (на самом деле, я вполне уверен, что это не так), но именно так вы и должны думать. Какие математические приемы вы можете использовать, чтобы сократить количество выполняемых итераций?

0 голосов
/ 29 июня 2009

Попробуйте переключить preg_split() на explode() или str_split(), которые быстрее

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...