ФорумПрограммированиеPHP для идиотов → тормозит сайт, оптимизация zend + smarty

тормозит сайт, оптимизация zend + smarty

  • ArhiISP

    Сообщения: 15 Репутация: N Группа: Кто попало

    Spritz 7 октября 2010 г. 23:59

    Добрый вечер, изучаю сайтостроение. делаю тестовый сайтик по урокам Practical Web 2.0 Applications with PHP
    выкладываю его для теста на wooohooo.ru. сайт строится на zend + smarty
    сейчас столкнулся с тем, что пока нет обращений к базе данных, сайт вроде бы нормально работает, но как идет обращение к базе, сразу же видны очень сильные задержки. в чем может быть проблема? хостинг? код? в заранее благодарен. увидеть торможение можно как на этапе логина, так и на этапе просмотра опубликованных сообщений (чтоб не регится, сразу можно зайти под логином "ИСП" пароль "224224") в кратце о коде.

    index.php


    <?php 

    error_reporting(E_ALL|E_STRICT);
    ini_set('display_errors', 1);
    date_default_timezone_set('Europe/Moscow');

    //путь до установленного фреймворка
    set_include_path('.'.PATH_SEPARATOR . '../libs'
    .PATH_SEPARATOR.'../libs/Pear'
    .PATH_SEPARATOR.get_include_path());


    require_once 'Zend/Loader/Autoloader.php';
    $loader = Zend_Loader_Autoloader::getInstance();
    $loader->registerNamespace(array('CustomControllerAclManager', 'Templater', 'CustomControllerAction'
    , 'DatabaseObject', 'FormProcessor', 'Profile','Text_CAPTCHA'
    ,'Text_Password','Breadcrumbs','FCKeditor'));


    //загрузка конфигурационной информации
    $config=new Zend_Config_Ini('../settings.ini','development');
    Zend_Registry::set('config',$config);

    //создание обьекта для системного журнала
    $logger=new Zend_Log(new Zend_Log_Writer_Stream($config->logging->file));
    Zend_Registry::set('logger',$logger);

    //соединение с базой данных
    $params = array('host' => $config->database->hostname,
    'username' => $config->database->username,
    'password' => $config->database->password,
    'dbname' => $config->database->database,
    'driver_options'=> array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8'),
    'profiler' => false);


    $db = Zend_Db::factory($config->database->type, $params);
    Zend_Registry::set('db', $db);
    $db->query("set names utf8");

    //настройка аутентификации пользователей
    $auth = Zend_Auth::getInstance();
    $auth->setStorage(new Zend_Auth_Storage_Session());

    //обработка запроса пользователя
    $controller=Zend_Controller_Front::getInstance();
    $controller->throwExceptions(true);
    $controller->setControllerDirectory($config->paths->base.'/include/Controllers/');
    $controller->registerPlugin(new CustomControllerAclManager($auth));

    //настройка визуализации
    $vr = new Zend_Controller_Action_Helper_ViewRenderer();
    $vr->setView(new Templater());
    $vr->setViewSuffix('tpl');
    Zend_Controller_Action_HelperBroker::addHelper($vr);


    $controller->throwExceptions(true);
    $controller->dispatch();


    из AccountController функция

            public function loginAction()
    {
    // if a user's already logged in, send them to their account home page
    $auth = Zend_Auth::getInstance();

    if ($auth->hasIdentity())
    $this->_redirect('/account');

    $request = $this->getRequest();

    // определение страницы, которую изначально запрашивал пользователь
    $redirect = $request->getPost('redirect');
    if (strlen($redirect) == 0)
    $redirect = $request->getServer('REQUEST_URI');
    if (strlen($redirect) == 0)
    $redirect = '/account';

    // инициализация сообщения об ошибке
    $errors = array();

    // обработка входа, если запрос сделан путем отправления формы
    if ($request->isPost()) {

    // получение данных из формы и их проверка
    $username = $request->getPost('username');
    $password = $request->getPost('password');

    if (strlen($username) == 0)
    $errors['username'] = 'Не введен Логин';
    if (strlen($password) == 0)
    $errors['password'] = 'Не введен Пароль';

    if (count($errors) == 0) {

    // настройка параметров адаптера аутентификации
    $adapter = new Zend_Auth_Adapter_DbTable($this->db,
    'users',
    'username',
    'password',
    'md5(?)');

    $adapter->setIdentity($username);
    $adapter->setCredential($password);

    // попытка аутентификации пользователя
    $result = $auth->authenticate($adapter);

    if ($result->isValid()) {
    $user = new DatabaseObject_User($this->db);
    $user->load($adapter->getResultRowObject()->user_id);

    // регистрации попытки входа в журнал
    $user->loginSuccess();

    // запись личных данных пользователя в сеанс
    $identity = $user->createAuthIdentity();
    $auth->getStorage()->write($identity);

    // перенаправление пользователя на запрашиваемую им страницу
    $this->_redirect($redirect);
    }

    // регистрация неудачной попытки входа в журнале
    DatabaseObject_User::LoginFailure($username,
    $result->getCode());
    $errors['username'] = 'Не верный логин или пароль';
    }
    }

    $this->view->errors = $errors;
    $this->view->redirect = $redirect;
    }



    user.php из датабейзобжект

    <?php
    class DatabaseObject_User extends DatabaseObject
    {
    static $userTypes = array('member' => 'Member',
    'administrator' => 'Administrator');

    public $profile = null;
    public $_newPassword = null;

    public function __construct($db)
    {
    parent::__construct($db, 'users', 'user_id');

    $this->add('username');
    $this->add('password');
    $this->add('user_type', 'member');
    $this->add('ts_created', time(), self::TYPE_TIMESTAMP);
    $this->add('ts_last_login', null, self::TYPE_TIMESTAMP);

    $this->profile = new Profile_User($db);
    }

    protected function preInsert()
    {
    // $this->password = uniqid();
    $this->_newPassword = Text_Password::create(8);
    $this->password = $this->_newPassword;
    return true;
    }

    protected function postLoad()
    {
    $this->profile->setUserId($this->getId());
    $this->profile->load();
    }

    protected function postInsert()
    {
    $this->profile->setUserId($this->getId());
    $this->profile->save(false);
    $this->sendEmail('user-register.tpl');
    return true;
    }

    protected function postUpdate()
    {
    $this->profile->save(false);
    return true;
    }

    protected function preDelete()
    {
    $this->profile->delete();
    return true;
    }

    public function __set($name, $value)
    {
    switch ($name) {
    case 'password':
    $value = md5($value);
    break;

    case 'user_type':
    if (!array_key_exists($value, self::$userTypes))
    $value = 'member';
    break;
    }

    return parent::__set($name, $value);
    }


    public function usernameExists($username)
    {
    $query = sprintf('select count(*) from %s where username = ?',
    $this->_table);

    $result = $this->_db->fetchOne($query, $username);

    return $result > 0;
    }

    static public function IsValidUsername($username)
    {
    $validator = new Zend_Validate_Alnum();
    return $validator->isValid($username);
    }


    public function sendEmail($tpl)
    {
    $templater = new Templater();
    $templater->user = $this;

    // считывается тело сообщения
    $body = $templater->render('email/' . $tpl);

    // извлечение темы из первой строки
    list($subject, $body) = preg_split('/\r|\n/', $body, 2);

    // настройка и отправка сообщения
    $mail = new Zend_Mail('UTF-8');
    $mail->setHeaderEncoding(Zend_Mime::ENCODING_BASE64);

    // помещение адреса доставки и полного имени в строку "кому"
    $mail->addTo($this->profile->email,
    trim($this->profile->first_name . ' ' .
    $this->profile->last_name));

    // чтение данных администратора из конфигурационной информации
    $mail->setFrom(Zend_Registry::get('config')->email->from->email,
    Zend_Registry::get('config')->email->from->name);

    // добавление темы и тела, отправки
    $mail->setSubject(trim($subject));
    $mail->setBodyText(trim($body));
    $mail->send();
    }

    public function createAuthIdentity()
    {
    $identity = new stdClass;
    $identity->user_id = $this->getId();
    $identity->username = $this->username;
    $identity->user_type = $this->user_type;
    $identity->first_name = $this->profile->first_name;
    $identity->last_name = $this->profile->last_name;
    $identity->email = $this->profile->email;

    return $identity;
    }

    public function loginSuccess()
    {
    $this->ts_last_login = time();
    unset($this->profile->new_password);
    unset($this->profile->new_password_ts);
    unset($this->profile->new_password_key);
    $this->save();

    $message = sprintf('Successful login attempt from %s user %s',
    $_SERVER['REMOTE_ADDR'],
    $this->username);

    $logger = Zend_Registry::get('logger');
    $logger->notice($message);
    }
    static public function LoginFailure($username, $code = '')
    {
    switch ($code) {
    case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
    $reason = 'Unknown username';
    break;
    case Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS:
    $reason = 'Multiple users found with this username';
    break;
    case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
    $reason = 'Invalid password';
    break;
    default:
    $reason = '';
    }

    $message = sprintf('Failed login attempt from %s user %s',
    $_SERVER['REMOTE_ADDR'],
    $username);

    if (strlen($reason) > 0)
    $message .= sprintf(' (%s)', $reason);

    $logger = Zend_Registry::get('logger');
    $logger->warn($message);
    }



    public function fetchPassword()
    {
    if (!$this->isSaved())
    return false;

    // генерация новых параметров пароля
    $this->_newPassword = Text_Password::create(8);
    $this->profile->new_password = md5($this->_newPassword);
    $this->profile->new_password_ts = time();
    $this->profile->new_password_key = md5(uniqid() .
    $this->getId() .
    $this->_newPassword);

    // сохранение нового файла в профиле и отправка сообщения.
    $this->profile->save();
    $this->sendEmail('user-fetch-password.tpl');

    return true;
    }

    public function confirmNewPassword($key)
    {
    // проверка наличия правильных временных данных
    if (!isset($this->profile->new_password)
    || !isset($this->profile->new_password_ts)
    || !isset($this->profile->new_password_key)) {

    return false;
    }

    // проверка подтверждения пароля в течении суток
    if (time() - $this->profile->new_password_ts > 86400)
    return false;

    // проверка правильности ключа
    if ($this->profile->new_password_key != $key)
    return false;

    // все правильно принимаем новый пароль для учетной записи

    // пропускаем локальный уровень, новый пароль уже в md5
    parent::__set('password', $this->profile->new_password);

    unset($this->profile->new_password);
    unset($this->profile->new_password_ts);
    unset($this->profile->new_password_key);

    // сохранение учетных данных и профиля пользователя
    return $this->save();
    }





    }
    ?>






  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 8 октября 2010 г. 0:01, спустя 1 минуту 35 секунд

    предположу - хостинг.
    Сапожник без сапог
  • ArhiISP

    Сообщения: 15 Репутация: N Группа: Кто попало

    Spritz 8 октября 2010 г. 0:02, спустя 1 минуту 55 секунд

    databaseobject.php

    [man]
    <?php
       /**
        * DatabaseObject
        *
        * Abstract class used to easily manipulate data in a database table
        * via simple load/save/delete methods
        */
       abstract class DatabaseObject
       {
           const TYPE_TIMESTAMP = 1;
           const TYPE_BOOLEAN   = 2;

           protected static $types = array(self::TYPE_TIMESTAMP, self::TYPE_BOOLEAN);

           private $_id = null;
           private $_properties = array();


           protected $_db = null;
           protected $_table = '';
           protected $_idField = '';

           public function __construct(Zend_Db_Adapter_Abstract $db, $table, $idField)
           {
               $this->_db = $db;
               $this->_table = $table;
               $this->_idField = $idField;
           }

           public function load($id, $field = null)
           {
               if (strlen($field) == 0)
                   $field = $this->_idField;

               if ($field == $this->_idField) {
                   $id = (int) $id;
                   if ($id <= 0)
                       return false;
               }

               $query = sprintf('select %s from %s where %s = ?',
                                join(', ', $this->getSelectFields()),
                                $this->_table,
                                $field);

               $query = $this->_db->quoteInto($query, $id);

               return $this->_load($query);
           }

           protected function getSelectFields($prefix = '')
           {
               $fields = array($prefix . $this->_idField);
               foreach ($this->_properties as $k => $v)
                   $fields[] = $prefix . $k;

               return $fields;
           }

           protected function _load($query)
           {
               $result = $this->_db->query($query);
               $row = $result->fetch();
               if (!$row)
                   return false;

               $this->_init($row);

               $this->postLoad();

               return true;
           }

           public function _init($row)
           {
               foreach ($this->_properties as $k => $v) {
                   $val = $row[$k];

                   switch ($v['type']) {
                       case self::TYPE_TIMESTAMP:
                           if (!is_null($val))
                               $val = strtotime($val);
                           break;
                       case self::TYPE_BOOLEAN:
                           $val = (bool) $val;
                           break;
                   }

                   $this->_properties[$k]['value'] = $val;
               }
               $this->_id = (int) $row[$this->_idField];
           }


           public function save($useTransactions = true)
           {
               $update = $this->isSaved();

               if ($useTransactions)
                   $this->_db->beginTransaction();

               if ($update)
                   $commit = $this->preUpdate();
               else
                   $commit = $this->preInsert();

               if (!$commit) {
                   if ($useTransactions)
                       $this->_db->rollback();
                   return false;
               }

               $row = array();

               foreach ($this->_properties as $k => $v) {
                   if ($update && !$v['updated'])
                       continue;

                   switch ($v['type']) {
                       case self::TYPE_TIMESTAMP:
                           if (!is_null($v['value'])) {
                               if ($this->_db instanceof Zend_Db_Adapter_Pdo_Pgsql)
                                   $v['value'] = date('Y-m-d H:i:sO', $v['value']);
                               else
                                   $v['value'] = date('Y-m-d H:i:s', $v['value']);
                           }
                           break;

                       case self::TYPE_BOOLEAN:
                           $v['value'] = (int) ((bool) $v['value']);
                           break;
                   }

                   $row[$k] = $v['value'];
               }

               if (count($row) > 0) {
                   // perform insert/update
                   if ($update) {
                       $this->_db->update($this->_table, $row, sprintf('%s = %d', $this->_idField, $this->getId()));
                   }
                   else {
                       $this->_db->insert($this->_table, $row);
                       $this->_id = $this->_db->lastInsertId($this->_table, $this->_idField);
                   }
               }

               // update internal id

               if ($commit) {
                   if ($update)
                       $commit = $this->postUpdate();
                   else
                       $commit = $this->postInsert();
               }

               if ($useTransactions) {
                   if ($commit)
                       $this->_db->commit();
                   else
                       $this->_db->rollback();
               }

               return $commit;
           }

           public function delete($useTransactions = true)
           {
               if (!$this->isSaved())
                   return false;

               if ($useTransactions)
                   $this->_db->beginTransaction();

               $commit = $this->preDelete();

               if ($commit) {
                   $this->_db->delete($this->_table, sprintf('%s = %d', $this->_idField, $this->getId()));
               }
               else {
                   if ($useTransactions)
                       $this->_db->rollback();
                   return false;
               }

               $commit = $this->postDelete();

               $this->_id = null;

               if ($useTransactions) {
                   if ($commit)
                       $this->_db->commit();
                   else
                       $this->_db->rollback();
               }

               return $commit;
           }

           public function isSaved()
           {
               return $this->getId() > 0;
           }

           public function getId()
           {
               return (int) $this->_id;
           }

           public function getDb()
           {
               return $this->_db;
           }

           public function __set($name, $value)
           {
               if (array_key_exists($name, $this->_properties)) {
                   $this->_properties[$name]['value'] = $value;
                   $this->_properties[$name]['updated'] = true;
                   return true;
               }

               return false;
           }

           public function __get($name)
           {
               return array_key_exists($name, $this->_properties) ? $this->_properties[$name]['value'] : null;
           }

           protected function add($field, $default = null, $type = null)
           {
               $this->_properties[$field] = array('value'   => $default,
                                                  'type'    => in_array($type, self::$types) ? $type : null,
                                                  'updated' => false);
           }

           protected function preInsert()
           {
               return true;
           }

           protected function postInsert()
           {
               return true;
           }

           protected function preUpdate()
           {
               return true;
           }

           protected function postUpdate()
           {
               return true;
           }

           protected function preDelete()
           {
               return true;
           }

           protected function postDelete()
           {
               return true;
           }

           protected function postLoad()
           {
               return true;
           }

           public static function BuildMultiple($db, $class, $data)
           {
               $ret = array();

               if (!class_exists($class))
                   throw new Exception('Undefined class specified: ' . $class);

               $testObj = new $class($db);

               if (!$testObj instanceof DatabaseObject)
                   throw new Exception('Class does not extend from DatabaseObject');

               foreach ($data as $row) {
                   $obj = new $class($db);
                   $obj->_init($row);

                   $ret[$obj->getId()] = $obj;
               }

               return $ret;
           }
       }[/man]

    Спустя 63 сек.

    предположу - хостинг.


    а не подскажите достаточно надежный хостинг по доступной цене?)
  • mario

    Сообщения: 6067 Репутация: N Группа: Джедаи

    Spritz 8 октября 2010 г. 0:06, спустя 3 минуты 8 секунд

    не подскажите достаточно надежный хостинг по доступной цене?)

    см в подпись. Это если именно хостинг нужен.
    А vps лучше брать на xen виртуализации.
  • ArhiISP

    Сообщения: 15 Репутация: N Группа: Кто попало

    Spritz 8 октября 2010 г. 0:08, спустя 2 минуты 8 секунд

    хочется, чтобы не было жутких задержек) если дело в хостинге, то что ж делать, придется поменять:(
    а так по коду, в глаза ничего не бросается, из-за чего могут быть задержки именно при обращении к бд?
  • mario

    Сообщения: 6067 Репутация: N Группа: Джедаи

    Spritz 8 октября 2010 г. 0:11, спустя 3 минуты 7 секунд

    хочется, чтобы не было жутких задержек) если дело в хостинге, то что ж делать, придется поменять:(

    там первый месяц бесплатно, так что тестируйте.
  • Nox

    Сообщения: 204 Репутация: N Группа: Кто попало

    Spritz 8 октября 2010 г. 4:55, спустя 4 часа 43 минуты 50 секунд


    хочется, чтобы не было жутких задержек) если дело в хостинге, то что ж делать, придется поменять:(

    там первый месяц бесплатно, так что тестируйте.

    хочется, чтобы не было жутких задержек) если дело в хостинге, то что ж делать, придется поменять:(

    там первый месяц бесплатно, так что тестируйте.
    я жутко извиняюсь, но зачем вы людям это говно советуете?
  • VaseninM

    Сообщения: 2416 Репутация: N Группа: Адекваты

    Spritz 8 октября 2010 г. 8:09, спустя 3 часа 14 минут

    я жутко извиняюсь, но зачем вы людям это говно советуете?

    клиент? Есть какие то факты?
  • mario

    Сообщения: 6067 Репутация: N Группа: Джедаи

    Spritz 8 октября 2010 г. 8:44, спустя 35 минут 6 секунд

    я жутко извиняюсь, но зачем вы людям это говно советуете?

    эм?:)
    Ты хуйню плетешь ;) Работаю с ними уже второй год. Ни один из заказчиков не пожаловался. Ты бы вначале глянул что да как, а потом пиздел.
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 8 октября 2010 г. 9:05, спустя 21 минуту 11 секунд

    обсирать надо аргументированно.
    про хостинг от mario ничего не могу сказать — верю на слово. сам пользуюсь уже давно timeweb ( <- реферал) и очень доволен. а по теме для Zend+Smarty я бы посоветовал искать VPS пошустрее. нелёгкая такая упряжка :)))
    ιιlllιlllι унц-унц
  • ArhiISP

    Сообщения: 15 Репутация: N Группа: Кто попало

    Spritz 8 октября 2010 г. 10:50, спустя 1 час 44 минуты 41 секунду


    обсирать надо аргументированно.
    про хостинг от mario ничего не могу сказать — верю на слово. сам пользуюсь уже давно timeweb ( <- реферал) и очень доволен. а по теме для Zend+Smarty я бы посоветовал искать VPS пошустрее. нелёгкая такая упряжка :)))

    а как ее облегчить? отказ от смарти даст ли прирост, если все пустить через zend овский View ?
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 8 октября 2010 г. 13:06, спустя 2 часа 16 минут 9 секунд

    г-н Котеров в своей бесконечной милости писал, что если склеить все нужные тебе файлы Zend в один и настроить нормально кешер байткода (eAccelerator), то получишь ускорение до 10раз.
    но опять же, для такого колдовства лучше VPS или дедик.
    ιιlllιlllι унц-унц
  • Sinkler

    Сообщения: 7958 Репутация: N Группа: в ухо

    Spritz 8 октября 2010 г. 15:07, спустя 2 часа 1 минуту 4 секунды


    г-н Котеров в своей бесконечной милости писал, что если склеить все нужные тебе файлы Zend в один и настроить нормально кешер байткода (eAccelerator), то получишь ускорение до 10раз.
    но опять же, для такого колдовства лучше VPS или дедик.
    насколько я помню, он писал максимум в 22 раза)))
  • ArhiISP

    Сообщения: 15 Репутация: N Группа: Кто попало

    Spritz 8 октября 2010 г. 15:23, спустя 16 минут 22 секунды

    VPS пока достаточно дорогое решение для меня) поэтому eAccelerator ом как я полагаю вопспользоваться не смогу.
    А вот по поводу склейки всех нужных файлов зенда в один, вот где то читал, читал что не помогает, где то пишут, что помогает. Скажите, кто пробовал, и был ли прирост от этого?
  • Абырвалг

    Сообщения: 6480 Репутация: N Группа: Джедаи

    Spritz 8 октября 2010 г. 15:33, спустя 10 минут

    ArhiISP, если есть доступ к php.ini - можно прописать свои расширения. Найди только соответствующие бинарники

Пожалуйста, авторизуйтесь, чтобы написать комментарий!