Tuningoljuk a fejlesztőkörnyezetet!

Korábban írtam egy blogbejegyzést arról, hogyan lehet gyorsan és egyszerűen fejlesztőkörnyezetet összeállítani Ubuntu Linux rendszeren a Drupalos fejlesztésekhez. Több érdekes visszajelzés érkezett, például megtudtam, hogy a jogosultság-probléma megoldása lehetséges CGI mód nélkül is, a PHP-t hagyományosan Apache modulként használva. Időközben mindig finomítottam kicsit a beállításokon, majd Tyr43l-től kaptam hasznos tanácsokat a további teljesítményhangolás tekintetében.
Nyilván egy fejlesztői környezetnél nem azok az elvek érvényesülnek, amelyek egy nagyobb terhelésű szervernél, már sokszor az alapbeállítások is megfelelőek. Viszont érdemes rászánni egy kis időt a finomhangolásra, amelyet majd később a munka során megspórolunk.

Az általam használt számítógép Intel core i5-ös processzorral és 8 GB RAM-mal rendelkezik, ezért más gépeken szükség lehet a megadott értékek átállítására, az operációs rendszer pedig továbbra is Ubuntu 11.04.

1. MySQL teljesítménynövelés

Hozzunk létre egy új fájlt a beállítások számára:

$ sudo gedit /etc/mysql/conf.d/mysql_tuning.cnf

A fájl tartalma legyen a következő:

[mysqld]
max_connections = 10
max_user_connections = 25
key_buffer = 1024M
myisam_sort_buffer_size = 128M
join_buffer_size = 4M
read_buffer_size = 8M
sort_buffer_size = 16M
table_cache = 2048
table_definition_cache = 1024
thread_cache_size = 286
interactive_timeout = 25
wait_timeout = 1800
connect_timeout = 10
max_allowed_packet = 64M
max_connect_errors = 1000
query_cache_limit = 1M
query_cache_size = 16M
query_cache_type = 1
tmp_table_size = 64M
log_slow_queries = /var/log/mysql/mysql-slow.log

innodb_buffer_pool_size = 1024M
innodb_additional_mem_pool_size = 20M
innodb_log_file_size = 10M
innodb_log_buffer_size = 64M
innodb_flush_log_at_trx_commit = 2
innodb_lock_wait_timeout = 180

A félkövéren megjelölt adatokat szükséges módosítani, ha kevesebb memóriát adnánk a MySQL-nek, jelen esetben 1 gigabyte RAM-ot fog lefoglalni magának.

A fájl mentése után a következő paranccsal indítsuk újra az adatbázis-szervert:

$ sudo service mysql restart

Amennyiben további beállításokkal szeretnénk növelni a MySQL szerver teljesítményét, a Tuning Primer Script személyében praktikus segítőtársra lelhetünk.

2. PHP trükkök

Ha az előző leírásban felvázolt CGI módban futtatjuk a PHP-t, akkor nyissuk meg a konfigurációs fájlját (Apache modulként használva az /etc/php5/apache2/php.ini fájlt keressük):

$ sudo gedit /etc/php5/cgi/php.ini

A realpath_cache_size és a realpath_cache_ttl értékét fogjuk megemelni, alapértelmezetten „16k” és „120” van beállítva nekik:

realpath_cache_size = 128k
realpath_cache_ttl = 160

CGI módban használt PHP-nél gyorsíthat a PHP-FPM, amely daemonként folyamatosan futva a kérések kiszolgálása során jelent teljesítménynövekedést:

$ sudo sudo apt-get install php5-fpm

Szerkesszük beállításokat tartalmazó állományt:

$ sudo gedit /etc/php5/fpm/pool.d/www.conf

Keressük meg benne a jogosultságra vonatkozó user és group sorokat, majd adjuk meg az előző leírásban használt felhasználó- és csoportnevet.

user = felhasznalo
group = felhasznalo

Végül indítsuk újra a szolgáltatást:

$ sudo service php5-fpm restart

3. APC telepítése

Az APC egy PHP kiterjesztésként elérhető gyorsítótár, amely nagyobb terhelésnél ugrásszerű gyorsulást képes előidézni. A következő paranccsal tudjuk feltelepíteni:

$ sudo apt-get install php-apc

Fejlesztésnél okozhat mellékhatásokat, például egy fájl változtatásának eredménye nem jelenik meg a böngészőben. Az alábbi módon tudjuk kivédeni ezeket:

Nyissuk meg a beállításait tartalmazó állományt:

$ sudo gedit /etc/php5/conf.d/apc.ini

Adjuk hozzá a következő sorokat:

extension = apc.so
apc.shm_segments = 1
apc.num_files_hint = 2048
apc.rfc1867 = 1
apc.stat = 1
apc.shm_size = 64M

Majd indítsuk újra a webszervert:

$ sudo service apache2 restart

4. Apache apróság

Ha Apache webszervert használunk, akkor az AllowOverride és .htaccess használata minden lekérésre további fájlműveleteket jelent, ezért az általánosan használt beállításokat érdemes lehet a webszerver konfigurációs állományába (pl. /etc/apache2/sites-available/virtualhost_wildcard) átemelni.

5. SQLite adatbázis a memóriában

A Drupal 7 képes SQLite adatbázist használni a működéséhez. Ez egy, a MySQL-nél jóval kisebb erőforrás-igényű adatbáziskezelő, egyik jellemzője, hogy a teljes adatbázis egyetlen állományban tárolódik.
Ha ezt a fájlt a memóriában, vagyis ramdiszken tároljuk el, akkor többszörös sebességnövekedést érhetünk el. Azt ne felejtsük semmiképpen, hogy a számítógép leállítása vagy újraindítása során a ramdiszk tartalma elveszik, így csak átmeneti, kísérletezéshez használt adatokat tartsunk ott. Használhatjuk egy-egy művelet gyorsítására is, hiszen léteznek eszközök az egyes adatbázis-formátumok közti hatékony konverzióra.

Első lépésben szükségünk van a PHP SQLite támogatására:

$ sudo apt-get install php5-sqlite
$ sudo service apache2 restart

A legegyszerűbb módszer, ha felhasználjuk a rendszerünkön már meglévő ramdiszket, amely telepítéskor állítódik be. Ezt a /dev/shm/ könyvtárban találjuk, vagyis ha a Drupal telepítésekor az adatbázis-kapcsolat beállításánál az SQLite opciót választjuk, majd fájlnévnek megadjuk a /dev/shm/enoldalam.sqlite elérési utat, akkor a Drupal memóriába települ. Érdemes összehasonlítani a telepítés sebességét a klasszikus MySQL módhoz képest.

Persze készíthetünk külön ramdiszket is a következő módon, például az /mnt/ramdiszk/ könyvtárba. Ehhez a következő lépésekre van szükség:

$ sudo mkdir /mnt/ramdiszk
$ sudo mount none /mnt/ramdiszk -t tmpfs -o noatime,nosuid,nodev

Így már telepíthetjük is a rendszert, például a /mnt/ramdiszk/teszt.sqlite fájlt megadva.

Ha azt szeretnénk, ha ez a ramdiszk a fenti parancs kiadása nélkül, minden bekapcsoláskor automatikusan létrejöjjön, akkor nyissuk meg szerkesztésre az /etc/fstab fájlt:

$ sudo gedit /etc/fstab

Majd az állomány végére írjuk a következő sort:

tmpfs  /mnt/ramdiszk  tmpfs  defaults,noatime,nosuid,nodev  0  0

Sőt, az egész számítógép teljesítményét növelhetjük, ha ugyanebbe a fájlba felvesszük a /tmp könyvtárat is:

tmpfs  /tmp  tmpfs  defaults,noatime,nosuid,nodev  0  0

Ne feledjük, hogy így bár minden alkalommal létrejön a meghajtó, viszont továbbra is elveszik minden bekapcsoláskor és újraindításkor a tartalma, ezért csak megfelelő körültekintéssel helyezzünk rá adatokat. Érdemes megjegyezni még, hogy az ott tárolt adatok a memóriában foglalják el a helyet, vagyis kevés rendelkezésre álló memória esetén ne próbáljunk meg nagyobb fájlokat ott tárolni.

6. MySQL adatbázis a memóriában

Ha ideiglenesen szeretnénk felgyorsítani a MySQL adatbázis-műveleteket és vállaljuk az ezzel járó esetleges adatvesztést, az adatbázist átpakolhatjuk az előzőekben létrehozott ramdiszken. A példában a „teszt” nevű adatbázissal fogok dolgozni. Ezt az adatbázist hozzuk létre a phpMyAdmin, vagy más általunk ismert eszköz segítségével, majd végezzük el az alábbi műveleteket:

$ sudo service mysql stop
$ sudo mv /var/lib/mysql/teszt /mnt/ramdiszk/
$ sudo mkdir /var/lib/mysql/teszt
$ sudo mount none /var/lib/mysql/teszt -t tmpfs -o noatime,nosuid,nodev
$ sudo sh -c "mv /mnt/ramdiszk/teszt/* /var/lib/mysql/teszt/"
$ sudo service mysql start
$ sudo rmdir /mnt/ramdiszk/teszt

A parancsoknál mindenhol kiírtam az adatbázis nevét. Gyakorlatban annyi történt, hogy az adatbázis-szerver leállítása után az adatbázishoz tartozó fájlokat áthelyeztem egy átmeneti helyre, létrehoztam egy új ramdiszket a megfelelő helyen, majd a fájlok visszapakolása után elindítottam az adatbázis-szervert.

Ha szeretnénk a ramdiszkről az eredeti helyére visszaállítani az adatbázist, a következő módon tehetjük meg:

$ sudo service mysql stop
$ mkdir /mnt/ramdiszk/teszt
$ sudo sh -c "mv /var/lib/mysql/teszt/* /mnt/ramdiszk/teszt"
$ sudo umount /var/lib/mysql/teszt
$ sudo chown mysql:mysql /var/lib/mysql/teszt
$ sudo chmod 700 /var/lib/mysql/teszt
$ sudo mv /mnt/ramdiszk/teszt/* /var/lib/mysql/teszt
$ sudo service mysql start
$ sudo rmdir /mnt/ramdiszk/teszt

Ügyesen megírt szkriptekkel a fenti műveletek automatizálhatóak mind SQLite, mind MySQL esetén. Akár az is megoldható, hogy a gép leállításakor automatikusan elmentse a ramdiszken tárolt adatbázisokat, majd indításkor visszahelyezze azokat.
További lehetőség lehet még az adatbázisok SSD meghajtón való tárolása, amelyet a fenti módszerekhez hasonlóan lehet megoldani.

Hozzászólások

A legtöbb CMS-hez szerintem a tmp_table_size és table_cache MySQL értékek alacsonyak. Egy általános Drupal is 100+ táblát használ, de egy Magento 300-at, ha nem tévedek.

Az APC érték nagyjából jó, de nagyon figyelni kell, 40MB-nál kisebb érték egy default Drupal installációnál többet árt mint használ, egy közepes oldal 60-90MB között, de láttam olyat is, hogy 200MB kellett neki. :)

Kössz a postot, nagyon sok jó dolog van benne, viszont azt kifelejtetted, hogy ezeket az értékeket mi alapján lehet követni, hogy adott esetben jók e (pl. MySQLből lekérdezhető a runtime information - PHPMyAdmin szépen írja is, hogy melyik értékeket kell növelni, vagy mi a probléma. Az APC-hez meg van apc.php, amivel látod hogy mennyire van tele és mennyire töredezik szét a cache.)

Igazad van, bár érdemes nem elfelejteni, hogy itt nem nagy terhelésnek kitett oldalakról beszélünk, hanem olyanokról, amelyek a fejlesztés alatt gyakran változnak.

A „table_cache” értéke teljesen rendben van, a „tmp_table_size” értékét megemeltem a leírásban 16-ról 64 megabyte-ra.

Köszönöm a hasznos kiegészítéseidet! :)

A „max_user_connections” értéke 150-ről 25-re módosult, fejlesztői gépen bőven elég.

Nálam lett még olyan, hogy többször kaptam 13-as Errcode-al Can't read and write mysql üzenetet, mivel a tmp táblákat nem tudta kírni.

Ez kellett hozzá: http://stackoverflow.com/questions/2783313/how-can-i-get-around-mysql-er... a legtöbb pontos.

Még nem találkoztam ilyennel, akkor végül ez lett a megoldás? http://stackoverflow.com/questions/2783313/how-can-i-get-around-mysql-er...

Köszi az írást!
Nálam reklamált a rendszer ezzel az APC beállítással, igényelte a pontos méret beállítást.
apc.shm_size = 64M

Köszönöm a visszajelzést, inkább átírom így a leírást! :)

En az APC elleneben az eAcceleratort favorizalom, teljesitmenyben kb. ugyanannyit hoz, viszont egyreszt jol turi a hosting kornyezetet (is), masreszt pedig egyszerubb konfigolni. Cserebe nincs memcache-szeru mukodese...

Javítottam a PHP APC konfigurációt Ez volt eredetileg:
apc.stat = 1
apc.stat_ctime = 1
apc.rfc1867 = 1
apc.include_once_override = 0
apc.shm_size = 64
Ez lett helyette:
extension = apc.so
apc.shm_segments = 1
apc.num_files_hint = 2048
apc.rfc1867 = 1
apc.stat = 1
apc.shm_size = 64M

Eleg sokat segithet a innodb_file_per_table=1 beallitas az innodb-s szekcioban. Ez eleri azt, amit a MyISAM: minden tabla adata kulon fajlba kerul (ebben az esetben .ibd kiterjesztessel). Ez foleg azert fontos, mert tobb fajlban kvazi egyszerre lehet seekelni parhuzamosan, mig egy fajlnal azert valahol sorositani kell a funkciokat. Persze, egy a disk, szoval sorositas mindenkepp lesz, de minel lentebb van, annal kevesebb a performanciaveszteseg.

Nekem így néz ki a "mariadb-server.cnf" fájlom. Ha esetleg egy összehasonlítást majd csinálsz, hogy ez nálad, hogyan szerepel azt szivesen olvasnám. Nekem ezzel a konfiggal sikerült gyorsulást elérnem, a gépben 8 GB RAM van.

Op. rendszer: Fedora 22 Workstation, "mysql --version" kimenete:

mysql Ver 15.1 Distrib 10.0.19-MariaDB, for Linux (x86_64) using readline 5.1

max_connections = 75
table_cache = 256
max_allowed_packet = 128M
query_cache_size = 64M
query_cache_limit = 2M
tmp_table_size = 64M
max_heap_table_size = 64M
thread_cache_size = 4
sort_buffer_size = 2M
join_buffer_size = 2M
thread_stack = 192K

innodb_buffer_pool_size = 1024M
innodb_flush_log_at_trx_commit = 0
innodb_log_buffer_size = 4M
innodb_log_file_size = 256M
innodb_flush_method=O_DSYNC