Parantaa Levyn I/O-PHP-Sovellukset

Link: https://blog.rodneyrehm.de/archives/12-improving-disk-io-in-php-apps.html

Rodney Rehm

Vapauttamaan Smarty 3.1.0 – refactored useimmat Smarty on levyn käyttöä. Koska tämä optimointi syyskuusta 2011 pitää popping kysymyksiä Smarty foorumeilla, olen vihdoin tuntenut tarvetta selittää, mitä tein. Vaikka Smarty on syy löysin tämän, tämä viesti koskee PHP-yleensä, ei Smarty erityisesti. Tämä viesti on kyse pohjaa voit ymmärtää kaksi asiaa:

  1. Oma toiminta ei atomic
  2. Vältä accessing the hard disk unnecessarly

Varoitus:, Ellet tiedä, ja miksi teet sen, tämä sisältö on pidettävä haitallisia neuvoja!



Useita Prosesseja ja kilpailutilanteita

Olet luultavasti muistaa, että tietokoneeseen kytkeytyy eri prosesseja (käynnissä olevat sovellukset, …) ja SUORITTIMEN. Tämä tapahtuu niin, rinnakkainen suoritus prosesseja voitaisiin saavuttaa yhden SUORITTIMEN ytimen. Tämä on mitä me kutsumme Multitasking ja samat periaatteet koskevat tietokoneita, joissa on enemmän kuin yksi PROSESSORI ydin.

Tämä tarkoittaa sitä, että program (PHP script) ei suoriteta peräkkäin. Joitakin ohjelma on toteutettu, niin se on keskeytetty, niin jotain muuta voi ajaa, sitten se jatkuu toteuttamista, sitten se pysähtyi jälleen, ja niin edelleen.

Joissakin kielissä voimme kertoa suorittamista host käsitellä joukko-operaatioiden yhtenä toiminta – vaadimme, että atomisuuden. PHP ei tunne tätä käsitettä. Se on turvallista sanoa, että PHP-skripti voidaan hajottaa milloin tahansa tiettynä toimintaa.

Ellei sinulla on ollut mahdollisuus työskennellä melko korkea-liikennettä sivustoja, jotka olet todennäköisesti koskaan nähnyt kilpailu toiminta. Kisa kunto on mitä me kutsumme, kun kaksi (rinnakkain suorittamista) prosessit tekevät ristiriitaisia asioita. Esimerkiksi Prosessi 1 kirjoittaa tiedoston /tmp/file.txt, kun Prosessi 2 on yrittänyt poistaa, että sama tiedosto.

Näiden prosessien ei tarvitse suorittaa samassa yhteydessä. Kun Prosessi 1 voi olla PHP-skripti, Prosessi 2 voi olla shell script laukaisi Cron, tai joitakin opasta rm /tmp/file.txt SSH: n kautta.

Tiedostojen Lukitus

Jos haluat estää näiden rodun ehtoja, meillä on oikeus lukita tiedostoja. Kun tiedosto on lukittu Prosessi 1 ja Prosessi 2 on yrittää hankkia lukko, Prosessi 2 on estää suorituksen, kunnes lukko julkaisi Prosessi 1. PHP tarjoaa tätä toiminnallisuutta flock().

flock() on pari ongelmaa, vaikka. Yhdelle se toimii vain resources, joten sinun täytyy olla tiedosto avataan fopen() ennen saada lukko. Myös flock() ei onnistu tietyille tiedostojärjestelmiä, kuten FAT-tai NFS-protokollan avulla. Päälle, että se näyttää melko naurettavaa jos haluat avata tiedoston, vain saada lukko, vain poistaa tiedoston.

Joten tosielämässä, jossa PHP-skripti ei tiedä, mikä tiedostojärjestelmä on käytössä, flock()ei auta.

Mahdollinen kilpailutilanne

Ensi silmäyksellä, seuraava koodi pidetään hyvää koodia, kun me tarkistaa, jos tiedosto on olemassa ennen linkityksen poistaminen. Tämä on koska unlink() kysymyksiä E_WARNING, kun se ei löydä tiedostoa, linkitys:

$filepath = “/tmp/some.file”;
if (file_exists($filepath)) {
unlink($filepath);
}

 

Mutta me muistamme, että PHP ei ole atomic toimija ja käsikirjoitus voidaan hajottaa milloin tahansa:

$filepath = “/tmp/some.file”;
if (file_exists($filepath)) {
// <- potential race condition
unlink($filepath);
}

Ottaen huomioon edellä koodi on Prosessi 1, voisimme kohdata seuraava ehto:

*Process 1*: file_exists("/tmp/some.file")
*Process 2*: unlink("/tmp/some.file")
*Process 1*: unlink("/tmp/some.file") -> E_WARNING, file not found!

Välillä tarkistaa, jos tiedosto on olemassa, ja itse asiassa sen poistamista, toinen prosessi oli mahdollisuus poistaa tiedoston. Nyt unlink() meidän script kysymyksiä E_WARNING unlink() epäonnistui.

Lieventämään kilpailutilanne

Älä pelkää, PHP tietää, kaikkivaltias @ hiljaisuus-operaattori. Prefixing toiminto soittaa kanssa @tekee PHP sivuuttaa mahdolliset virheet myöntämä toiminto soittaa soveltamisalaan. Seuraava koodi estää E_WARNING – liikkeeseen, koska rotu kunnossa (tai jokin muu vika, että asia):

$filepath = “/tmp/some.file”;
if (file_exists($filepath)) {
@unlink($filepath);
}

Kanssa, että vähän @ olemme avasi oven hieman yksinkertaistaa koodia. Koska olemme esittävien file_exists() unlink() ei ole antaa mitään varoituksia, ja @unlink() ei ole antaa mitään varoituksia, voimme yksinkertaisesti pudota file_exists():

$filepath = “/tmp/some.file”;
@unlink($filepath);

Et voila, meillä on onnistuneesti lieventää kilpailun edellytys. Ja tekemällä näin, meidän on vahingossa vähentää Levyn I/O 50%.

Vähentää Levyn I/O (tilastot)

Lisäksi vaikutuksia rodun ehtoja, ojitusten file_exists() on muita etuuksia vähentää stat puhelut. Aina, kun sinun täytyy koskettaa HDD, kuvitella Ferrari-sovellus lyömällä jarrut. Verrattuna CPU kiintolevyn (kyllä, jopa SSDs) ovat kilpikonnia kahlittu rock. Joten perimmäisenä tavoitteena on välttää koskettaa file system aina kun se on mahdollista.

Harkitse seuraavia hyvin koodattu ohjelma tunnistaa, jos tiedosto on olemassa, ja kun se on muutettu viimeksi:

$filepath = “/tmp/some.file”;
$file_exists = file_exists($filepath);
$file_mtime = null;
if ($file_exists) {
$file_mtime = filemtime($filename);
}

Tiesitkö, että filemtime() palaa false (ja kysymyksiä, E_WARNING), jos se ei voi löytää tiedosto? Joten, miten kääntää asiat ja ojitusten file_exists():

$filepath = “/tmp/some.file”;
$file_mtime = @file_mtime($filepath);
$file_exists = !!$file_mtime;

Custom Virheiden käsittelyä

Kuten mainittiin aluksi, ojitusten file_exists() oli tehnyt Smarty 3.1.0. Teimme lukuisia testejä ja viitearvot ja tuli siihen tulokseen, että meidän olisi typerää olla tekemättä sitä. Ja siinä vaiheessa ajattelin, että kukaan ei koskaan huomaa. Se olisi ollut totta, olisi se ollut set_error_handler().

set_error_handler() voit rekisteröidä omia tapa käsitellä virheitä. Se on aika siisti ajaa tiettyjä virheitä tietokantaan tai lähettää sähköposteja tai jotain sellaista. Se antaa sinulle ehdoton valta jokainen ilmoitus tai varoitus. Jopa ne, jotka olisi ollut naamioitu error_reporting() tai @ – operaattori.

Ilmeisesti jotkut ihmiset rekisteröidä custom error handlers saada KAIKKI VIRHEET. Jopa peittää niitä. Jotkut kehittäjät eivät ymmärrä vihjeitä docs, muut tekivät sen tarkoituksella. Aikeet syrjään, nämä huonosti suunniteltu virhe käsittelijät rikkoa tapa odotamme PHP töihin. Yhtäkkiä virheet, kuten virhe error in 'test.php' on line 2: unlink(/tmp/some.file): No such file or directory (2) alkoi popping.

Heidän mielensä Smarty oli huonosti. Kun kaikki sen koodi oli nostaa E_WARNING: n koko paikka. He eivät tiedä (ja en välitä) siitä, parannuksia olemme tehneet. He eivät halua “korjata” niiden virhe käsittelijät, koska ne ei näe niitä rikki. Niin Smarty 3.1.2 esittelin Smarty::muteExpectedErrors() – custom error handler, että se olisi proxy niiden käsittelijät, suodattaa virheitä Smarty todella odotetaan tapahtuvan.

Varoitus (lisätty Jan 10. 2013)

Tämä viesti ilmestyi hakkeri uutiset, liipaisu pari kommentit. Lisäsin varoituksen päälle post. Se sanoi, tässä on muutamia syitä, valitsin tämän reitin:

  • en todellakaan välitä, jos tiedostoa ei voinut käyttää, koska etuoikeus (tai muu) syistä. Siellä on maailmanlaajuinen-järjestelmät-tarkista huolehtia, että. Tämä koodi olettaa, että kaikki on hyvin. Jos se ei ole, järjestelmät-tarkista kertoa meille, mitä on tekeillä.
  • Tämä on pienin määrä koodia tarvitaan “vain tehdä työtä” yli kaikki setup.
    • Riippumatta siitä, kuinka monta fyysistä koneet käynnissä samanaikaisesti.
    • Riippumatta tiedostojärjestelmä käyttää (kyllä, jotkut eivät tarjoa lukitus)
    • Riippumatta taajuus ja samanaikaisuuden yksittäinen tiedosto on koskettanut
    • Riippumatta PECLs joitakin ympäristö voi olla asennettu

Tämä on palo-ja unohtaa lähestymistapaa. Tämä on jotain, voit tehdä, kun välimuistia, kun yksinkertaisesti kiinnosta noin eheys ja pysyvyys.

Tekisin mitä tahansa edellä mainituista, jos en välittänyt tiedot ja voisi määritellä ympäristö? HELVETTI EI!, Mutta sitten, en varmaan olisi käyttää PHP joko…

Leave a Reply

Your email address will not be published. Required fields are marked *