Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

pr0n.PHP
Kamil Szarmach
Narzędzia i sposoby optymalizacji aplikacji PHP dla serwisów o dużej przepustowości.
Do czego służy internet
Nasi klienci
Oczekiwania
Szybkość odpowiedzi
Stabilność
Interakcje
Prywatność
Dostępność
Monetyzacja
Optymalizacja
Problemy
duży ruch
przepustowość
konkurencja ddos
nagły peek
Problemy
Przyczyny
baza danych
zbyt skomplikowany kod
narzut frameworka
rozmiar plików
baza danych
MySQL? podzapytania są złe!
sprawdzaj indeksy
liczba połączeń
znaj silnik bazy - niuanse mają znaczenie
Redis / Memcache
Case: lista
SELECT DISTINCT ? AS `status`, `e`.`entity_id`, `e`.`type_id`, `e`.`attribute_set_id`,
  `cat_index`.`position` AS `cat_index_position`, `e`.`name`, `e`.`short_description`,
  `e`.`sku`, `e`.`price`, `e`.`special_price`, `e`.`special_from_date`, `e`.`special_to_date`,
  `e`.`cost`, `e`.`weight`, `e`.`small_image`, `e`.`thumbnail`, `e`.`news_from_date`,
  `e`.`news_to_date`, `e`.`url_key`, `e`.`url_path`, `e`.`is_recurring`, `e`.`recurring_profile`,
  `price_index`.`price`, `price_index`.`tax_class_id`, `price_index`.`final_price`,
  IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS `minimal_price`,
  `price_index`.`min_price`, `price_index`.`max_price`, `price_index`.`tier_price` FROM `catalog_product_flat_?` AS `e`
  INNER JOIN `catalog_category_product_index` AS `cat_index`
    ON cat_index.product_id=e.entity_id AND cat_index.store_id=?
    AND cat_index.visibility IN(?, ?)
    AND cat_index.category_id=?
    AND e.entity_id NOT IN (SELECT product_id FROM catalog_category_product_index WHERE category_id IN(?, ?, ?, ?, ?, ?, ?, ?, ?, ?))
  INNER JOIN `catalog_product_index_price` AS `price_index`
    ON price_index.entity_id = e.entity_id
    AND price_index.website_id = ? AND price_index.customer_group_id = ?
  ORDER BY `cat_index_position` ASC, `cat_index`.`position` ASC
Case: lista
SELECT DISTINCT ? AS `status`, `e`.`entity_id`, `e`.`type_id`, `e`.`attribute_set_id`,
  `cat_index`.`position` AS `cat_index_position`, `e`.`name`, `e`.`short_description`,
  `e`.`sku`, `e`.`price`, `e`.`special_price`, `e`.`special_from_date`, `e`.`special_to_date`,
  `e`.`cost`, `e`.`weight`, `e`.`small_image`, `e`.`thumbnail`, `e`.`news_from_date`,
  `e`.`news_to_date`, `e`.`url_key`, `e`.`url_path`, `e`.`is_recurring`, `e`.`recurring_profile`,
  `price_index`.`price`, `price_index`.`tax_class_id`, `price_index`.`final_price`,
  IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS `minimal_price`,
  `price_index`.`min_price`, `price_index`.`max_price`, `price_index`.`tier_price` FROM `catalog_product_flat_?` AS `e`
  INNER JOIN `catalog_category_product_index` AS `cat_index`
    ON cat_index.product_id=e.entity_id AND cat_index.store_id=?
    AND cat_index.visibility IN(?, ?)
    AND cat_index.category_id=?
    AND e.entity_id NOT IN (SELECT product_id FROM catalog_category_product_index WHERE category_id IN(?, ?, ?, ?, ?, ?, ?, ?, ?, ?))
  INNER JOIN `catalog_product_index_price` AS `price_index`
    ON price_index.entity_id = e.entity_id
    AND price_index.website_id = ? AND price_index.customer_group_id = ?
  ORDER BY `cat_index_position` ASC, `cat_index`.`position` ASC
Case: lista
SELECT DISTINCT ? AS `status`, `e`.`entity_id`, `e`.`type_id`, `e`.`attribute_set_id`,
  `cat_index`.`position` AS `cat_index_position`, `e`.`name`, `e`.`short_description`,
  `e`.`sku`, `e`.`price`, `e`.`special_price`, `e`.`special_from_date`, `e`.`special_to_date`,
  `e`.`cost`, `e`.`weight`, `e`.`small_image`, `e`.`thumbnail`, `e`.`news_from_date`,
  `e`.`news_to_date`, `e`.`url_key`, `e`.`url_path`, `e`.`is_recurring`, `e`.`recurring_profile`,
  `price_index`.`price`, `price_index`.`tax_class_id`, `price_index`.`final_price`,
  IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS `minimal_price`,
  `price_index`.`min_price`, `price_index`.`max_price`, `price_index`.`tier_price` FROM `catalog_product_flat_?` AS `e`
  INNER JOIN `catalog_category_product_index` AS `cat_index`
    ON cat_index.product_id=e.entity_id AND cat_index.store_id=?
    AND cat_index.visibility IN(?, ?)
    AND cat_index.category_id=?
    AND e.entity_id NOT IN ((?, ?, ?, ?, ?, ?, ?, ?, ?, ?))
  INNER JOIN `catalog_product_index_price` AS `price_index`
    ON price_index.entity_id = e.entity_id
    AND price_index.website_id = ? AND price_index.customer_group_id = ?
  ORDER BY `cat_index_position` ASC, `cat_index`.`position` ASC
SELECT DISTINCT product_id FROM catalog_category_product_index WHERE category_id IN(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Text
foreach($rows as $row) {
  $string .= $row->product_id.",";
}
$string = substr($string,0,-1);
skomplikowany kod
pętle
debuguj - var_dump i Xdebug
microtime - umiesz liczyć? policz
PHP to nie jedyna technologia
częste wywołania AJAX to dodatkowe
 instancje PHP-FPM i NGINX
NodeJS
javascript jest łatwy
już znamy ten język
możliwość współdzielenia sesji (memcache / redis)
doskonały do czatów i powiadomień
NodeJS: notyfikacje
var ioApp = io;
    ioApp.of('/listen')
    .on('connection', function(socket) {
        console.log('connection made');
        socket.on('set name', function(userName) {
            socket.set('userName', userName, function() {
                console.log('username: ' + userName);
                socket.emit('begin chat');
            });
        });
    });
ioApp
    .of('/addText')
    .on('connection', function(socket) {
        console.log('add tekst');
        socket.on('add text', function(data) {
            console.log(data.user + ": " + data.text);
            socket.broadcast.emit('msg received', data.user, data.text);
            socket.emit('msg received', data.user, data.text);
        })
    });
    ioApp.of('/notifications')
    .on('connection', function(socket) {
        socket.on('check', function(d) {
            console.log('check called '+d.id);
        console.log('SELECT * FROM user_notification WHERE (user='+d.id+' OR opponent='+d.id+') AND type>0 AND type<10;');
            
        connection.query('SELECT * FROM user_notification WHERE (user='+d.id+' OR opponent='+d.id+') AND type>0 AND type<10;', function (error, rows, fields) {
                console.log('err: '+error);
                console.log('rows: '+rows);
                console.log('f: '+fields);
                socket.emit('notify', rows);
                console.log('wyslano zapro '+d.id);
                for(var pole in rows) {
                    console.log(pole);
                }
            });
        });
    });
Framework
Yii/Zend/Cake - proste i lekkie
Zend2/Syfony2/Kohana - ładne, proste , ciężkie
znaj framework!
słabe punkty
zastąp niskopoziomowo
każdy  będzie bardzo dobry o ile go znamy
doskonały i idealny tylko brak frameworka
Zend Framework
Symfony 2
tnaFLIX
motherless
pornHUB
youporn
ZOO Tube
kamerkowo
Zend Framework 2
absolutnie nikt poważny!!!
Pliki
content trzymany w chmurze
ociężałość css/html/js to nie nasz problem
cacheowanie css i js
frontend ma nam służyć, a nie narzucać
Debugowanie
serializacja do loga
Xdebug na produkcji wykluczone!
w razie potrzeby olej performance i włącz logi
na produkcji logi wyłączone!
Sukces
Dobre wyniki to
dobre pieniądze
Popularny serwis
reklamuje się sam
Inwestycja w kod
to oszczędność na
eksploatacji i czas
na rozwój.
O mnie
Kamil Szarmach
PHP od 2001 roku
kamil@kamilszarmach.pl
ZendFramework
MySQL, Oracle
Piwo i hamburgery to moje paliwo