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

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

  • ArhiISP

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

    Spritz Окт. 7, 2010, 11: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, 12:01 д.п., спустя 1 минуту 35 секунд

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

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

    Spritz Окт. 8, 2010, 12: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, 12:06 д.п., спустя 3 минуты 8 секунд

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

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

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

    Spritz Окт. 8, 2010, 12:08 д.п., спустя 2 минуты 8 секунд

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

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

    Spritz Окт. 8, 2010, 12: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, 1:06 п.п., спустя 2 часа 16 минут 9 секунд

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

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

    Spritz Окт. 8, 2010, 3:07 п.п., спустя 2 часа 1 минуту 4 секунды


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

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

    Spritz Окт. 8, 2010, 3:23 п.п., спустя 16 минут 22 секунды

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

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

    Spritz Окт. 8, 2010, 3:33 п.п., спустя 10 минут

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

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