Производительность массива PHP - PullRequest
34 голосов
/ 05 февраля 2011

Я тестирую алгоритм для упаковки двухмерных бинов, и я выбрал PHP для его макетирования, так как в настоящее время это мой простой язык.

Как вы можете видеть на http://themworks.com/pack_v0.2/oopack.php?ol=1 это работает довольно хорошо, но вам нужно подождать около 10-20 секунд, чтобы собрать 100 прямоугольников.Для некоторых трудно обрабатываемых наборов он достигнет предела времени выполнения php 30 с.

Я провел некоторое профилирование, и это показывает, что большую часть времени мой скрипт проходит через разные части небольшого 2d массива с нулями и 1 в нем.,Он либо проверяет, равна ли определенная ячейка 0/1, либо устанавливает ее на 0/1.Он может выполнять такие операции миллион раз, и каждый раз это занимает несколько микросекунд.

Полагаю, я мог бы использовать массив логических значений в статически типизированном языке, и все было бы быстрее.Или даже сделать массив из 1-битных значений.Я думаю о преобразовании всего этого в какой-то скомпилированный язык.Разве PHP не подходит для этого?

Если мне нужно преобразовать его, скажем, в C ++, насколько хороши автоматические преобразователи?Мой скрипт - это просто множество циклов с базовыми массивами и манипуляциями с объектами.

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

function fits($bin, $w, $h, $x, $y) {

    $w += $x;
    $h += $y;

    for ($i = $x; $i < $w; $i++) {

        for ($j = $y; $j < $h; $j++) {

            if ($bin[$i][$j] !== 0) {
                return false;
            }
        }
    }

    return true;    
}

Обновление: я пытался использовать массив 1dвместо 2d как один из предложенных ответов.Так как мне нужно было всегда иметь доступную ширину корзины, я решил обернуть все в объект.Кроме того, теперь в каждом цикле необходимо рассчитать индекс.Теперь запуск сценария занимает еще больше времени.Другие методы не принесли большого прироста производительности, а сделали код менее читабельным.Время для HipHop, я думаю.

Обновление: поскольку hiphop php работает только на Linux, а у меня его нет, я решил переписать все это на C ++.Приятно освежить старые навыки.Кроме того, если я найду способ использовать хип-хоп, будет интересно сравнить рукописный код C ++ и один хип-хоп сгенерированный.

Обновление: я переписал эту вещь на с ++, в среднем она работаетВ 20 раз быстрее и использует гораздо меньше памяти.Дайте мне посмотреть, смогу ли я сделать это еще быстрее.

Ответы [ 7 ]

23 голосов
/ 05 февраля 2011

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

Что касается вашего кода, я бы оптимизировал несколько моментов:

.

function fits($bin, $x, $y, $w, $h) {
    $w += $x;
    $h += $y;

    for ($i = $x; $i < $w; ++$i) {
        for ($j = $y; $j < $h; ++$j) {
            if ($bin[$i][$j] !== 0) {
                return false;
            }
        } 
    }

    return true;   
}

Хотя я не уверен, почему вы добавляете $x к $width / $y к $height. Разве вы не хотите переходить от текущих координат к границам изображения?

11 голосов
/ 05 февраля 2011

Решением вашей проблемы может быть https://github.com/facebook/hiphop-php/wiki/

Как говорят все остальные, PHP не является оптимальным языком для задач с интенсивными вычислениями. Он также не имеет типа массива. То, что в PHP называется array(), на самом деле представляет собой словарь / хэш-карту. У него есть некоторые оптимизации, которые можно удвоить как список, но, как вы уже обнаружили, он не обеспечивает такое же поведение во время выполнения, как указатели и массивы Си.

HipHop может преобразовать код PHP в оптимизированный C ++. Он также был предназначен для манипулирования строками, но вполне мог предложить правильное преобразование массива / списка.

Отказ от ответственности: я никогда не пробовал. Просто хотел дать умный ответ здесь.

6 голосов
/ 05 февраля 2011

Чтобы предложить другую альтернативу PHP:

Вы изучили SplFixedArray?

В зависимости от того, как структурированы ваши массивы (линейные от 0 до x) массивы, этоможет работать немного быстрее

Для оценки см. http://www.slideshare.net/tobias382/new-spl-features-in-php-53 Слайд 15 и 16 (извините, не нашел лучшего)

5 голосов
/ 16 января 2018

ОБНОВЛЕННЫЙ ОТВЕТ, НЕОБХОДИМЫЙ НА 2018 ГОДА.

Этот вопрос старый, и приведенные ответы не совсем верны в PHP 7 , если используется упакованные массивыПоскольку вопрос отображается первым попаданием в Google, я добавляю новый ответ

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

Читайте здесь: Блог Blackfire на PHP 7 Улучшения массива

1 голос
/ 11 июня 2014

Более поздней альтернативой является расширение QB для PHP, которое специально разработано для решения подобных проблем.

Хотя PHP является отличным языком для построения сложных веб-приложений, он накладывает определенные ограничения,Написание кода, выполняющего низкоуровневые вычислительно-сложные задачи на PHP, как правило, нецелесообразно - это будет просто слишком медленно.Расширение QB устраняет эту слабость PHP.Переводя коды операций Zend и выполняя их через виртуальную машину со статической типизацией, QB обеспечивает прирост производительности на порядок.Дополнительная мощь позволяет программистам PHP делать вещи, которые они не могли делать раньше, такие сложные манипуляции изображениями на уровне пикселей.

См .: http://php -qb.net /

0 голосов
/ 08 сентября 2016

Массивы в PHP действительно кажутся довольно медленными, особенно в цикле по многомерным массивам.Другой вариант - попробовать Quercus .Это реализация PHP в Java.Я полагаю, он использует массивы Java.Хотя я не сравнивал.

0 голосов
/ 15 февраля 2011

Вопрос почти квалифицируется как «в первую очередь основанный на мнении». Имея это в виду:

«Разве PHP не подходит для этого?»

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

«Я думаю о преобразовании всего этого в некоторый скомпилированный язык.»

Технически, PHP также может быть скомпилирован. На Facebook есть компилятор PHP на C ++. Есть Zend-компилятор как раз вовремя. Раньше был интерпретатор PHP на Java (хотя, если я правильно помню, он больше не активен).

Я бы порекомендовал вам попробовать Java, так как его синтаксис похож, в конце концов, это было одно из вдохновляющих идей PHP 5. Java-байт-код компилируется в нативный код начиная с JDK 1.5. Производительность должна возрасти примерно в 4 раза для той же структуры кода (при условии, что вы используете дистрибутив PHP для сообщества).

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