сериализовать большой массив в PHP?

Дифференциальная реализация ответа @cosmosis. Вероятно, это более гибко.

import numpy as np
import matplotlib.pyplot as plt

X = np.linspace(0,100,11)

plt.plot(X,-X, label='plot 1', color='red')
plt.plot(X,-2*X, label='plot 2', color='green')
plt.plot(X,-3*X, label='plot 3', color='blue')

(lines, labels) = plt.gca().get_legend_handles_labels()
#it's safer to use linestyle='none' and marker='none' that setting the color to white
#should be invisible whatever is the background
lines.insert(1, plt.Line2D(X,X, linestyle='none', marker='none'))
labels.insert(1,'')

plt.legend(lines,labels,numpoints=1, loc=4,ncol=1)

plt.show()

Другой вариант - создать две легенды в качестве здесь , а затем вытеснить их с помощью ключевого слова bbox_to_anchor здесь

(lines, labels) = plt.gca().get_legend_handles_labels()
leg1 = plt.legend(lines[:1], labels[:1], bbox_to_anchor=(0,0,0.8,1), loc=1)
leg2 = plt.legend(lines[1:], labels[1:], bbox_to_anchor=(0,0,1,1), loc=1)
gca().add_artist(leg1)

Выполняя это, я получаю this [/g2] без необходимости добавления каких-либо других объектов.

13
задан JasonDavis 10 August 2009 в 21:21
поделиться

10 ответов

Как уже ответила пара других людей, просто для удовольствия, вот очень быстрый тест (смею ли я его так называть?) ; рассмотрите следующий код:

$num = 1;

$list = array_fill(0, 5000, str_repeat('1234567890', $num));

$before = microtime(true);
for ($i=0 ; $i<10000 ; $i++) {
    $str = serialize($list);
}
$after = microtime(true);

var_dump($after-$before);
var_dump(memory_get_peak_usage());

Я запускаю это на PHP 5.2.6 (тот, который идет в комплекте с Ubuntu jaunty).
И да, есть только значения; нет ключей; и значения довольно просты: нет объекта, нет подмассивов, нет ничего, кроме строки.

Для $ num = 1 вы получите:

float(11.8147978783)
int(1702688)

Для $ num = 10 , вы получите:

float(13.1230671406)
int(2612104)

А для $ num = 100 вы получите:

float(63.2925770283)
int(11621760)

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


Теперь с массивом из 50000 элементов вместо 5000, это означает, что эта часть кода изменена:

$list = array_fill(0, 50000, str_repeat('1234567890', $num));

С $ num = 1 вы получите:

float(158.236332178)
int(15750752)

Учитывая время, которое потребовалось для 1, я не буду запускать это ни для $ num = 10 или $ num = 100 ...


Да, конечно, в реальной ситуации вы бы не сделали это 10 000 раз; поэтому давайте попробуем выполнить только 10 итераций цикла for.

Для $ num = 1 :

float(0.206310987473)
int(15750752)

Для $ num = 10 :

float(0.272629022598)
int(24849832)

И для $ num = 100 :

float(0.895547151566)
int(114949792)

Да, это почти 1 секунда - и используется довольно много памяти ^^
(Нет, это не рабочий сервер: у меня довольно высокий предел memory_limit на этой машине разработки ^^)


Итак, в конце концов, он должен быть немного короче, чем это число - и, да, у вас могут быть числа, которые говорят все, что вы хотите - Я бы не сказал, что есть «предел», как в «жестко запрограммированном» в PHP, но вы в конечном итоге столкнетесь с одним из них:

  • max_execution_time (обычно на веб-сервере не более 30 секунд)
  • memory_limit (на веб-сервере обычно не более 32 МБ)
  • нагрузка на ваш веб-сервер: в то время как 1 из этого большого цикла сериализации потребовался 1 мой процессор; если у вас есть несколько пользователей на одной странице одновременно, я позволю вам представить, что это даст; -)
  • терпение вашего пользователя ^^

Но,
И вы должны принять во внимание количество времени / загрузки процессора, использование этого кеша может помочь вам; -)

Тем не менее, лучший способ узнать это - провести тестирование самостоятельно, с реальными данными ;-)


И вы можете также посмотреть, что Xdebug может сделать, когда дело доходит до профилирования : такая ситуация - одна из тех, для которых она полезна!

]
27
ответ дан 1 December 2019 в 06:03
поделиться

Функция serialize () ограничена только доступной памятью.

7
ответ дан 1 December 2019 в 06:03
поделиться

PHP не применяет ограничений. Serialize возвращает представление байтового потока (строку) сериализованной структуры, поэтому вы просто получите большую строку.

5
ответ дан 1 December 2019 в 06:03
поделиться

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

4
ответ дан 1 December 2019 в 06:03
поделиться

Хорошо ... еще номера! (PHP 5.3.0 OSX, без кеша опкодов)

Код @Pascal на моей машине для n = 1 при 10 тыс. Итерах дает:

float(18.884856939316)
int(1075900)

Я добавляю unserialize () к вышеприведенному, так что

$num = 1;

$list = array_fill(0, 5000, str_repeat('1234567890', $num));

$before = microtime(true);
for ($i=0 ; $i<10000 ; $i++) {
    $str = serialize($list);
    $list = unserialize($str);
}
$after = microtime(true);

var_dump($after-$before);
var_dump(memory_get_peak_usage());

производит

float(50.204112052917)
int(1606768) 

Я предполагаю, что лишние 600 КБ или около того - это сериализованная строка.

Мне было интересно узнать о var_export и его партнере include / eval $ str = var_export ($ list, true); вместо serialize () в оригинал производит

float(57.064643859863)
int(1066440)

, поэтому памяти становится немного меньше (по крайней мере, для этого простого примера), но уже больше времени.

добавление в eval ('$ list ='. $ str. ';'); вместо unserialize в приведенном выше производит

float(126.62566018105)
int(2944144)

Указывает, что, вероятно, есть утечка памяти где-то при выполнении eval: - /.

Итак, опять же, это не ' отличные тесты (мне действительно нужно изолировать eval / unserialize, поместив строку в локальную переменную или что-то в этом роде, но я ленив), но они показывают связанные тенденции. var_export кажется медленным.

2
ответ дан 1 December 2019 в 06:03
поделиться

Нет ограничений, но помните, что сериализация и десериализация имеет свои затраты.

Десериализация чрезвычайно дорога.

Менее затратный способ кэширования этих данных будет через var_export () как таковой (начиная с PHP 5.1.0, он работает с объектами ):

$largeArray = array(1,2,3,'hello'=>'world',4);

file_put_contents('cache.php', "<?php\nreturn ".
                                var_export($largeArray, true).
                                ';');

Затем вы можете просто получить массив, выполнив следующие действия:

$largeArray = include('cache.php');

Ресурсы обычно не могут быть кэшированы.

К сожалению, если в вашем массиве есть циклические ссылки, вам нужно использовать ] serialize () .

4
ответ дан 1 December 2019 в 06:03
поделиться

Нет, ограничений нет, и это :

set_time_limit(0);
ini_set('memory_limit ', -1);

unserialize('s:2000000000:"a";');

поэтому у вас должен быть safe.mode = On или установленное расширение, подобное Suhosin , иначе оно займет всю память в вашей системе.

1
ответ дан 1 December 2019 в 06:03
поделиться

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

Как указано выше, единственное ограничение на размер - доступная память.

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

1
ответ дан 1 December 2019 в 06:03
поделиться

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

На самом деле неинтересно постоянно сериализовать и десериализовать данные только для обновления или изменения некоторых фрагментов информации.

1
ответ дан 1 December 2019 в 06:03
поделиться

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

1
ответ дан 1 December 2019 в 06:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: