Возникла простейшая задача: импортировать каталог из 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() заточены под использованиеXML Parser , но почему-то используется кастомный парсер с применением таких "черепах" как 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() заточены под использование
В итоге, пришлось внести следующие изменения в код.
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 секунд.
Есть куда копать?