Я делаю некоторые профилирования по различным методам доступа к большим (ish) массивам данных в PHP. Практический пример довольно прост: некоторые из наших инструментов выводят данные в файлы PHP как ассоциативные массивы, и эти файлы считаются статическими данными приложением. Мы делаем игры, поэтому некоторые примеры файлов данных будут включать элементы в каталоге, задачи, которые должен выполнить пользователь, или определения для карт:
<?php $some_data = array( ...lots and lots of stuff in here... ); ?>
Поскольку эти массивы являются большими (400 КБ), и большая часть нашего кода заинтересована в этих данных, становится необходимо как можно более эффективно получать доступ к этим данным. Я решил использовать 3 разных шаблона для этого. Представляя методы, я поделюсь своими результатами ниже.
То, что я ищу, – это некоторые проверки на основе этих методов и их время, а также любые другие методы, которые можно попробовать.
В методе экспортер фактически создает файл, который выглядит так:
<?php function getSomeData() { $some_data = array( ...lots and lots of stuff here... ); return $some_data; } ?>
Клиентский код может затем получить данные, просто вызвав getSomeData (), когда они этого захотят.
В этом методе файл данных выглядит идентично исходному коду блока выше, однако клиентский код должен перескакивать через несколько обручей, чтобы получить данные в локальной области. Это предполагает, что массив находится в файле с именем 'some_data.php';
global $some_data; //must be the same name as the variable in the data file... include 'some_data.php';
Это принесет массив $ some_data в область видимости, хотя это немного громоздко для клиентского кода (мое мнение).
Этот метод почти идентичен методу # 1, однако функция getter не возвращает значение, а скорее устанавливает ссылку на данные.
<?php function getSomeDataByRef($some_data) { $some_data = array( ...lots and lots of stuff here... ); return $some_data; } ?>
Затем код клиента извлекает данные, объявляя локальную переменную (называемую чем угодно) и передавая ее по ссылке на getter:
$some_data_anyname = array(); getSomeDataByRef(&$some_data_anyname);
Поэтому я запустил небольшой скрипт, который запускает каждый из этих методов получения данных в 1000 раз и усредняет время выполнения (вычисленное microtime (true) в начале и в конце). Ниже приведены мои результаты (в мс, работающие на MacBookPro 2 ГГц, 8 ГБ оперативной памяти, версия PHP 5.3.4):
AVG: 0,0031637034416199 MAX: 0,0043289661407471 МИН: 0.0025908946990967
AVG: 0.01434082698822 MAX: 0.018275022506714 MIN: 0.012722969055176
AVG: 0.00335768699646 MAX: 0.0043489933013916 МИН: 0.0029017925262451
В любом случае представляется очевидным, что из этих данных метод global + include уступает другим, что является «незначительной» разницей.
Мысли? Я что-то совсем не вижу? (вероятно…)
Заранее спасибо!
Не уверен, что это именно то, что вы ищете, но оно должно помочь в решении проблем со скоростью и памятью. Вы можете использовать фиксированный массив массивов:
$startMemory = memory_get_usage(); $array = new SplFixedArray(100000); for ($i = 0; $i < 100000; ++$i) { $array[$i] = $i; } echo memory_get_usage() - $startMemory, ' bytes';
Подробнее о больших массивах php читайте здесь: http://nikic.github.com/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG.html
Также вы подумали о хранении данных в кеше / памяти? Например, вы можете использовать mysqlite с движком inmemory при первом выполнении, а затем получить доступ к данным:
$pdo = new PDO('sqlite::memory:'); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // .. Use PDO as normal
Для одного из моих проектов, в которых база данных не была вариантом, я столкнулся с такой же проблемой загрузки больших (по большому счету, я имею в виду серии из 3 Мбайт файлов) php-файлов, содержащих массивы в памяти, и я искал варианты для максимизации производительности. Я нашел очень простой, который кешировал эти файлы на диске как json при первом использовании. Я разделил время загрузки на 3, а пиковое потребление памяти на 30%. Загрузка локального json-файла с помощью json_decode () намного быстрее, чем включение большого файла php, содержащего массив. это также имеет преимущество в том, что формат, который большинство языков может манипулировать напрямую. Надеюсь, это поможет.