Истрункция как поднять бабла. Тормозит opencart
Тормозит Opencart. Часть 8 | Истрункция как поднять бабла
<?php
class ControllerCommonSeoPro extends Controller {
private function getquery($query) {
$query = $this->db->query("SELECT LOWER(`keyword`) as 'keyword' FROM " . DB_PREFIX . "url_alias WHERE query = '" . $query . "'");
if (!empty($query->row['keyword'])) {
return $query->row['keyword'];
}
}
private function getkeyword($keyword) {
$query = $this->db->query("SELECT `query` FROM " . DB_PREFIX . "url_alias WHERE keyword = '" . $keyword . "'");
if (!empty($query->row['query'])) {
return $query->row['query'];
}
}
public function __construct($registry) {
parent::__construct($registry);
$this->cachedata = $this->cache->get('seo_pro');
if (!$this->cachedata) {
$query = $this->db->query("SELECT LOWER(`keyword`) as 'keyword', `query` FROM " . DB_PREFIX . "url_alias");
$this->cachedata = array();
foreach ($query->rows as $row) {
$this->cachedata['keywords'][$row['keyword']] = $row['query'];
$this->cachedata['queries'][$row['query']] = $row['keyword'];
}
$this->cache->set('seo_pro', $this->cachedata);
}
}
public function index() {
// Add rewrite to url class
if ($this->config->get('config_seo_url')) {
$this->url->addRewrite($this);
} else {
return;
}
// Decode URL
if (!isset($this->request->get['_route_'])) {
$this->validate();
} else {
$route_ = $route = $this->request->get['_route_'];
unset($this->request->get['_route_']);
$parts = explode('/', trim(utf8_strtolower($route), '/'));
list($last_part) = explode('.', array_pop($parts));
array_push($parts, $last_part);
$rows = array();
foreach ($parts as $keyword) {
if ($this->getkeyword($keyword)) {
$rows[] = array('keyword' => $keyword, 'query' => $this->getkeyword($keyword));
}
}
if (count($rows) == sizeof($parts)) {
$queries = array();
foreach ($rows as $row) {
$queries[utf8_strtolower($row['keyword'])] = $row['query'];
}
reset($parts);
foreach ($parts as $part) {
$url = explode('=', $queries[$part], 2);
if ($url[0] == 'category_id') {
if (!isset($this->request->get['path'])) {
$this->request->get['path'] = $url[1];
} else {
$this->request->get['path'] .= '_' . $url[1];
}
} elseif (count($url) > 1) {
$this->request->get[$url[0]] = $url[1];
}
}
} else {
$this->request->get['route'] = 'error/not_found';
}
if (isset($this->request->get['product_id'])) {
$this->request->get['route'] = 'product/product';
if (!isset($this->request->get['path'])) {
$path = $this->getPathByProduct($this->request->get['product_id']);
if ($path) $this->request->get['path'] = $path;
}
} elseif (isset($this->request->get['path'])) {
$this->request->get['route'] = 'product/category';
} elseif (isset($this->request->get['manufacturer_id'])) {
$this->request->get['route'] = 'product/manufacturer/info';
} elseif (isset($this->request->get['information_id'])) {
$this->request->get['route'] = 'information/information';
} elseif ($this->getquery($route_)) {
header($this->request->server['SERVER_PROTOCOL'] . ' 301 Moved Permanently');
$this->response->redirect($this->getquery($route_));
} else {
if (isset($queries[$parts[0]])) {
$this->request->get['route'] = $queries[$parts[0]];
}
}
$this->validate();
if (isset($this->request->get['route'])) {
return $this->forward($this->request->get['route']);
}
}
}
public function rewrite($link) {
if (!$this->config->get('config_seo_url')) return $link;
$seo_url = '';
$component = parse_url(str_replace('&amp;', '&', $link));
$data = array();
parse_str($component['query'], $data);
$route = $data['route'];
unset($data['route']);
switch ($route) {
case 'product/product':
if (isset($data['product_id'])) {
$tmp = $data;
$data = array();
if ($this->config->get('config_seo_url_include_path')) {
$data['path'] = $this->getPathByProduct($tmp['product_id']);
if (!$data['path']) return $link;
}
$data['product_id'] = $tmp['product_id'];
if (isset($tmp['tracking'])) {
$data['tracking'] = $tmp['tracking'];
}
}
break;
case 'product/category':
if (isset($data['path'])) {
$category = explode('_', $data['path']);
$category = end($category);
$data['path'] = $this->getPathByCategory($category);
if (!$data['path']) return $link;
}
break;
case 'product/product/review':
case 'information/information/info':
return $link;
break;
default:
break;
}
if ($component['scheme'] == 'https') {
$link = $this->config->get('config_ssl');
} else {
$link = $this->config->get('config_url');
}
$link .= 'index.php?route=' . $route;
if (count($data)) {
$link .= '&amp;' . urldecode(http_build_query($data, '', '&amp;'));
}
$queries = array();
foreach ($data as $key => $value) {
switch ($key) {
case 'product_id':
case 'manufacturer_id':
case 'category_id':
case 'information_id':
$queries[] = $key . '=' . $value;
unset($data[$key]);
$postfix = 1;
break;
case 'path':
$categories = explode('_', $value);
foreach ($categories as $category) {
$queries[] = 'category_id=' . $category;
}
unset($data[$key]);
break;
default:
break;
}
}
if(empty($queries)) {
$queries[] = $route;
}
$rows = array();
foreach($queries as $query) {
if ($this->getquery($query)) {
$rows[] = array('query' => $query, 'keyword' => $this->getquery($query));
}
}
if(count($rows) == count($queries)) {
$aliases = array();
foreach($rows as $row) {
$aliases[$row['query']] = $row['keyword'];
}
foreach($queries as $query) {
$seo_url .= '/' . rawurlencode($aliases[$query]);
}
}
if ($seo_url == '') return $link;
$seo_url = trim($seo_url, '/');
if ($component['scheme'] == 'https') {
$seo_url = $this->config->get('config_ssl') . $seo_url;
} else {
$seo_url = $this->config->get('config_url') . $seo_url;
}
if (isset($postfix)) {
$seo_url .= trim($this->config->get('config_seo_url_postfix'));
} else {
$seo_url .= '/';
}
if(substr($seo_url, -2) == '//') {
$seo_url = substr($seo_url, 0, -1);
}
if (count($data)) {
$seo_url .= '?' . urldecode(http_build_query($data, '', '&amp;'));
}
return $seo_url;
}
private function getPathByProduct($product_id) {
$product_id = (int)$product_id;
if ($product_id < 1) return false;
static $path = null;
if (!is_array($path)) {
$path = $this->cache->get('product.seopath');
if (!is_array($path)) $path = array();
}
if (!isset($path[$product_id])) {
$query = $this->db->query("SELECT category_id FROM " . DB_PREFIX . "product_to_category WHERE product_id = '" . $product_id . "' ORDER BY main_category DESC LIMIT 1");
$path[$product_id] = $this->getPathByCategory($query->num_rows ? (int)$query->row['category_id'] : 0);
$this->cache->set('product.seopath', $path);
}
return $path[$product_id];
}
private function getPathByCategory($category_id) {
$category_id = (int)$category_id;
if ($category_id < 1) return false;
static $path = null;
if (!is_array($path)) {
$path = $this->cache->get('category.seopath');
if (!is_array($path)) $path = array();
}
if (!isset($path[$category_id])) {
$max_level = 10;
$sql = "SELECT CONCAT_WS('_'";
for ($i = $max_level-1; $i >= 0; --$i) {
$sql .= ",t$i.category_id";
}
$sql .= ") AS path FROM " . DB_PREFIX . "category t0";
for ($i = 1; $i < $max_level; ++$i) {
$sql .= " LEFT JOIN " . DB_PREFIX . "category t$i ON (t$i.category_id = t" . ($i-1) . ".parent_id)";
}
$sql .= " WHERE t0.category_id = '" . $category_id . "'";
$query = $this->db->query($sql);
$path[$category_id] = $query->num_rows ? $query->row['path'] : false;
$this->cache->set('category.seopath', $path);
}
return $path[$category_id];
}
private function validate() {
if (isset($this->request->get['route']) && $this->request->get['route'] == 'error/not_found') {
return;
}
if(empty($this->request->get['route'])) {
$this->request->get['route'] = 'common/home';
}
if (isset($this->request->server['HTTP_X_REQUESTED_WITH']) && strtolower($this->request->server['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
return;
}
if (isset($this->request->server['HTTPS']) && (($this->request->server['HTTPS'] == 'on') || ($this->request->server['HTTPS'] == '1'))) {
$config_ssl = substr($this->config->get('config_ssl'), 0, $this->strpos_offset('/', $this->config->get('config_ssl'), 3) + 1);
$url = str_replace('&amp;', '&', $config_ssl . ltrim($this->request->server['REQUEST_URI'], '/'));
$seo = str_replace('&amp;', '&', $this->url->link($this->request->get['route'], $this->getqueryString(array('route')), 'SSL'));
} else {
$config_url = substr($this->config->get('config_url'), 0, $this->strpos_offset('/', $this->config->get('config_url'), 3) + 1);
$url = str_replace('&amp;', '&', $config_url . ltrim($this->request->server['REQUEST_URI'], '/'));
$seo = str_replace('&amp;', '&', $this->url->link($this->request->get['route'], $this->getqueryString(array('route')), 'NONSSL'));
}
if (rawurldecode($url) != rawurldecode($seo)) {
header($this->request->server['SERVER_PROTOCOL'] . ' 301 Moved Permanently');
$this->response->redirect($seo);
}
}
private function strpos_offset($needle, $haystack, $occurrence) {
// explode the haystack
$arr = explode($needle, $haystack);
// check the needle is not out of bounds
switch($occurrence) {
case $occurrence == 0:
return false;
case $occurrence > max(array_keys($arr)):
return false;
default:
return strlen(implode($needle, array_slice($arr, 0, $occurrence)));
}
}
private function getqueryString($exclude = array()) {
if (!is_array($exclude)) {
$exclude = array();
}
return urldecode(http_build_query(array_diff_key($this->request->get, array_flip($exclude))));
}
}
?>
ocshop.info
Тормозит Opencart. Часть 13 | Истрункция как поднять бабла
Все глобальный подводные камни, которые могут встретиться на пути к быстрой системе я уже описывал ранее, пока что к ним добавить особо нечего.Но иногда встречаются ситуации, когда магазин задыхается не из-за архитектурных проблем, а по глупости, недосмотру горе-разработчиков, или по банальному незнанию.
Итак. Что нужно проверить и почему могут быть тормоза.1 — Права на папки с кешами (системный, модификаторы, vqmod).
2 — Очень часто сайт долбят поисковые боты в ссылки фильтра. Что делать с ботами ниже. Что делать с фильтром? Все просто — покупаем Mega Filter Pro, а еще лучше Mega Filterp Pro Plus, включаем в его настройках кеш, добавляем в robots.txt Disalow: /*mfp и радуемся.
3. Поисковые боты в последнее время сошли с ума. Во первых их развелось великое множество, во вторых Бингу по моему сервером завезли, и он если заходит — укладывает магазин напрочь. По хорошему трафик у нас идет с Яндекса Гугла и немножко с мыл ру. Поэтому я бы рекомендовал закрыть к монахам в robots всех ботов кроме вышеуказанных. И внимательно проверить, закрыты ли у вас ссылки фильтров и метки. Да да метки надо закрывать — так как в opencart они реализованы через поиск, а поиск в opencart оставляет желать лучшего. Мало того такая реализация не приносит никакой пользы для seo. Так как в итоге в индекс попадает вагон соплей и ничего больше.
Также не забываем про crowl-delay. Имеет смысл поставить 5-10 секунд. Ничего не случится, от ботов не убудет. 10 секунд — это 2880 страниц в день. Вполне достаточно для того чтобы переиндесировать среднестатистический магазин ежесуточно полностью.
4 — Обновите vqmod до последней версии. Он стал намного быстрее.
5 — Старайтесь избегать дешевых виртуальных хостингов.
6 — Проверяйте лог ошибок. Недавно обнаружил на одном из магазинов смешную ситуацию. Из-за ошибки в переменной, выводимой в шаблон ajax скрипт обращался к несуществующей странице вызывая циклическую переадресацию, но не на сервеном уровне, а на уровне магазина. Соответсвенно магазин сам себя ддосил.
7 — Не используйте Лайтнинг от упырька MaxD. При ближайшем рассмотрении от этой поделки больше вреда чем пользы. Чего только стоит «фоновое создание кеша всех страниц сайта». Звучит вроде здорово, а на практике, у вас автоддос нон стоп.
Хуйнаныр(21)Очко(0)ocshop.info
Opencart тормозит | Nulled Warez Scripts
Информация :
Внимание форумчане! При создании тем, или выкладывании какой-либо информации проверьте в какой ветке форума вы находитесь! Не путайте Opencart и Opencart2. При несоблюдении данного условия выносится соответствующее наказание! И потом не говорите что вас НЕ ПРЕДУПРЕЖДАЛИ! По возможности используйте обменники mail, yandex, google, dropbox, rghost Дабы избежать просьб перезалить и проблем с рекламой!
Страница 1 из 5 1 2 3 4 5 Вперёд >-
Naterius Постоялец
Регистр.: 29 июл 2013 Сообщения: 62 Симпатии: 4 На сайте около 500 категорий и около 200 000 товаровТормозит жутко. Запустил логи запросов по БД и увидел странную картину. Если в категории есть под категория, а у нее в свою очередь есть товар.То идет проброс запросов по всем позициям.А если все товары только в родительской категории, то открываеться за секунды.В чем может быть проблема? -
cat2315 Создатель
Регистр.: 1 дек 2008 Сообщения: 32 Симпатии: 5 А модуль кеширования есть? Если есть то похоже, что кеш, для товаров в подкатегориях неправильно отрабатывет. -
Naterius Постоялец
Регистр.: 29 июл 2013 Сообщения: 62 Симпатии: 4 Да модуля кеширования нету, проблема решилась заменой файлов папки каталога , а конкретно модель и контролер, на файлы оригинального диста.Видимо в дисте русской сборки где то ошибка.А да версия 2.0.3.Если вдруг у кого будет такая проблема. -
mizaider Рекламодатель
Регистр.: 14 янв 2016 Сообщения: 25 Симпатии: 7 А вы счётчик количества товаров в категории отключили? -
FidaSa
Регистр.: 1 мар 2013 Сообщения: 509 Симпатии: 133 Naterius сказал(а): ↑На сайте около 500 категорий и около 200 000 товаровТормозит жутко. Запустил логи запросов по БД и увидел странную картину.Если в категории есть под категория, а у нее в свою очередь есть товар.То идет проброс запросов по всем позициям.А если все товары только в родительской категории, то открываеться за секунды.В чем может быть проблема?
Нажмите, чтобы раскрыть...
Тут есть еще такой модуль pagecache, его можно поставить в приложении версия на 1,5 !Вложения:
- pagecache 8 aug.zip Размер файла: 28,3 КБПросмотров: 15
-
artist_007 Создатель
Регистр.: 20 окт 2015 Сообщения: 28 Симпатии: 1 FidaSa сказал(а): ↑Тут есть еще такой модуль pagecache, его можно поставить в приложении версия на 1,5 !
Нажмите, чтобы раскрыть...
Пробовали его? Насколько эффективен? Что стало лучше после установки? -
Naterius Постоялец
Регистр.: 29 июл 2013 Сообщения: 62 Симпатии: 4 artist_007 сказал(а): ↑Пробовали его? Насколько эффективен? Что стало лучше после установки?
Нажмите, чтобы раскрыть...
Super Chache более эффективен, магазин на обычном хостинге летает. -
SpideR-KOSS Постоялец
Регистр.: 6 авг 2011 Сообщения: 51 Симпатии: 3 Напишите в личку, помогу разобраться с тормозами. -
FidaSa
Регистр.: 1 мар 2013 Сообщения: 509 Симпатии: 133 Naterius сказал(а): ↑Super Chache более эффективен, магазин на обычном хостинге летает.
Нажмите, чтобы раскрыть...
Поделитесь им ? рабочей версией ? -
Naterius Постоялец
Регистр.: 29 июл 2013 Сообщения: 62 Симпатии: 4 FidaSa сказал(а): ↑Поделитесь им ? рабочей версией ?
Нажмите, чтобы раскрыть...
Вот 3 модуля для ускоренияСкрытый контент. Для просмотра Вы должны быть зарегистрированным участником.
Нажмите, чтобы раскрыть...
Первых 2 работают в паре
www.nulled.cc
Тормозит Opencart. Часть 10 | Истрункция как поднять бабла
Особо нового выдумать ничего не выдумал.Но появилось несколько занятных наблюдений и один интересный проект:
1. Ваш магазин унижен большим количеством товаров? Он ели загружается? Клиенты уходят не дождавшись пока загрузится страница? Ваши «специалисты», поставили диагноз переехать на более мощный хостинг, и арендовать хотя бы VPS, а ваш магазин до этого не стал моим пациентом, смею вас расстроить, более мощный хостинг — не всегда поможет, так как во первых, у вас не проиндексированная база, во вторых если она проиндексированная, то не полностью и криво. И в третьих, обычно горе специалисты и администраторы серверов, забывают, а чаще не подозревают, о существовании тонких настроек mysql, без которых, вы хоть суперкомпьютер поставьте, прироста в производительности не ощутите.
Также не забываем про параметр swappiness, неправильная настройка которого приводит к тому что: Linux ate my RAM!И ваши данные как вот эти бараны будут бегать по старому через узкие места.Да и в сумме, переезд с места на место и годовая плата за хороший vps, могут оказаться в несколько раз дороже, чем стоимость комплексной оптимизации. А результат может так и не появится.
2. По каким то причинам, оказывается подмена хранилища кеша на memcached. На больших нагруженных проектах показатели даже ухудшаются. С чем это связано — я пока не понимаю, но реально на трех проектах за последнее время, откат к дисковому кешу дал прирост в производительности в несколько раз. Нужно будет покурить матчасть по этому поводу и поделать тесты на разных конфигурациях.
3. Недавно высмотрел еще одну штуку, которая много мало, а пару запросов может исключить. Если мы не используем мультиланг и мультишоп, можно в index.php все значения локализаций присвоить статичными данными, а не запросами в базу и разбором кукисов.
4. На днях был оптимизирован магазин, в котором на момент окончания работ было 730 000 товаров. Сайтмап генерится, seo-url работают. При условии общего количества товаров в категории до 20-30к, даже время загрузки получается меньше 500мс. К сожалению, все дополнительные меры программной оптимизации упираются в потерю совместимости со сторонними дополнениями. А так как владелец магазина планирует увеличить номенклатуру раз в 10, мы оказались на распутье. То ли плюнуть и заняться денормализацией, то ли сохранить нативную совместимость и наращивать железо. При чем в данном случае, все упирается в память (сейчас всего 6ГБ) и в ssd накопитель в качестве хранилища для временных данных mysql. По предварительным подсчетам, если поставить 32гб и ssd, вполне может получится система 5M ready. Останется лишь решить по мелочи вопросы с CDN для изображений и Sphinx-ом для поиска.
Ну и напоминаю. Turbocache и прямые руки — лучшее лекарство от тормозов, серьезная экономия на хостинге, и сведение количества потерянных посетителей до 0!
Нитропаки, и прочая лабуда — полное гавно!
Хуйнаныр(4)Очко(0)ocshop.info
Тормозит Opencart часть 15 | Наследие упырей
Сначала анекдот.
Приходит хирург кардиолог к автомастеру, двигатель мол кряхтит — посмотри.А болторез давай ныть.— Почему мол ты получаешь 5000 долларов за операцию, а я 500 за капитальный ремонт движка?Хирург завел двигатель и говорит — «на ремонтируй, я тебе заплачу 5000″.
Век живи век учись.
Я недавно заглядывал в Престу, 2 000 товаров, тормозит как скотина. Вроде бы все инструменты есть для аудита в ней встроенные. А с налета сделать ничего не смог. Пришлось бы переписать полдвижка. С Опенкартом же, уже давно все понятно. Мой первый пост про тормоза Opencart появился почти два года назад в январе 2014 го, с того времени магазинов в лицо и изнутри я поведал наверное штук 600 уже, и 99% стали работать зашибись.
И вдруг попадается мне магазин на opencart 1.4.8. Я уже забыл что там да как, версии движка этой лет 6, там даже класса кеша нет. Но при этом жирный сервант, вроде как какие то умники проставили индексы и все равно тормозит. При этом, тупит главная а все остальные страницы открываются в рамках.
Умники которых было до меня 5 человек, заявили, что мол мы ничего не можем сделать, движок гавно, индексы в базе есть, сервант жирный. Меняйте движок.
Но послушайте господа, 1.4.8 — это утилитарное гавно. При правильно затюненной базе, там тормозить просто нечему. Там даже сеоурлы в таблице product. И нет лишнего хлама в виде схем, кучи статусов всего чего только можно, api, отслеживаний активности пользователей и кучи хлама который появился в 2.x.
Вот тут я подзавис. Так как доступа к сереверу у меня нет. VMOD нет. PhpMyAdmin на сервере нет. Профайлера под 1.4 у меня нет. А если бы и был. У владельца магазин — он же CRM и укладывать его даже на полчаса нельзя.На помощь пришел мод фрилансера, который db_log под 1.5, хорошо что в 1.4 и 1.5 библиотека db.php не сильно отличается или не отличается совсем. Очень быстро лог медленных запросов перевалил за пару мегабайт и было над чем работать.
И у нас обнаружилась вот такая конструкция
SELECT * FROM oc_product ……. ORDER BY RAND() LIMIT 0,3
Вылезло это в модуле Вафловиса, который выводил из избранных категорий по три случайных товара на главную. Все упыри делают свои модули на 20 дефолтных товарах из свежеустановленной сборки и забывают, что товаров может быть не только лишь 2.
И так 10 раз по 500 миллисекунд на выполнение запроса. А трафла на магазине в пик человек 20-30 в минуту. Вот они зашли и выгрызли весь ресурс у mysql.
Плюс 5 секунд загрузка главной (которая якобы не оптимизируется и меняйте движок) — это овердохуя.
Лечиться все просто. Вместо выборки трех случайных записей из сложносочлененного массива данных несколькими джоинами, отсортированного случайным образом, делаем вот так. Ограничиваем выборку случайных значений только по полю product_id, на порядок уменьшая диапазон сортируемых значений, соответственно, на порядок увеличивая скорость обработки запроса.
SELECT product_id FROM oc_product ……. ORDER BY RAND() LIMIT 0,3
Потом перебираем получившийся массив, через model_catalog_product->getProduct($product_id) получаем полные данные по нашим трем товарам. И на выходе получаем 250мс полную генерацию страницы.
Четыре специалиста. Порядка 500 долларов в труху потраченных на их услуги-заслуги. И решение, которое лежит на поверхности.
По моему это уже старость. И мне пора устраиваться Juniorom в 1С.
Хуйнаныр(29)Очко(0)ocshop.info
Тормозит Opencart часть 6. Модуль TurboCache.
В цикле статей про ускорение Opencart, мы постоянно упоминали кеширование, кеширование и еще раз кеширование.
При формировании страницы движок собирает ее из нескольких основных частей. И для получения максимально прироста производительности, желательно, чтобы однотипные сегменты страниц, вместо того чтобы им постоянно фомироваться заново, брались уже готовые, что сэкономит ресурсы сервера, и повысит скорость генерации страниц. А после этого. Не лишним было бы сохранить полностью готовый HTML и в следующий раз, при запросе на страницу, данные которой у нас уже готовы, отдать ее из кеша, а не генерировать заново.
Это идеальный вариант, и мы в ближайшем будущем его реализуем. На сегодня первая часть этой задачи практически решена, и мы рады представить вам наш TurboCache, который как раз и предназначен, для того чтобы кешировать промежуточные однотипные сегменты магазина.
При тестировании на свежеустановленном движке при генерации главной страницы к примеру. TurboCache уменьшает количество запросов в базу почти в 4 раза с 74 до 19.
Скорость генерации станиц на работающих проектах увеличивается до 10-15 раз.
Вот список функционала дополнения.
— Гибкая настройка кеширования стандартных модулей и верхнего меню— Кеширование списка товаров на странице категорий— Кеширование списка товаров на странице производителей— Настройка время жизни кеша— Добавлено Gzip сжатие для файлов кеша и настройка степени компрессии.— Кеш-менеджер для гибкой настройки кешируемых элементов и гибкой очистки файлов кеша.— Поддерживает мультиязычность— Возможность полной очистки файлов системного кеша, изображений и vqmod.
Попробовать урезанную версию модуля для Opencart вы можете скачав его по здесь.Полная версия для Opencart находится здесь.
Для русской локализации Ocstore дополнение лежит здесь.
Наслаждайтесь, и быстрых вам магазинов!
_______________________________________________________________Предыдущие статьи по ускорению и оптимизации:
часть 1часть 2часть 3часть 4часть 5
Хуйнаныр(3)Очко(0)
ocshop.info