[ Сообщений: 37 ] 
Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3  След.
Автор Сообщение
СообщениеДобавлено: 11 дек 2012, 15:00 
Эксперт
Аватара пользователя

Сообщения: 276
Поблагодарили: 16 раз.
Неплохой мануал на русском по XMLReader

_________________
видеорецепты

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 11 дек 2012, 16:04 
Аватара пользователя

Сообщения: 30
Поблагодарили: 3 раз.
Пробовали как раз XMLReader вчера, XML целиком пытались взять. Но, во-первых, он работал достаточно медленно, во-вторых, что странно, все равно слопал выделенную память.

Кто-нибудь именно с ним работал на практике? может где-то очищать надо память по ходу парсинга или, возможно, есть какие-то узкие места в использовании функций класса.. Например, если $reader->read() часто сильно используется? Кто подскажет?

Кстати, а может из-за БД такое быть... Соединение открыто постоянно и с каждым запросом по идее ресурс какой-то кушается..

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 11 дек 2012, 17:19 
Эксперт
Аватара пользователя

Сообщения: 276
Поблагодарили: 16 раз.
ptutkin писал(а):
Кто-нибудь именно с ним работал на практике?

Уж года 2 как в работе. Бодро читает здоровенный XML, при этом не жрёт память, как это было с simplexml.
Ничего не надо чистить. Может быть ваш скрипт загоняет в оперативную память считываемые данные и что-то там с ними делает, тогда естественно, что память будет расходоваться.
Попробуйте XMLReader-ом распарсить "вхолостую" большой xml, без баз и каких-либо обработок. В двух словах, напишите элементарный скрипт и прогоните прайс.
А может вовсе проблема не в парсерах XML? В общем, пишите скрипт с чистого листа и тестируйте.

_________________
видеорецепты

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 11 дек 2012, 17:23 
Эксперт
Аватара пользователя

Сообщения: 235
Поблагодарили: 17 раз.
ptutkin, попробуйте произвести парсинг и при этом не вставлять данные в БД. Память съедается?

Добавлено спустя 5 часов 25 минут 13 секунд:
В общем попробовал, XMLReader работает очень не плохо.
Вот пример кода, где достаются некоторые элементы из прайса:

Код:
<?php
$reader = new XMLReader();
$reader->open("file.xml");

while (@$reader->read()) {

switch ($reader->nodeType) {
   case (XMLREADER::ELEMENT):
   
     if (strtolower($reader->localName) == "offers") {
   
           while (@$reader->read())
         {
         
              if ($reader->nodeType == XMLREADER::ELEMENT)
              {
                 if (strtolower($reader->localName) == "offer")
                 echo $reader->getAttribute("id").' <br />';
                 
               switch (strtolower($reader->localName))
               {
                     case "url":                  
                     $reader->read();
                  echo $reader->value.'<br />';
                  break;
                  
                     case "price":                  
                     $reader->read();
                  echo $reader->value.'<br />';
                  break;
                  
                  case "picture":                  
                     $reader->read();
                  echo $reader->value.'<br />';
                  break;                                    
                  
               }
               
               
              }
           }
         
      
     }
}


?>

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 11 дек 2012, 22:54 
Аватара пользователя

Сообщения: 30
Поблагодарили: 3 раз.
Убрал все, что связано с запросами, в том числе и подключение. все запросы.. оставил только проход по тегам + получение данных, но никуда они не идут, естественно..

Так вот.. по выводу memory_get_usage все ок - на месте топчется (хотя так и с запросами было)
А вот если просматривать через htop, то процесс жрет и причем достаточно активно.

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

Может кусок кода подготовить именно как по тегам прохожу и показать? может даст пищу для размышления? :)

Спасибо за помощь :)

Добавлено спустя 7 минут 23 секунды:
Вот использование парсера:

Код:
<?php
ini_set('memory_limit', '12000M');
set_time_limit(0);
error_reporting(E_ALL);

$reader = new XMLReader();
$reader->open($fileXml);

while ($reader->read()) {
  switch ($reader->nodeType) {
    case (XMLREADER::ELEMENT):     
      if ($reader->localName == "shop") {

        $shopId = $reader->getAttribute("id");
       
        echo "<br>\n";
        echo "================ ShopId: ".$shopId." ====== Memory: ".memory_get_usage()."========= <br>\n";
        echo "<br>\n";
       
        while ($reader->read()) {         
          if ($reader->nodeType == XMLREADER::ELEMENT) {
            switch ($reader->localName) {
              case 'url':
                while ($reader->read()) {
                  if ($reader->nodeType == XMLREADER::END_ELEMENT && $reader->localName == "url") {
                    break;
                  }
                }
              break;
             
              case 'name':
                $reader->read();
                $shopName = $reader->value;
             
              break;
             
              case 'regions_geotarget':
                while ($reader->read()) {                 
                  if ($reader->nodeType == XMLREADER::ELEMENT) {
                    if ($reader->localName == "geotarget") {
                      $geo_id = $reader->getAttribute("id");
                      $geo_pid = $reader->getAttribute("pid");
                      $geo_price_markup = $reader->getAttribute("price_markup");
                    }
                  }
                  elseif ($reader->nodeType == XMLREADER::END_ELEMENT && $reader->localName == "regions_geotarget") {
                    break;
                  }
                }
              break;
             
              case 'offers':
               
                while ($reader->read()) {
                  if ($reader->nodeType == XMLREADER::ELEMENT) {
                    if ($reader->localName == "offer") {
                      $offerId = $reader->getAttribute("id");
                     
                      while ($reader->read()) {
                        if ($reader->nodeType == XMLREADER::ELEMENT) {
                          switch ($reader->localName) {
                            case 'url':
                              $reader->read();
                              $offer_url = $reader->value;
                              break;
                             
                            case 'price':                             
                              $reader->read();
                              $offer_price = $reader->value;
                              break;
                             
                            case 'currencyId':
                              $reader->read();
                              $offer_currencyId = $reader->value;
                              break;
                             
                            case 'categoryId':
                              $reader->read();
                              $offer_categoryId = $reader->value;
                              break;
                             
                            case 'picture':
                              $offer_pict_w = $reader->getAttribute("w");
                              $offer_pict_h = $reader->getAttribute("h");
                              $reader->read();
                              $offer_picture = $reader->value;
                              break;
                             
                            case 'vendor':
                              $offer_vendor_id = $reader->getAttribute("id");
                              $reader->read();
                              $offer_vendor = $reader->value;
                              break;
                             
                            case 'model':
                              $reader->read();
                              $offer_model = $reader->value;
                              break;
                             
                            case 'description':
                              $reader->read();
                              $offer_desc = $reader->value;
                              break;
                             
                            case 'name':
                              $reader->read();
                              $offer_name = $reader->value;
                              break;
                          }
                        }
                        elseif ($reader->nodeType == XMLREADER::END_ELEMENT && $reader->localName == "offer") {
                          break;
                        }
                      }
                    }
                  }
                  elseif ($reader->nodeType == XMLREADER::END_ELEMENT && $reader->localName == "offers") {
                    break;
                  }
                }
               
                break;
             
              case 'categories':
                while ($reader->read()) {                 
                  if ($reader->nodeType == XMLREADER::ELEMENT) {
                    if ($reader->localName == "category") {
                      $catId = $reader->getAttribute("id");
                      $parentId = $reader->getAttribute("parentId");
                      $reader->read();
                      $catName = $reader->value;
                    }
                  }
                  elseif ($reader->nodeType == XMLREADER::END_ELEMENT && $reader->localName == "categories") {
                    break;
                  }
                }
                               
                break;
             
            }
          }
          elseif ($reader->nodeType == XMLREADER::END_ELEMENT && $reader->localName == "shop") {
            break;
          }
        }
       
      }
    }
}
echo "!!! DONE !!!\n";

?>


Добавлено спустя 3 минуты 12 секунд:
И вот вывод (чисто для примера):

Код:
================ ShopId: 289 ====== Memory: 263272========= <br>
<br>
<br>
================ ShopId: 637 ====== Memory: 266848========= <br>
<br>
<br>
================ ShopId: 721 ====== Memory: 268912========= <br>
<br>
<br>
================ ShopId: 724 ====== Memory: 266624========= <br>
<br>
<br>
================ ShopId: 835 ====== Memory: 266616========= <br>
<br>
<br>
================ ShopId: 967 ====== Memory: 266680========= <br>
<br>
<br>
================ ShopId: 2003 ====== Memory: 266760========= <br>
<br>
<br>
================ ShopId: 2898 ====== Memory: 266848========= <br>
<br>
<br>
================ ShopId: 3551 ====== Memory: 266760========= <br>


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 дек 2012, 09:34 
Эксперт
Аватара пользователя

Сообщения: 235
Поблагодарили: 17 раз.
А какие показания Load average перед и в момент парсинга демонстрирует htop?

ini_set('memory_limit', '12000M'); // это слишком круто
ini_set('memory_limit', '128M'); // так лучше

Можно попробовать открыть поток так:
$reader->open($fileXml, NULL, LIBXML_COMPACT);

LIBXML_COMPACT (integer) - активирует оптимизацию выделения памяти для небольших узлов. Это может повысить быстродействие приложения без внесения изменений в коде.
Замечание:
Доступно только в Libxml >= 2.6.21

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 дек 2012, 12:59 
Аватара пользователя

Сообщения: 30
Поблагодарили: 3 раз.
До запуска показывает:
Load average: 0.60 0.51 0.50

После старта (кстати memory_limit стоял 300М):
Load average: 1.17 0.65 0.55
Load average: 1.25 0.71 0.57
Load average: 1.45 0.79 0.60

Сейчас поставил те параметры, что вы советовали:

до запуска:
Load average: 0.83 0.81 0.64

после:
Load average: 1.20 0.90 0.68
Load average: 1.41 1.00 0.72
и т.д.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 дек 2012, 13:12 
Эксперт
Аватара пользователя

Сообщения: 235
Поблагодарили: 17 раз.
ptutkin, показатели вполне нормальные для такого процесса. Но будем думать как его оптимизировать )

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 дек 2012, 13:46 
Аватара пользователя

Сообщения: 30
Поблагодарили: 3 раз.
Самое интересное, что убирал из кода все практически, оставляя только проход по нодам:
while ($reader->read()){}
и особо ничего не поменялось

в htop каждую секунду RES (правильно ли я понимаю, что именно этот параметр надо смотреть, т.е. использование оперативки?) растет на 20-30Mb.. Может с php что? или с XMLReader :)

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 дек 2012, 14:02 
Эксперт
Аватара пользователя

Сообщения: 235
Поблагодарили: 17 раз.
В любом случае скрипт не съест больше оперативки, чем выделено под него в memory_limit. И если весь прайс парсится без ошибок, думаю цель достигнута. Главное чтобы не очень долго )

Я обычно CPU% смотрю

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 дек 2012, 14:10 
Аватара пользователя

Сообщения: 30
Поблагодарили: 3 раз.
меня удивляет как раз вот что..
в скрипте: ini_set('memory_limit', '128M');

но по RES смотрю - там смело так растет размер памяти, причем выходит за пределы выделенной памяти.. это вообще как? :)

а CPU загружен достаточно сильно.. 97-98%..

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 дек 2012, 16:07 
Аватара пользователя

Сообщения: 59
Поблагодарили: 5 раз.
ptutkin
Я бы рекомендовал не совсем красивый, зато легкий способ.
не нужно весь прайс загонять.
Загоняйте. хоть в SuimpleXML, хоть в TEXT переменную только часть прайса. Часть Вы всегда сможете найти по тегам. Она вырезается легко. И не нужно качать полный прайс и целиком его в переменную кидать. прочитайте часть fread() определенной динны. Сравните - попала ли нужная часть туда полностью или нет. попала - вырежьте ее, а остаток прицепить к следующей итерации. С вырезанной частью уже работайте чем хотите.
Единственно, в первых постах было праильно написано, в базу сразу загонять не стоит, а загоняйте в файл данных для вставки, а потом уже вставляйте.
Я так делаю, все пашет быстро, даже на слабых машинах.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 дек 2012, 19:07 
Эксперт
Аватара пользователя

Сообщения: 276
Поблагодарили: 16 раз.
ptutkin писал(а):
меня удивляет как раз вот что..
в скрипте: ini_set('memory_limit', '128M');

но по RES смотрю - там смело так растет размер памяти, причем выходит за пределы выделенной памяти.. это вообще как?


может ini_set отключено в конфигурации php?

если не хватает памяти, должен был вылететь с подобным сообщением
Цитата:
Allowed memory size of 33554432 bytes exhausted (tried to allocate 43148176 bytes)

_________________
видеорецепты

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 дек 2012, 23:35 
Аватара пользователя

Сообщения: 30
Поблагодарили: 3 раз.
Всем спасибо большое за помощь, с утечкой памяти разобрались :) Оказалось, был включен xdebug.

Осталось выяснить со скоростью. Сориентируйте, пожалуйста, в вашем понимании "быстро" это сколько реально по времени должно уходить на парсинг 1,3 Гб? я понимаю, все зависит и от железа в том числе, но хотя бы приблизительно.

Напомню, на всякий случай, наши характеристики сервера:

CPU AMD Opteron 3280 Octacore
Barebone Fujitsu PRIMERGY MX130 S2
RAM 16x Gigabyte RAM

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 13 дек 2012, 00:01 
Эксперт
Аватара пользователя

Сообщения: 276
Поблагодарили: 16 раз.
ptutkin писал(а):
Сориентируйте, пожалуйста, в вашем понимании "быстро" это сколько реально по времени должно уходить на парсинг 1,3 Гб

Чисто на парсинг должно уходить мало от минуты до нескольких, то есть только чтобы прочитать.
Сервер, двухпроцессорная многоядерная система на базе интел, память 16Гб, точный конфиг сейчас не скажу. На апдейт сайта с товарами уходит 25 минут, включая загрузку, распаковку, апдейт базы, переиндексацию сфинкса. Более 2-х миллионов товаров. Файл 1.2Гб. Может быть и можно оптимизировать (конечно можно, нет предела совершенству!) и выйти минут на 10-15 я думаю, но это в лучшем случае :) Апдейт на работу сайта не влияет и идет фоном, разумеется ночью, так что все терпимо.

_________________
видеорецепты

Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3  След.
 [ Сообщений: 37 ] 

   Похожие темы   Ответы   Автор   Просмотры   Последнее сообщение 
В этой теме нет новых непрочитанных сообщений. Надпись "реклама" над блоками товаров

[ На страницу: 1, 2 ]

в форуме Микс-Товары

17

mariaonline

12486

31 окт 2014, 08:50

Odaria Перейти к последнему сообщению

В этой теме нет новых непрочитанных сообщений. Не могу настроить блок "Контекстных товаров" (2448

в форуме Микс-Товары

6

moreinfo

12208

01 мар 2010, 13:40

mager Перейти к последнему сообщению

В этой теме нет новых непрочитанных сообщений. Нужны более гибкие настройки шаблонов «Контекстных товаров»

в форуме Микс-Товары

3

BOOTKiller

11728

12 май 2006, 15:42

ivanov Перейти к последнему сообщению

В этой теме нет новых непрочитанных сообщений. Обновлен способ вывода денег из Микс-Товаров

в форуме Миксмаркет в развитии

10

ivanov

17812

08 июл 2008, 19:55

ivanov Перейти к последнему сообщению

В этой теме нет новых непрочитанных сообщений. Яндекс.Маркет сделал API для доступа к карточкам товаров

в форуме Микс-Товары

8

mgarkunov

17453

30 май 2012, 14:00

Евгений Перейти к последнему сообщению



Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения
cron


О проекте Новости Пресса о нас Сотрудничество Вакансии Контакты
2005–2011 Партнерская сеть Миксмаркет
Разработка сайта — iji-design / AdLabs
Powered by phpBB Group