High performance websites
An introduction into xDebug profiling, Kcachegrind and JMeter
About Us




 Axel Jung             Timo Schmidt
 Software Developer    Software Developer
  AOE media GmbH         AOE media GmbH
Preparation

 Install Virtualbox and import the t3dd2012 appliance (User &
  Password: t3dd2012)
 You will find:
   • Apache with xdebug and apc
   • Jmeter
   • Kcachegrind
   • PHPStorm
 There are two vhost:
   • typo3.t3dd2012 and playground.t3dd2012
Can you build a new   Yes, we can!
  website for me?
But I expect a lot of
visitors. Can you handle
          them?


            Yes, we can!
Yes, we can!
Really?
...after inventing the next,
  cutting edge, enterprise
        architecture...
...and some* days
 of development...
The servers are not
fast enough for your application ;)
xDebug

INSTALL AND CONFIGURE
Install XDebug & KCachegrind
●   Install xdebug

(eg. apt-get install php5-xdebug)

●   Install kcachegrind

(eg. apt-get install kcachegrind)
Configure xDebug
●   Configuration in
    (/etc/php5/conf.d/xdebug.ini on Ubuntu)

●   xdebug.profiler_enable_trigger = 1

●   xdebug.profiler_output_dir = /..
Profiling

●   By request:

?XDEBUG_PROFILE

●   All requests by htaccess:

php_value xdebug.profiler_enable 1
Open with KCachegrind
KCachegrind

OPTIMIZE WITH IDE AND MIND
Analyzing Cachegrinds
●High self / medium self and
many calls =>

High potential for optimization

●   Early in call graph & not needed =>

High potential for optimization
Hands on

● There is an extension „slowstock“
in the VM.

● Open:
„http://typo3.t3dd2012/index.php?id=2“ and analyze it with kcachegrind.
Total Time Cost 12769352




   This code is very time consuming
Change 1 (SoapConversionRateProvider)



SoapClient is instantiated everytime
=> move to constructor
Change 1 (SoapConversionRateProvider)
Before:
/**
 * @param string $fromCurrency
 * @param string $toCurrency
 * @return float
 */
public function getConversionRate($fromCurrency, $toCurrency) {
              $converter = new SoapClient($this->wsdl);

             $in = new stdClass();
             $in->FromCurrency = $fromCurrency;
             $in->ToCurrency = $toCurrency;

             $out = $converter->ConversionRate($in);
             $result = $out->ConversionRateResult;

             return $result;
}
Change 1 (SoapConversionRateProvider)
After:
/** @var SoapClient */
protected $converter;

/** @return void */
public function __construct() {
                $this->converter = new SoapClient($this->wsdl);
}

/**
 * @param string $fromCurrency
 * @param string $toCurrency
 * @return float
 */
public function getConversionRate($fromCurrency, $toCurrency) {
                $in = new stdClass();
                $in->FromCurrency = $fromCurrency;
                $in->ToCurrency = $toCurrency;

               $out = $this->converter->ConversionRate($in);
               $result = $out->ConversionRateResult;
               return $result;
}
Total Time Cost 10910560 ( ~ -15%)




    11,99 % is still much time :(
Change 2 (SoapConversionRateProvider)

●  Conversion rates can be cached in APC cache to reduce webservice
calls.

    – Inject
           „ConversionRateCache“ into
      SoapConversionRateProvider.

    – Use   the cache in the convert method.
Change 2 (SoapConversionRateProvider)
Before:
/** @var SoapClient */
protected $converter;

/** @return void */
public function __construct() {
                $this->converter = new SoapClient($this->wsdl);
}

/**
 * @param string $fromCurrency
 * @param string $toCurrency
 * @return float
 */
public function getConversionRate($fromCurrency, $toCurrency) {
                $in = new stdClass();
                $in->FromCurrency = $fromCurrency;
                $in->ToCurrency = $toCurrency;

               $out = $this->converter->ConversionRate($in);
               $result = $out->ConversionRateResult;

               return $result;
}
Change 2 (SoapConversionRateProvider)
After:
 /** @var Tx_Slowstock_System_Cache_ConversionRateCache */
protected $cache;
 ...

/** @param Tx_Slowstock_System_Cache_ConversionRateCache $cache */
public function injectRateCache(Tx_Slowstock_System_Cache_ConversionRateCache $cache) {
                $this->cache = $cache;
}
…

public function getConversionRate($fromCurrency, $toCurrency) {
                $cacheKey = $fromCurrency.'-'.$toCurrency;
                if(!$this->cache->has($cacheKey)) {
                                   $in = new stdClass();
                                   $in->FromCurrency = $fromCurrency;
                                   $in->ToCurrency = $toCurrency;

                                $out = $this->converter->ConversionRate($in);
                                $result = $out->ConversionRateResult;
                                $this->cache->set($cacheKey, $result);
               }
               return $this->cache->get($cacheKey);
}
Change 2 (SoapConversionRateProvider)
After:
 /** @var Tx_Slowstock_System_Cache_ConversionRateCache */
protected $cache;
 ...

/** @param Tx_Slowstock_System_Cache_ConversionRateCache $cache */
public function injectRateCache(Tx_Slowstock_System_Cache_ConversionRateCache $cache) {
                $this->cache = $cache;
}
…

public function getConversionRate($fromCurrency, $toCurrency) {
                $cacheKey = $fromCurrency.'-'.$toCurrency;
                if(!$this->cache->has($cacheKey)) {
                                   $in = new stdClass();
                                   $in->FromCurrency = $fromCurrency;
                                   $in->ToCurrency = $toCurrency;

                                $out = $this->converter->ConversionRate($in);
                                $result = $out->ConversionRateResult;
                                $this->cache->set($cacheKey, $result);
               }
               return $this->cache->get($cacheKey);
}
Total Time Cost 5187627 ( ~ -50%)




 Much better, but let's look on the call
  graph... do we need all that stuff?
The kcachegrind call graph
The kcachegrind call graph




Do we need any TCA in Eid? No
Change 3 – Remove unneeded code:
                    (Resources/Private/Eid/rates.php):
Before:
tslib_eidtools::connectDB();
tslib_eidtools::initTCA();
$TSFE = t3lib_div::makeInstance('tslib_fe', $GLOBALS['TYPO3_CONF_VARS'], ...);

After:
tslib_eidtools::connectDB();
$TSFE = t3lib_div::makeInstance('tslib_fe', $GLOBALS['TYPO3_CONF_VARS'], ...);
Total Time Cost 2877900 ( ~ -45%)
Summary

●       From 12769352 => 2877900 (-77%) with three changes 

●       Additional Ideas:

    ●    Reduce created fluid objects by implementing static fluid view helpers
         (examples in fluid core)

    ●    Cache reverse conversion rate (1/rate)

    ●    Use APC Cache Backend for TYPO3 and Extbase caches
JMeter

http://jmeter.apache.org/
Why Jmeter?
JMeter

BUILD A SIMPLE WEB TESTPLAN
JMeter Gui
Add Thread Group
Name Group
Add HTTP Defaults
Set Server
Add HTTP Sampler
Set Path
Add Listener
Start Tests
View Results
JMeter

RECORD WITH PROXY
Add Recording Controller
Add Proxy Server
Exclude Assets
Start
Configure Browser
Browse
View results
JMeter

ADVANCED
Add Asserts
Match Text
Constant Timer
Set the Base
Summary Report
Graph Report
Define Variables
Use Variables
CSV Files
CSV Settings
Use CSV Vars
Command Line

• /…/jmeter -n -t plan.jmx -l build/logs/testplan.jtl -j
  build/logs/testplan.log
Jenkins and JMeter
Detail Report
Use Properties

 -p ${properties}
JMeter + Cloud

DISTRIBUTED TESTING
Start Server
jmeter.properties

remote_hosts=127.0.0.1
Run Slaves
http://aws.amazon.com/

AMAZON CLOUD
Create User
EC2
Create Key
Name Key
Download Key
Create Security Groups
Launch
Select AMI ami-3586be41
Minimum Small
Configure Firewall
Wait 15 Min
Get Adress
Connect
Start Cloud Tool
Start Instances
Wait for Slaves
Slave Log
Close JMeter
All Slave will be terminated
Slave AMI

• ami-963e0ce2
• Autostart JMeter im Server Mode
Costs
Want to know more?




European HQ:   AOE media GmbH
               Borsigstraße 3
               65205 Wiesbaden

Tel.:                            +49 (0)6122 70 70 7 - 0
Fax:                             +49 (0)6122 70 70 7 - 199
E-Mail:                          postfach@aoemedia.de
Web:                             http://www.aoemedia.de

Performance measurement and tuning