PHP почему продолжить, чем использовать break - PullRequest
4 голосов
/ 03 апреля 2011

Пожалуйста, рассмотрите следующий код:

$start = microtime();
for($i = 2; $i < 100; $i++)
{
    for($y = 2; $y <= sqrt($i); $y++)
    {
        if($i%$y != 0)
        {
            continue;
        }
        else
        {
          continue 2;
        }
    }

    echo $i.',';
}
echo "\nFinished in " . (microtime() - $start);

Учитывая, что в приведенном выше коде эффективно используется продолжение 2, чтобы разорвать внутренний цикл и пропустить любой код после внутреннего цикла, почему следующий код в среднем выполняется быстреекогда кажется, что он делает больше:

 $start = microtime();
for($i = 2; $i < 100; $i++)
{
    $flag = true;
    for($y = 2; $y <= sqrt($i); $y++)
    {
        if($i%$y != 0)
        {
            continue;
        }
        else
        {
          $flag = false;
          break;
        }
    }

    if($flag === true) echo $i.',';
}
echo "\nFinished in " . (microtime() - $start);

Спасибо за любой ввод.

__ _ __ Обновление __ _ __ _ __ _ __ _

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

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

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

Только для иллюстрации рассмотрите следующие небольшиеобразцы, использующие microtime (true), который показывает ту же схему, что и microtime ().

Я знаю, что это небольшая выборка, но картина довольно четкая:

Продолжить 0.00037288665771484 0.00048208236694336 0.00046110153198242 0.00039386749267575 0.000366210931039 *

Перерыв 0.00033903121948242 0.00035715103149414 0.00033307075500488 0.00034403800964355 0.00032901763916016

Спасибо за внимание и за любые дальнейшие отзывы.

** ___ ОБНОВЛЕНИЕ Дальнейшее расследование __ _ __ _ __ _ ___

Интересно, еслиоператоры echo удаляются из кода, оператор continue выполняет быстрее, а операторы echo на месте: break быстрее.

Пожалуйста, рассмотрите следующий пример кода и учтите, что результаты конфликтуют в зависимости от того, используются ли операторы echoудалены или нет:

<?php
$breakStats = array();
$continueStats = array();

ob_start();
for($i = 0; $i < 10000; $i++)
{
   $breakStats[] = doBreakTest();
   $continueStats[] = doContinueTest();
}
ob_clean();

echo "<br/>Continue Mean " . (array_sum($continueStats) / count($continueStats));
echo "<br/>Break Mean " . (array_sum($breakStats) / count($breakStats));

function doBreakTest()
{
    $start = microtime(true);
    for($i = 2; $i < 100; $i++)
    {
        $flag = true;
        $root = sqrt($i);
        for($y = 2; $y <= $root; $y++)
        {
            if($i%$y != 0)
            {
                continue;
            }
            else
            {
                $flag = false;
                break;
            }
        }
    }

    if($flag === true) echo $i . '';
    return microtime(true) - $start;
}

function doContinueTest()
{
    $start = microtime(true);
    for($i = 2; $i < 100; $i++)
    {
        $root = sqrt($i);
        for($y = 2; $y <= $root; $y++)
        {
            if($i%$y != 0)
            {
                continue;
            }
            else
            {
                echo $i . '';
                continue 2;
            }
        }
    }
    return microtime(true) - $start;
}

Присутствуют эхо-операторы:

Продолжить Среднее 0,00014134283065796 Среднее значение прерывания 0,00012669243812561

Отсутствует эхо-оператор:

Продолжить Среднее 0,00011746988296509Среднее значение перерыва 0.00013022310733795

Обратите внимание, что, удаляя оператор echo из теста break и flag, мы также удаляем проверку ($ flag === true), поэтому нагрузка должна уменьшиться, но продолжение в этом случае все равно выигрывает.W

Таким образом, в чистом сценарии продолжения n и разрыва + флага выясняется, что продолжение n является более быстрым конструктом.Но добавьте равное количество идентичных операторов echo и флагов производительности continue n.

Логично, что continue n должен быть быстрее, но я ожидал бы увидеть то же самое с присутствующими операторами echo.

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

Спасибо:)

Ответы [ 2 ]

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

Версия continue 2 немного быстрее для меня. Но это не те вещи, о которых вам обычно нужно беспокоиться. Рассмотрим:

for($y = 2; $y <= sqrt($i); $y++)

Здесь вы вычисляете sqrt на каждой итерации. Просто изменив это на:

$sqrt = sqrt($i);
for($y = 2; $y <= $sqrt; $y++)

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

continue 2 следует использовать, если вы обнаружите, что вам легче понять. Компьютер на самом деле все равно.

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

php -d vld.active=1 -d vld.execute=0 -f foo.php

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

Да, первый немного быстрее. Это потому, что он просто выпрыгивает из продолжения 2 и печатает $ i.

Во 2-м примере нужно выполнить больше заданий ... присвоить значение переменной $ flag, выпрыгнуть из цикла, проверить значение $ flag, проверить тип $ flag (тоже сравнивает), а затем распечатать $ i. Это немного медленнее (простая логика).

В любом случае, имеет ли это какое-то назначение?

Некоторые мои результаты для сравнения

0.0011570 < 0.0012173
0.0011540 < 0.0011754
0.0011820 < 0.0012036
0.0011570 < 0.0011693
0.0011970 < 0.0012790

Используется: PHP 5.3.5 @ Windows (1000 попыток; сначала 100% было быстрее)

0.0011570 < 0.0012173
0.0005000 > 0.0003333
0.0005110 > 0.0004159
0.0003900 < 0.0014029
0.0003950 > 0.0003119
0.0003120 > 0.0002370

Используется: PHP 5.3.3 @ Linux (1000 попыток; 32% сначала: 68% секунды быстрее)

0.0006700 > 0.0004863
0.0003470 > 0.0002591
0.0005360 > 0.0004027
0.0004720 > 0.0004229
0.0005300 > 0.0004366

Используется: PHP 5.2.13 @ Linux (1000 попыток; 9% сначала: 91% секунды быстрее)

Извините, у меня больше нет серверов для тестирования :) Теперь я думаю, что это в основном зависит от аппаратного обеспечения (и, возможно, от ОС тоже).

Обычно: Это доказывает только то, что сервер Linux работает быстрее, чем один запуск в Windows:)

...