Перейти к содержимому


Ускоряем работу клиентской части ShopCMS при большом количестве товаров и категорий


  • Вы не можете ответить в тему
Сообщений в теме: 42

#1 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 20 January 2016 - 03:37 PM

Ускоряем работу клиентской части ShopCMS
с большим количеством каталогов (порядка тысячи и более),
большим количеством товаров (десятки тысяч и более)
и большим количеством зарегистрированных клиентов (порядка нескольких тысяч и более).

Количество категорий и товаров можно посмотреть в "Админка->Отчеты->Системные данные".
Количество зарегистрированных клиентов в "Админка->Списки->Покупатели",
там умножить число строк (обычно это 20) на число страниц.


Программная часть (скорость выполнения PHP-кода)
================================================

При тысяче (и более) категорий основное время PHP-вычислений занимает построение иерархического списка категорий, который мы видим в блоке "Развернутый каталог" и на странице "Расширенный поиск".
При каждой перезагрузке страницы таблица категорий заново получается SQL-запросом из базы и на нее напускается рекурсивная функция построения списка, которая (при тысяче категорий/подкатегорий) работает долго.
Но зачем каждый раз заново строить список категорий в клиентской части, если изменяется этот список только в админке? Куда правильнее сохранить этот список готовым в файл и брать его каждый раз оттуда, меняя этот файл только из админки.
Примерно так и сделано.
В клиентской части: если файлов с таблицей категорий и построенным списком нет, то все происходит штатным путем (медленно), а таблица категорий и построенный список сохраняются в файлы. Т.е. на следующей странице они будут взяты уже из файлов (быстро).
В админской части: если произошли изменения в таблице категорий, то файлы удаляются и - см.выше.
Можно прямо в админке их и создать заново, но особого смысла я не вижу. Просто у первого клиента после изменений в категориях медленнее загрузится первая страница.
Второй список категорий (для "не развернутого" каталога) не трогался, т.к. строится линейно и быстро.


1. в файле category_functions.php

1.1. в функции catGetCategoryCListMin

вместо


return _recursiveGetCategoryCList( 1, 0, null, 'NUM', false, false);


вставляем


# BEGIN кэшируем в файл клиентский список категорий
#return _recursiveGetCategoryCList( 1, 0, null, 'NUM', false, false);
if (file_exists("core/temp/catcache.txt") && ($cache = file_get_contents("core/temp/catcache.txt")) && $cats = unserialize($cache)) return $cats;
else
{
$cats = _recursiveGetCategoryCList( 1, 0, null, 'NUM', false, false);
file_put_contents("core/temp/catcache.txt",serialize($cats));
return $cats;
}
# END кэшируем в файл клиентский список категорий


1.2. в функции update_psCount в начало вставляем


# BEGIN кэшируем в файл клиентский список категорий
if (file_exists("core/temp/catcache.txt")) unlink("core/temp/catcache.txt");
if (file_exists("core/temp/categories.txt")) unlink("core/temp/categories.txt");
# END кэшируем в файл клиентский список категорий



2. в файле index.php

2.1. перед


$q = db_query("select categoryID, name, products_count, products_count_admin, parent, picture, subcount FROM ".CATEGORIES_TABLE." ORDER BY sort_order, name");


вставляем


# BEGIN кэшируем в файл клиентский список категорий
if (file_exists("core/temp/categories.txt") && ($cache = file_get_contents("core/temp/categories.txt")) && $categories = unserialize($cache))
{
foreach ($categories as $row)
{
$fc[(int)$row["categoryID"]] = $row;
$mc[(int)$row["categoryID"]] = (int)$row["parent"];
}
}
else
{
$categories = array();
# END кэшируем в файл клиентский список категорий


2.2. после


$mc[(int)$row["categoryID"]] = (int)$row["parent"];


вставляем


# BEGIN кэшируем в файл клиентский список категорий
$categories[] = $row;
}
file_put_contents("core/temp/categories.txt",serialize($categories));
# END кэшируем в файл клиентский список категорий




SQL-часть (скорость выполнения запросов)
========================================

У таблиц категорий, товаров и клиентов довольно небольшой список используемых вариантов сортировки и полей для поиска.
Достаточно добавить несколько индексов, чтобы на удивление сильно увеличить скорость выполнения некоторых тормозных запросов.

создаем файл addon.php с содержимым


<?php
db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD INDEX date_added(date_added)"); // home.php - новинки
db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD INDEX items_sold(items_sold)"); // home.php - популярные

db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD INDEX sort_order_name(sort_order,name)"); // стандартная сортировка товара
db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD INDEX price(Price)"); // сортировка по цене товара
db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD INDEX enabled(enabled)"); // включенные-отключенные товары
db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD INDEX name(name)"); // сортировка по названию товара

db_query("ALTER TABLE ".CATEGORIES_TABLE." ADD INDEX sort_order_name(sort_order,name)"); // стандартная сортировка категорий

db_query("ALTER TABLE ".CUSTOMERS_TABLE." ADD INDEX login(Login)"); // для WHERE Login=

unlink("core/includes/admin/addon.php");
?>


Кладем его в core/includes/admin/ и заходим в админку либо перезагружаем страницу, если уже в админке.
Файл добавит индексы и должен удалиться сам, но лучше проверить (мне попадались сайты, где удаление файлов в этом каталоге было запрещено).


В общем случае я искал тормозные запросы следующим образом:

В файле mysql.php в функции db_query

строку


$res["resource"] = mysql_query($s);


заменил на


if (isset($_GET['speedtest'])) global $relaccess;list($usec, $sec) = explode(" ", microtime());$start = (float)$usec + (float)$sec;
$res["resource"] = mysql_query($s);
if (isset($_GET['speedtest'])) if (in_array(100, $relaccess)) {list($usec1, $sec1) = explode(" ", microtime());$f=fopen('sql.txt','a');fwrite($f,round((float)$usec1+(float)$sec1-$start,5)."/".$s."\n");fclose($f);}


При этом если находишься под админом и добавляешь в url строку с GET-переменной speedtest=1 (например, http://badisoft.ru/?speedtest=1), то в корне сайта создастся (либо будет дополняться, если уже есть) файл sql.txt примерно с таким содержимым:

0.00021/select code, currency_value, where2show, currency_iso_3, Name, roundval from emph_currency_types where CID=3
0.0002/select CID, Name, code, currency_value, where2show, roundval, currency_iso_3 from emph_currency_types order by sort_order
0.01132/select categoryID, name, products_count, products_count_admin, parent, picture, subcount FROM emph_categories ORDER BY sort_order, name
0.00056/select bid, title, content, bposition, which, sort, html, url, admin, pages, dpages, categories, products FROM emph_blocks WHERE active=1 ORDER BY sort ASC
0.00021/select count(*) from emph_categories where categoryID=1
0.0002/select categoryID, parent, name FROM emph_categories WHERE categoryID=1
0.00051/select categoryID, parent, name, products_count from emph_categories where parent=1  order by sort_order, name
0.00023/select last_update from emph_dump where type=1
0.00022/select today from emph_counter WHERE tbid=1
0.05832/replace into emph_online values ('97ca250a247dba98302e15d5f127644a', '1453217907')
0.0584/UPDATE emph_counter SET todayp=todayp+0, todayv=todayv+1, allp=allp+0, allv=allv+1, allieb=allieb+0, allmozb=allmozb+1, allopb=allopb+0, allozb=allozb+0, allrusl=allrusl+1, allenl=allenl+0, allozl=allozl+0, allwins=allwins+1, alllins=alllins+0, allmacs=allmacs+0, allozs=allozs+0 WHERE tbid=1
0.00096/select count(*) from emph_online WHERE time > 1453217307
0.00023/select todayp, todayv, allp, allv from emph_counter WHERE tbid=1
0.00019/select poll_id, poll_title, poll_ans, all_poll FROM emph_survey WHERE active=1
[тут кусок лога вырезан для краткости]
0.00024/select settings_value from emph_settings where settings_constant_name='CONF_DATE_FORMAT'
0.00025/select settings_value from emph_settings where settings_constant_name='CONF_DATE_FORMAT'
0.00701/select customerID from emph_customers where Login='admin'
0.00021/select itemID, Quantity FROM emph_shopping_carts WHERE customerID=1
0.0003/select orderID, customerID, order_time, customer_ip,  shipping_type, payment_type, customers_comment,  statusID, shipping_cost, order_discount, order_amount,  currency_code, currency_value, customer_firstname, customer_lastname,  customer_email, shipping_firstname, shipping_lastname,  shipping_country, shipping_state, shipping_city,  shipping_address, billing_firstname, billing_lastname, billing_country,  billing_state, billing_city, billing_address,  cc_number, cc_holdername, cc_expires, cc_cvv, affiliateID, shippingServiceInfo, currency_round  from emph_orders where orderID=0
0.00018/select AID, uri, update_date, title, textToPrePublication, bid from emph_articles order by ordering,update_date DESC,AID DESC
0.00025/select settings_value from emph_settings where settings_constant_name='CONF_DATE_FORMAT'

Что мы видим? Видим кучу запросов по 0.000xx секунд и четыре явно медленных запроса 0.01132, 0.05832, 0.0584, 0.00701.
Первый решается индексом этой таблицы (категорий) по sort_order+name.
Второй и третий - это запросы малюсеньких таблиц (в третьм таблица вообще в одну запись), но с изменением содержимого таблиц, тут был не лучшим образом настроен SQL-сервер.
Четвертый решается индексом этой таблицы (клиентов) по Login.

Вот таким не особенно сложным способом скорость работы сайта была улучшена с

Обработка данных: 0.350 сек
Работа с БД: 0.260 сек
Общее время работы: 0.665 сек

до

Обработка данных: 0.041 сек
Работа с БД: 0.011 сек
Общее время работы: 0.056 сек

PS. В процессе улучшений случился также и переезд на другое железо, но, как ни странно, особого прироста производительности это не дало. Хотя "стало в два раза быстрее" - это тоже хорошо.
Наибольший прирост общей скорости работы дали:
1. кэширование на диск списка категорий.
2. настройка MySQL-сервера. Исходно ооочень медленно, на порядок-два хуже SELECT-ов выполнялись запросы, меняющие содержимое таблиц - UPDATE, REPLACE, INSERТ. Что-то связанное с кэшированием изменений и сбросом их на диск. Делал не я. Я в настройках MySQL-сервера ничего не понимаю. Видимо, какая-то специфика развернутого сервера, т.к. у меня все MySQL-сервера стоят с настройками практически по дефолту, но такой разницы между SELECT-ом и UPDATE-ом нет.
3. создание индексов по часто используемым полям у объемных таблиц (категории, товары, клиенты).


PPS. Обязательно надо мониторить в админке раздел "Статистика ошибок" и следить, чтобы там не было записей.
Особенно если в лог валятся не только ошибки, но и warning по несоответствию типа данных, чего даже в штатном shopCMS "из коробки" довольно много.
При появлении error или warning происходит:
1. вставка сообщения в таблицу (INSERT)
2. подсчет записей в таблице (SELECT)
3. усечение таблицы, если записей больше пятидесяти (DELETE)
т.е. при периодическом warning, который никак не влияет на работоспособность сайта мы получим три лишних SQL-запроса по каждому warning, причем два из них могут оказаться не быстрыми.

Некоторый (довольно небольшой) прирост даст убивание сбора статистики по клиентам (файл counter.php, но осторожно, там еще и ежесуточная чистка таблицы сессий).
Просто станет на пять SQL-запросов меньше.
Статистика там все равно довольно бессмысленная (браузеры - IE/FF/Opera/Other, ОС - Win/Lin/Mac/Other, Языки - Ru/En/Other).
Новых браузеров нет, новых ОС нет.
Статистика Яндекса или Гугля (а обычно у сайта есть обе) покажут то же самое намного лучше и развесистей.
  • 7
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#2 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 20 January 2016 - 08:36 PM

Еще одно небольшое ускорение за счет сокращения числа SQL-запросов.
В рамках вышеописанного сайта снизил затраты времени на запросы с ~0.015сек до ~0.010сек.
В логе десяток запросов константы 'CONF_DATE_FORMAT' видите?
А, да, я же сократил лог и осталось только три. Поверьте, их там с десяток.
А зачем константу запрашивать десять раз при загрузке одной страницы, если можно сохранить запрошенную константу в массив и при повторном запросе отдавать ее из массива?


function _getSettingOptionValue( $settings_constant_name )
{
# BEGIN оптимизируем SQL-запросы
global $conf_data;
if (isset($conf_data[$settings_constant_name])) return $conf_data[$settings_constant_name];
# END оптимизируем SQL-запросы
$q = db_query("select settings_value from ".SETTINGS_TABLE.
" where settings_constant_name='".xEscSQL($settings_constant_name)."'" );
# BEGIN оптимизируем SQL-запросы
# if ( $row = db_fetch_row( $q ) ) return $row["settings_value"];
if ( $row = db_fetch_row( $q ) )
{
$conf_data[$settings_constant_name] = $row["settings_value"];
return $row["settings_value"];
}
# END оптимизируем SQL-запросы
return null;
}


PS. Я бы еще и переназначение механизма сессий на хранение в SQL-базе убрал, т.к. там нет НИЧЕГО отличного от обычного штатного механизма кроме того, что "сборка мусора" (функция sess_sg) удаляет устаревшие сессии исходя из заданных часов жизни сессии в "Общих настройках" (сколько помнить юзера), а не из PHP-настройки session.gc_maxlifetime (1440сек=24мин по дефолту), которую можно менять используя функцию ini_set() или задавая в .htaccess.

На тестовом сайте убрал это переназначение (закомментировал в admin.php и index.php строку с функцией session_set_save_handler) и никакой разницы не заметил. Ну да, стала сессия сохраняться не заданные 2 часа, а явно меньше. Но я session.gc_maxlifetime и не менял. А SQL-запросов стало еще меньше.
  • 1
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#3 Salp

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 218 сообщений
Репутация: 54
Продвинутый

Отправлено 22 January 2016 - 12:26 PM

Огромное спасибо за проделанную работу. В свое время много времени потратил на оптимизацию настроек SQL и Apache сервера для домашнего хостинга именно под работу с ShopCMS. Уже многое забылось и сервера уже нет. Но бэкапы настроек остались и, при желании, можно все вспомнить. Это действительно важно и увеличение скорости загрузки страниц на домашнем сервере за год привело к трехкратному росту посещаемости сайта. После переноса сайта на дешевый хостинг, посещаемость снова упала.
  • 0

#4 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 22 January 2016 - 01:15 PM

Довольно полезна в борьбе за скорость загрузки (точнее, за общую оптимизацию сайта) вот эта ссылка:
https://developers.g...lub&tab=desktop
Правда, не все рекомендации на ShopCMS возмоэно выполнить.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#5 Revived

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 59 сообщений
Репутация: 0
Начинающий

Отправлено 22 January 2016 - 01:38 PM

?speedtest=1
Говорит нет такой страницы
  • 0

#6 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 22 January 2016 - 02:31 PM

?speedtest=1 Говорит нет такой страницы

Видимо, в строке УЖЕ есть GET-переменные. Перед первой ставится ?, перед последующими &.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#7 Revived

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 59 сообщений
Репутация: 0
Начинающий

Отправлено 22 January 2016 - 10:06 PM

А можно это как-то узнать, адресная строка пустая.
  • 0

#8 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 23 January 2016 - 01:58 AM

А можно это как-то узнать, адресная строка пустая.

Слэш уберите. Ссылка должна быть вида www.example.ru?speedtest=1
У меня и со слэшом работает, но у меня и не апач.
Забыл совсем про некое (дурацкое?) правило в .htaccess от ShopCMS.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#9 Revived

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 59 сообщений
Репутация: 0
Начинающий

Отправлено 23 January 2016 - 04:56 PM

Слэш автоматом подставляется, но да ладно. Я убрал условия и создал фаил. Но это как-то не удобно. А вообще производительность увеличилась в двое. Спасибо. А самым тяжелым местом на данный момент есть развесистый фильтр.
  • 0

#10 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 23 January 2016 - 05:18 PM

Я убрал условия и создал фаил. Но это как-то не удобно.

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

А самым тяжелым местом на данный момент есть развесистый фильтр.

Развесистый фильтр писался мной года три-четыре назад, когда я еще очень многого не знал. По части работы с большой базой его запросы ОЧЕНЬ не оптимальны. Он (как и shopCMS) писался еще без понимания, что бывают базы на 100500 товаров. Но оптимизировать его запросы "из спортивного интереса" смысла не вижу, т.к. есть мой же AJAX-фильтр, который намного интереснее.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#11 Salp

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 218 сообщений
Репутация: 54
Продвинутый

Отправлено 23 January 2016 - 06:04 PM

А зачем кешировать список категорий в файл, а не в базу?
  • 0

#12 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 24 January 2016 - 12:05 PM

А зачем кешировать список категорий в файл, а не в базу?

Банально быстрее. "База" это в конечном итоге тоже файл, только прослойка интерфейсов до него куда толще. А данные из небольшого файла будут браться даже не с диска, а из дискового кэша, т.е. очень быстро.

Встречный вопрос: а зачем вообще нечто "одинаковое для всех" сохранять в базу? Работа с базой в общем случае удобнее, но медленнее, чем с файловой системой.
Я же уже писал, что, на мой взгляд, и штатный перенос хранения сессий в sql-таблицу нахрен не нужен и сделан исходя из традиции. Ни в одной session-функции, заменяющей штатную не добавлено какой-либо дополнительной обработки сессий. Только в counter.php раз в сутки происходит "чистка мусора" (удаление сессий прошлых суток), но это не особенно и надо, они и так удалятся.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#13 Salp

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 218 сообщений
Репутация: 54
Продвинутый

Отправлено 25 January 2016 - 10:31 AM

Нашел на главной странице больше полтысячи быстрых запросов от ЧПУ модуля.
Они быстрые, но их очень много (((
9.0E-5/SELECT cpu FROM cguy_cpu WHERE type=2 AND ID=2 LIMIT 1
6.0E-5/SELECT cpu FROM cguy_cpu WHERE type=2 AND ID=4 LIMIT 1
6.0E-5/SELECT cpu FROM cguy_cpu WHERE type=2 AND ID=2 LIMIT 1
5.0E-5/SELECT cpu FROM cguy_cpu WHERE type=2 AND ID=4 LIMIT 1
0.0001/SELECT cpu FROM cguy_cpu WHERE type=3 AND ID=61 LIMIT 1
6.0E-5/SELECT cpu FROM cguy_cpu WHERE type=3 AND ID=60 LIMIT 1

  • 0

#14 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 25 January 2016 - 01:50 PM

Нашел на главной странице больше полтысячи быстрых запросов от ЧПУ модуля.

Очевидно, на странице больше полутысячи ссылок :).
Ведь запрос ЧПУ-модуля не происходит просто так, а генерится по каждой неоЧПУшенной ссылке, попавшей под маску "это надо оЧПУшить".
Для страницы прайс-листа (без переделки штатного PHP-кода прайс-листа) такая ситуация логична и понятна. Сколько товаров и категорий - столько и запросов. А вот для главной страницы полтысячи сслылок это какой-то перебор.

Если много запросов повторяющихся (т.е. с одним и тем же type и ID), то можно в модуле ЧПУ сделать тот же финт, что и с запросом сеттингов - при первом запросе лезть в базу и сохранять значение cpu в какой-нибудь global $cpu['type']['ID'], а при последующих запросах проверять существование isset($cpu['type']['ID']) и если true, то отдавать его, а не лезть снова в базу.
Но наличие полутыщи ЧАСТИЧНО ПОВТОРЯЮЩИХСЯ ссылок на главной странице это еще бОльший перебор, чем просто полтыщи ссылок :).
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#15 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 25 January 2016 - 03:35 PM

Еще ускоряем и уменьшаем количество запросов.

1. как-то я в первом описании совсем забыл, а это весьма важно.
В home.php есть как минимум две (для new_products и popular_products) конструкции вида
SELECT бла-бла-бла FROM таблица_товаров LEFT JOIN таблица_картинок ... LIMIT 0,".$cifra
где $cifra это что-то типа восьми. И получается, что надо объединить по JOIN всю таблицу товаров (десятки тысяч) с таблицей картинок, чтобы потом оттуда выбрать восемь нужных строк. Результат будет получен НАМНОГО быстрее, если убрать JOIN из запроса, т.е. оставить запрос только по таблице товаров, а нужные картинки подгрузить отдельными запросами. Да-да, еще восемь запросов, но суммарно эти девять запросов выполнятся быстрее (у меня - на порядок), чем одиночный запрос с JOIN.

А вот special_offers так исправлять вовсе не обязательно, т.к. там запрос по небольшой таблице спецпредложений и JOIN вполне уместен.

2. Все (!) запросы в home.php выполняются ВСЕГДА, вне зависимости от текущей страницы. Хотя спецпредложения выводятся только на главной, а new_products и popular_products - если включены соответствующие блоки.
Имеет смысл перенести эти куски PHP-кода в соответствующие tpl.html-файлы, чтобы код с запросами выполнялся только при использовании этого tpl.html-файла. Код переносится практически один-в-один, надо только $smarty-> заменить на $this-> и обрамить код тэгами {php}{/php}
home.php после этого осталнется пустым и можно его будет удалить.


PS. Думаю, что если копнуть, то конструкция "товары JOIN картинки LIMIT около десятка" найдется еще много где.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#16 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 25 January 2016 - 10:42 PM

Вау! А как безбожно (при относительно большой номенклатуре "характеристик товара" и, главное, использовании этой номенклатуры) тормозит функция GetExtraParametrs! Это что-то!
90% времени выполнения кода.
Похоже, эту функцию надо не как-то модифицировать, а переписывать с нуля.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#17 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 26 January 2016 - 01:56 PM

тормозит функция GetExtraParametrs! Это что-то!

Функция амнистирована, хотя в ней есть довольно любопытный код :).

$_Row; // что это за хрень?
$b=null; // $b нигде далее не используется

А виной диким тормозам был код

$q = mysql_query("show columns from ".PRODUCTS_OPTIONS_SET_TABLE." like 'qty'");
$row = mysql_fetch_row($q);
if(!isset($row[0]))
db_query( "ALTER TABLE ".PRODUCTS_OPTIONS_SET_TABLE." ADD `qty` INT( 11 ) NULL");

который создает поле qty если его еще нет.
Cовершенно непонятно, почему это не выполнено один раз при инсталляции модуля, а зачем-то вставлено в постоянно и очень часто выполняющуюся функцию, да еще и внутрь цикла.
Догадайтесь, что за модуль? Ага-ага, namer-овский "Учет количества товара по дополнительным характеристикам".
Также кроме этой функции (файл product_functions.php) этот код встречается в файлах
cart_functions.php
catalog_products_categories.php
order_functions.php
order_status_functions.php
но там он менее критичен, т.к. это либо админка, либо уже оформление заказа. Закомментировать или удалить тоже полезно, но на быстродействии оно уже мало сказывается, хотя в функциях cartMoveContentFromShoppingCartsToOrderedCarts и ordOrderProcessing оно опять же зачем-то засунуто в цикл.

PS. Проблема актуальна только там, где модуль поставлен по родной инструкции. В моей инструкции (см. тему на форуме) создание полей вынесено в отдельный выполняемый один раз при установке модуля файл.

PPS. Результат (по совокупности применения большинства из вышеописанных правок).
Было (главная страница):
Обработка данных: 1.032 сек
Компиляция шаблона: 0.590 сек
Работа с БД: 0.202 сек
Общее время работы: 1.823 сек
Запросов в БД: 221
Стало:
Обработка данных: 0.067 сек		
Компиляция шаблона: 0.033 сек		
Работа с БД: 0.075 сек		
Общее время работы: 0.174 сек		
Запросов в БД: 69

Особо подчеркну - это вовсе не насыщенный товарами и категориями сайт:
Всего товаров - 438
Всего категорий - 38
так что даже правку home.php и перенос PHP-кода в шаблоны блоков (см. выше) применять не пришлось, это не давало практически никакой прибавки в скорости.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#18 Salp

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 218 сообщений
Репутация: 54
Продвинутый

Отправлено 26 January 2016 - 11:33 PM

Все (!) запросы в home.php выполняются ВСЕГДА, вне зависимости от текущей страницы.

И не только в home.php, это касается всех php файлов в includes, но во многих случаях есть условия по if (isset($_GET[...

имеет смысл перенести эти куски PHP-кода в соответствующие tpl.html-файлы

А если оставить в home.php, но добавить дополнительное условие?
if ($_SERVER['REQUEST_URI'] == '/')

  • 0

#19 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 26 January 2016 - 11:46 PM

И не только в home.php, а практически код из всех php файлов в include.

Это не так. В большинстве файлов из core/include код условен, т.е. в самом начале или почти в начале стоит условие выполнения. Обычно это что-то типа if (isset($_GET['...']). Где-то да, условия нет (например, в файле обработки дискуссий), но это ошибка ShopCMS, а не правильный подход.

А если оставить в home.php, но добавить дополнительное условие?

Несомненно, можно и так. Почему бы нет? Правда, с придумыванием "дополнительного условия" проблема будет (я не шучу). Но получится ровно то же самое, что и перенос в tpl.html, только там оно исполняется (или не исполняется) без дополнительного условия. Зачем выносить за пределы и так условного исполнения код, обрамляя его затем рамками ТОГО ЖЕ САМОГО условного исполнения?
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#20 golftuning

    Пользователь

  • Пользователи
  • PipPip
  • 18 сообщений
Репутация: 0
Начинающий

Отправлено 06 February 2016 - 08:58 PM

Дмитрию огромное спасибо за работу, сайт просто летает теперь.
  • 0