2010-03-30 4 views
12

У меня есть PHP-скрипт, который создает binary search tree за a rather large CSV file (5MB +). Это хорошо и все, но для чтения/разбора/индексирования файла требуется около 3 секунд.PHP - * быстрый * serialize/unserialize?

Теперь я думал, что могу использовать serialize() и unserialize(), чтобы ускорить процесс. Когда CSV-файл не изменился в то же время, нет смысла разбирать его снова.

К моему ужасу я нахожу, что вызов serialize() на моем индексном объекте занимает 5 секунд и создает огромный (19 МБ) текстовый файл, тогда как unserialize() занимает невыносимое 27 секунд, чтобы прочитать его. Усовершенствования выглядят немного иначе. ;-)

Итак - существует ли более быстрый механизм для хранения/восстановления графов больших объектов на/с диска в PHP?

(Для уточнения: я искал что-то, что берет значительно меньше, чем вышеупомянутые 3 секунд, чтобы сделать работу де-сериализации.)

+0

Почему бы не хранить информацию, которая находится в файле в базу данных? – RJD22

+0

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

+0

Как выглядят ваши объекты индекса? – user187291

ответ

3

Кажется, что ответ на ваш вопрос - нет.

Даже если вы обнаружите вариант «двоичного формата сериализации», скорее всего, даже это будет замедлять то, что вы предполагаете.

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

Я хотел бы добавить следующие идеи, а также:

  • кэширование запросов/ответов
  • ваш PHP скрипт не выключен, но становится сетевой сервер отвечать на запросы
  • или, смею Я говорю это, изменить структуру данных и метод запроса вы используете
+0

Я думаю, что вы здесь. Жаль, но так оно и есть. – Tomalak

+0

У вас есть богатый источник данных, который предлагает множество креативных идей, я уверен, что вы придумаете что-то очень плавное. – zaf

1

Если вы хотите скорость, запись или чтение из файла менее оптимальной.

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

Другая возможность - это что-то вроде Memcached.

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

+0

Нет ли бинарного формата сериализации для PHP, который записывает байты памяти на диск и просто читает их снова? Если CSV - это все строки, и индексный объект фактически содержит меньше информации, чем текстовый файл, почему его сериализованная форма должна быть раздутой? – Tomalak

+0

@Tomalak: проверить пакет/распаковать – Robert

+0

@Robert: Похоже, что пакет работает только для отдельных значений, а не для сложных объектов. – Tomalak

2

я вижу два варианта здесь

строку сериализации, в простейшей форме нечто вроде

write => implode("\x01", (array) $node); 
    read => explode() + $node->payload = $a[0]; $node->value = $a[1] etc 

бинарной сериализации с пакетом()

write => pack("fnna*", $node->value, $node->le, $node->ri, $node->payload); 
    read => $node = (object) unpack("fvalue/nre/nli/a*payload", $data); 

Было бы интересно для сравнения оба варианта и сравнить результаты.

+0

Дерево имеет корневой узел. Было бы достаточно, чтобы 'pack()' этот корневой узел, я имею в виду, упаковал бы весь граф? – Tomalak

+0

нет, пакет обрабатывает только отдельные переменные – user187291

+2

Тогда я не боюсь. : - \ – Tomalak

6

var_export должно быть много быстрее, так как PHP не будет обрабатывать строку на всех:

// export the process CSV to export.php 
$php_array = read_parse_and_index_csv($csv); // takes 3 seconds 
$export = var_export($php_array, true); 
file_put_contents('export.php', '<?php $php_array = ' . $export . '; ?>'); 

Затем включите export.php, когда вам это нужно:

include 'export.php'; 

В зависимости от вашего веб-сервера, возможно, придется chmod export.php, чтобы сделать его исполняемым первым.

+5

Я знаю, что это старый, но есть лучший способ, по-прежнему используя тот же код. вместо 'file_put_contents ('export.php', '');', просто используйте 'file_put_contents ('export.php', ''); '. И вместо 'include 'export.php';', используйте '$ data = include 'export.php';'. –

+0

Это потрясающее решение. Я всегда использую var_export 'ed datas in includes, и это делает его немного проще! – Gfra54

-1

SQLite поставляется с PHP, вы можете использовать его как свою базу данных. В противном случае вы можете попробовать использовать сеансы, тогда вам не нужно сериализовать что-либо, вы просто сохраняете необработанный объект PHP.

+0

Могу ли я поделиться объектом между сеансами в PHP? – Tomalak

+0

Вы не можете делиться им между различными сеансами. Хотя вы, вероятно, можете заставить всех использовать один и тот же сеанс, установив собственный идентификатор сеанса. В противном случае вам придется изучить использование разделяемой памяти. http://php.net/manual/en/book.shmop.php –

+0

Просто быстро заметьте, если кто-нибудь наткнется на него - сделайте ** НЕ ** используйте сеансы для хранения больших объектов, и тем более - сделайте ** NOT ** пусть люди используют один и тот же сеанс. Это побеждает цель использования сеанса в первую очередь - и, поскольку только один пользователь может получить доступ к одному идентификатору сеанса за раз, он будет эффективно ограничивать обработку запросов только ** одним **! Сессия должна загружаться с диска/базы данных в любом случае! – SteveB

0

Как использовать JSON для хранения или загрузки данных? Я понятия не имею, как быстро парсер JSON находится на PHP, но обычно это работает на большинстве языков, и это легкий формат.

http://php.net/manual/en/book.json.php

+0

Да, это будет работать для данных, а не для графов объектов. Я искал что-то, что сбрасывает весь граф объекта на диск, поэтому я не буду штрафа за его повторное создание (с точки зрения разбора, проверки ошибок, построения объекта). – Tomalak

+0

JSON будет работать нормально, если ваш граф объекта не цикличен. –

+0

JSON не может представлять ссылки. Он может представлять иерархии. Даже необязательно иметь циклические ссылки, как только появляется «родительская» ссылка, все кончено. Кроме того, сериализация/un-serializing абсолютно не то, что я имел в виду. – Tomalak

4

Сначала вы должны изменить способ ваша программа работает. разделите CSV-файл на более мелкие куски. Я полагаю, это IP-хранилище данных. ,

Преобразование всех IP-адресов в целые или длинные.

Итак, если возник вопрос, вы можете узнать, какую часть посмотреть. Для этого есть функции <?php ip2long() /* and */ long2ip();. Итак, от 0 до 2^32 конвертировать все IP-адреса в 5000K/50K всего 100 файлов меньшего размера. Этот подход обеспечивает более быструю сериализацию.

Думайте умный, код аккуратным;)

Смежные вопросы