ФорумПрограммированиеPHP для идиотов → out of memory

out of memory

  • Sineokov

    Сообщения: 14 Репутация: N Группа: Кто попало

    Spritz Янв. 1, 2011, 9:22 п.п.

    Доброго времени суток, всем.

    У меня при выполнении функции simplexml_load_file() сервер возвращает ошибку: "error: xmlSAX2Characters: out of memory"
    то есть на сколько я понимаю памяти не хватает оперативной =)
    Как можно обойти эту проблему программным путём?
    Загружаемый xml файл очень большой. Может есть возможность считывать его частями, а не сразу целиком?
  • vasa_c

    Сообщения: 3131 Репутация: N Группа: в ухо

    Spritz Янв. 1, 2011, 11:59 п.п., спустя 2 часа 37 минут 19 секунд

    Скорее всего существует, но очевидно не с помощью simplexml_load_file()

    Смотря что вы собираетесь с ним делать.
  • Sineokov

    Сообщения: 14 Репутация: N Группа: Кто попало

    Spritz Янв. 2, 2011, 12:36 д.п., спустя 36 минут 49 секунд


    Скорее всего существует, но очевидно не с помощью simplexml_load_file()

    Смотря что вы собираетесь с ним делать.

    Ну, собственно, парсить его…
  • kostyl

    Сообщения: 5210 Репутация: N Группа: Джедаи

    Spritz Янв. 2, 2011, 12:41 д.п., спустя 4 минуты 35 секунд

    Sineokov, возможно придётся делать свой парсер…
  • Sineokov

    Сообщения: 14 Репутация: N Группа: Кто попало

    Spritz Янв. 2, 2011, 12:48 д.п., спустя 7 минут 41 секунду

    kostyl, каким образом?
    Точнее на чём он будет основан?
  • kostyl

    Сообщения: 5210 Репутация: N Группа: Джедаи

    Spritz Янв. 2, 2011, 1:04 д.п., спустя 15 минут 12 секунд

    Sineokov, ну я бы писал используя конечные автоматы
  • fgets

    Сообщения: 1099 Репутация: N Группа: Кто попало

    Spritz Янв. 2, 2011, 1:34 д.п., спустя 30 минут 41 секунду

    Однажды передо мною стояла подобная задача, я решил её при помощи fgets
    $xml = fopen("file.xml", "r"); // открывать обязательно "только для чтения" чтобы не переполнить буфер…
    while (!feof($xml)) {
    $buffer = fgets($xml);
    // тут работаем с полученным буфером
    }
    fclose($xml);


    также нужно перед этим открыть дополнительный файл-кеш для записи
    я проверял буфер на наличее нужной мне информации (без регулярок - стандартными str-функциями) и если такая присутствовала - парсил строку и посылал в файл-кеш…

    попробуйте на основе моего примера сделать свой
  • Sinkler

    Сообщения: 7958 Репутация: N Группа: в ухо

    Spritz Янв. 2, 2011, 1:39 д.п., спустя 4 минуты 36 секунд

    Однажды передо мною стояла подобная задача, я решил её при помощи fgets

    теперь понятно, чего у тебя ник такой))))
  • fgets

    Сообщения: 1099 Репутация: N Группа: Кто попало

    Spritz Янв. 2, 2011, 3:18 д.п., спустя 1 час 38 минут 59 секунд

    <?php 
    /** задача: вывести список доступных id с количеством подэлементов */
    $io = false; // интуитивный переключатель прохода
    $count = 0; // кол-во load'ов в over'е
    $id = ''; // текущий id
    $cache = @fopen('cache.txt', 'x'); // работа с кешем
    if (!$cache) die ('cache exists!');

    /** strread (буфер, io, счётчик, id, поток кеша) */
    function strread ($buffer, &$v2, &$v3, &$v4, &$v5)
    {
    if (!$v2) // ищем проход
    {
    if (strpos($buffer, '<over') === false)
    {
    $v2 = false;
    }
    else
    {
    $v4 = str_replace(array('<over id="', '">', '" />'), '', $buffer);
    /** можно и preg_match, но в данном случае
    * мы знаем что другого быть не может,
    * поэтому экономим память…
    */
    $v2 = true;
    }
    }
    else // ищем выход из over
    {
    if (strpos($buffer, '</over>') === false)
    {
    $v3++;
    $v2 = true;
    }
    else
    {
    fwrite($v5, "id: $v4, loads: $v3\r\n");
    $v3 = 0; $v4 = ''; // обнуляем переменные
    $v2 = false;
    }
    }
    }

    $xml = fopen('big.xml', 'rtb'); //открыли файл
    while (!feof($xml)) strread(trim(fgets($xml)), $io, $count, $id, $cache);
    fclose($xml); fclose($cache); // закрываем потоки xml и cache



    <ixxxxxi>
    <data>nodata</data>
    <over id="Anzhxicfq">
    <load>like</load>
    <offload>21</offload>
    <offload>15</offload>
    <load>like</load>
    <load>like</load>
    </over>
    <over id="ASy8d0nas">
    <load>like</load>
    <load>like</load>
    <load>like</load>
    </over>
    <over id="ASnax9z9u">
    <load>like</load>
    <load>like</load>
    <load>like</load>
    </over>
    <over id="Vefu9a1AA">
    <load>like</load>
    <load>like</load>
    </over>
    <over id="NAsu9ddda" />
    <over id="Zadli1110">
    <load>like</load>
    <load>like</load>
    <load>like</load>
    </over>
    </ixxxxxi>
  • fgets

    Сообщения: 1099 Репутация: N Группа: Кто попало

    Spritz Янв. 2, 2011, 3:27 д.п., спустя 8 минут 53 секунды

    ой немного ошибся в функции, вот правильная


    <?php
    /** strread (буфер, io, счётчик, id, поток кеша) */
    function strread ($buffer, &$v2, &$v3, &$v4, &$v5)
    {
    if (!$v2) // ищем проход
    {
    if (strpos($buffer, '<over') === false)
    {
    $v2 = false;
    }
    else
    {
    $xclose = (strpos($buffer, '" />'));
    $v4 = str_replace(array('<over id="', '">', '" />'), '', $buffer);
    /** можно и preg_match, но в данном случае
    * мы знаем что другого быть не может,
    * поэтому экономим память…
    */
    if ($xclose)
    {
    fwrite($v5, "id: $v4, loads: $v3\r\n");
    $v3 = 0; $v4 = ''; // обнуляем переменные
    $v2 = false;
    }
    else
    {
    $v2 = true;
    }
    }
    }
    else // ищем выход из over
    {
    if (strpos($buffer, '</over>') === false)
    {
    $v3++;
    $v2 = true;
    }
    else
    {
    fwrite($v5, "id: $v4, loads: $v3\r\n");
    $v3 = 0; $v4 = ''; // обнуляем переменные
    $v2 = false;
    }
    }
    }
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz Янв. 2, 2011, 12:09 п.п., спустя 8 часов 42 минуты 32 секунды

    гавно тема. добавь памяти и делай как делал
    Сапожник без сапог
  • Sineokov

    Сообщения: 14 Репутация: N Группа: Кто попало

    Spritz Янв. 2, 2011, 1:54 п.п., спустя 1 час 45 минут 14 секунд

    phpdude, ёптить. если бы это было так просто - добавить памяти на удалённый сервер, то я бы не парился с кодом.
  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz Янв. 2, 2011, 1:59 п.п., спустя 4 минуты 23 секунды

    если известна структура или док юзает схему то распарсить вручную вообще не проблема
    не всё полезно, что в swap полезло
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz Янв. 2, 2011, 4:40 п.п., спустя 2 часа 41 минуту 32 секунды

    конечная цель какая? надо импортировать файл в другое представление или просто показать преподу: "вот XML в виде неебического дерева"  )))

    когда файл гарантированно валидный, то его реально разобрать и конвертировать в самом скромном окружении - независимо от размера. будут расти только времязатраты. я бы комбинировал регулярки и код на php.
    ιιlllιlllι унц-унц
  • AlexB

    Сообщения: 4306 Репутация: N Группа: в ухо

    Spritz Янв. 2, 2011, 8:13 п.п., спустя 3 часа 32 минуты 16 секунд

    А почему не рассматривается простое увеличение количества памяти, через memory_limit? Это было сделано?
    Я аналогичную проблему решал таким образом и весьма успешно. Единственное, организовал очередь, следующий парсер не запускался пока не закончит работу предыдущей.
    Так что тут важна природа этого XML, откуда он берется, как часто парсится?
    Спустя 116 сек.

    Sineokov, возможно придётся делать свой парсер…
    Какой свой парсер для XML? С какого свой парсер сможет то, что не смогли отлаженные годами парсеры?

Пожалуйста, авторизуйтесь, чтобы написать комментарий!