Возникла простейшая задача: импортировать каталог из 1С 7.7. "Конфигурация базовая" обрадовался я, да не тут-то было.
Как оказалось у товаров по 25 свойств и по 5 типов цен. В результате, файл с 5 000 товаров занял 10 Мб. В принципе - немного.
Запустил импорт CommerceML MySql Fast - BETA VERS на Таймвебовском Eterno[b] и ушёл пить кофе. Вернувшись, обнаружил 502 ошибку, перенапрягся сервер.
Перенес бэкап сайта на локальную машину с двухъядерным процессором 2.2 Ghz и 4 гигами памяти и, о чудо, за 59 секунд файл был скормлен в Битрикс. Вот тут-то и возникла мысль об оптимизации файла commerceml_g_run.php
[spoiler]
Открыл файл и, о чудо снова, функции cmlStartElement() и cmlEndElement() заточены под использование , но почему-то используется кастомный парсер с применением таких "черепах" как preg_replace() и preg_match_all().
В итоге, пришлось внести следующие изменения в код.
1) Удаляем код:
2) Вместо кода
вставляем
Модернизация кода закончена.
В итоге - скрипт ускоряется в разы (у меня ускорился ~ в 50 раз)
Импорт, который ранее "нагибал" сервер хостера, прошел за 20 секунд.
Есть куда копать?
Как оказалось у товаров по 25 свойств и по 5 типов цен. В результате, файл с 5 000 товаров занял 10 Мб. В принципе - немного.
Запустил импорт CommerceML MySql Fast - BETA VERS на Таймвебовском Eterno[b] и ушёл пить кофе. Вернувшись, обнаружил 502 ошибку, перенапрягся сервер.
Перенес бэкап сайта на локальную машину с двухъядерным процессором 2.2 Ghz и 4 гигами памяти и, о чудо, за 59 секунд файл был скормлен в Битрикс. Вот тут-то и возникла мысль об оптимизации файла commerceml_g_run.php
[spoiler]
Открыл файл и, о чудо снова, функции cmlStartElement() и cmlEndElement() заточены под использование , но почему-то используется кастомный парсер с применением таких "черепах" как preg_replace() и preg_match_all().
В итоге, пришлось внести следующие изменения в код.
1) Удаляем код:
if ($pe = strpos($xmlData, ">"))
{
$headerString = substr($xmlData, 0, $pe);
if(preg_match('#encoding[\s]*=[\s]*"(.*?)"#i', $headerString, $arMatch))
{
$xmlData = $GLOBALS["APPLICATION"]->ConvertCharset($xmlData, $arMatch[1], LANG_CHARSET);
}
} |
2) Вместо кода
$search = array(
"'&(quot|#34);'i",
"'&(amp|#38);'i",
"'&(lt|#60);'i",
"'&(gt|#62);'i",
"'&#(\d+);'e"
);
$replace = array(
"\"",
"&",
"<",
">",
"chr(\\1)"
);
$pb = strpos($xmlData, "<");
while ($pb !== false)
{
$pe = strpos($xmlData, ">", $pb);
if($pe === false)
break;
$tag_cont = substr($xmlData, $pb+1, $pe-$pb-1);
$pb = strpos($xmlData, "<", $pe);
$check_str = substr($tag_cont, 0, 1);
if($check_str=="?")
continue;
elseif($check_str=="!")
continue;
elseif($check_str=="/")
cmlEndElement(false, substr($tag_cont, 1));
else
{
$p = 0;
$ltag_cont = strlen($tag_cont);
while(($p < $ltag_cont) && (strpos(" \t\n\r", substr($tag_cont, $p, 1))===false))
$p++;
$name = substr($tag_cont, 0, $p);
$at = substr($tag_cont, $p);
if (strpos($at, "&")!==false)
$bAmp = true;
else
$bAmp = false;
preg_match_all("/(\\S+)\\s*=\\s*[\"](.*?)[\"]/s".BX_UTF_PCRE_MODIFIER, $at, $attrs_tmp);
$attrs = Array();
for ($i=0; $i<count($attrs_tmp[1]); $i++)
$attrs[$attrs_tmp[1][$i]] = ($bAmp ? preg_replace($search, $replace, $attrs_tmp[2][$i]) : $attrs_tmp[2][$i]);
cmlStartElement(false, $name, $attrs);
if(substr($tag_cont, -1) === "/")
cmlEndElement(false, $name);
}
}
$xmlData = ""; |
вставляем
$XMLparser = xml_parser_create();
xml_set_element_handler($XMLparser, 'cmlStartElement', 'cmlEndElement');
if (!xml_parse($XMLparser, $xmlData)) {
echo xml_error_string(xml_get_error_code());
die('Ошибка');
}
xml_parser_free($XMLparser); |
Модернизация кода закончена.
В итоге - скрипт ускоряется в разы (у меня ускорился ~ в 50 раз)
Импорт, который ранее "нагибал" сервер хостера, прошел за 20 секунд.
Есть куда копать?
