Milyen részegen elkövetett cselekedeteket szégyell nagyon? Pánikbetegségek teljesítménytesztének eredményei

SZÍV NEURÓZIS (CARDIOFÓBIA). A fóbia sajátos formája a pánik szindrómával együtt a kardiofóbia, amelyet különösen jellegzetes klinikai képe és jelentős gyakorisága miatt érdemes leírni. Főleg fiataloknál, gyakrabban férfiaknál, de gyermekeknél is előfordul.

Rohamokban fellépő szorongásos állapotok, amelyben a betegek attól tartanak, hogy a szív leáll és meghal, előfordulhat szomatikus betegség jelenléte nélkül is. A következő roham elején hányinger, szédülés, belső szorongás és a szív enyhe összenyomódása jelenik meg.

Sok esetben azonban minden figyelmeztetés nélkül súlyos roham lép fel: szívdobogás az egész testben érezhető, némi növekedés vérnyomás, erős kompresszió- és szorító érzés a szív területén, levegőhiány, izzadás, szédülés és ájulás (de nem eszméletvesztés), testszerte remegés és alapvető félelem. A beteg azt hiszi, hogy a szíve pillanatok alatt leáll, és meghalt. Ez az önpusztítástól és a haláltól való félelem. Nál nél erős izgalom a betegek rohangálnak és segítségért könyörögnek. Ha autóban utazás közben félelemroham lép fel, a beteg kénytelen megállni és szünetet tartani.

Az első támadás után fóbiás fejlődés következik be. A betegek elvesztik lelki egyensúlyukat, állandó félelemben élnek, várják a következő rohamot vagy halált, átélik a félelemtől való félelmet (a várakozástól való félelem, fóbia). Ugyanakkor nem segíti őket a terapeuta üzenete arról normál mutatók szívműködést, sem azt a meggyőzést, hogy a korábbi rohamoknak nincs következménye. A rohamok gyakorisága és a közöttük lévő intervallumok szabálytalanok. A páciens időközönként gondosan figyelemmel kíséri szívműködését, szabályozza a pulzusát és rögzíti annak legkisebb eltéréseit. A véletlenszerű extraszisztolákat egy reménytelen kimenetelű betegség vitathatatlan jeleiként érzékeli.

A betegek óvatosan figyelnek más vegetatív megnyilvánulásokat, valamint közérzetük enyhe ingadozásait. A betegek vigyáznak magukra, alig mernek járni, törekednek minden stressz, aggodalom és mindenekelőtt a nehéz helyzetek megszüntetésére a támadás megelőzése érdekében (kitérő magatartás). A halálfélelem helyett sok esetben egyre inkább megjelenik a félelemtől és a félelmet kiváltó helyzetektől való félelem.

MEGJELENÉS FELTÉTELEI. Az első kardiofóbiás roham oka gyakran akut konfliktus és túlfeszítettség, elszakadás és csalódás, magány és elhagyatottság, valamint szorongás egy közeli személy szívhalála esetén.

Aggasztó tényezővé válik annak tudata, hogy szívhalál mindig előfordulhat, még fiatalok és egészségesek esetében is. A kávé és a nikotin intenzív fogyasztása elindíthatja ezt a folyamatot. A kezdet gyakran gyerekkorból származik. Többnyire elkényeztetett és eltartott gyermekek érintettek, kifejezett anyától való függéssel, nagyrészt ambivalens attitűdökkel: egyrészt a szeretet elvárása, másrészt agresszív késztetésekkel járó függetlenségvágy, másrészt a kötődésről és a kötődésről szóló, egymásnak ellentmondó fantáziák. elválasztás. Az ilyen attitűdök különösen veszélyesek, ha a kapcsolatok megszakadnak, elválások és csalódások következnek be. A szívfób gyakran az elválástól való félelemben él, mielőtt rájön, hogy ezt akarja, és fél tőle. Rendszeresen felmerülnek közös problémák a szülőkkel, konfliktusok a partnerekkel.

KEZELÉS
Ha be akut állapot az orvos jelenléte és a vele folytatott beszélgetés nem okoz javulást, nyugtatók vagy béta-blokkolók javasoltak. Más, félelmetes neurózisban szenvedő betegekhez hasonlóan sok fóbiás próbál alkohollal öngyógyítani; de hatása nem kielégítő, és nagy az alkoholfüggőség veszélye. A gyógyszeres terápia csak kiegészítő gyógymód, elsősorban akut esetekben, valamint kezdeti hatékony gyógymód.

A pszichoterápia meghatározó. Minél előbb kezdődik, annál jobb. Az okok tanulmányozása és konfliktushelyzetek közvetlenül az első kardiofóbiás rohamok után megállíthatják a későbbi fóbiás fejlődést. A későbbi kezelés nehezebb, és hosszú távú pszichoterápia szükséges.

Ezen és más szorongásos zavarok esetén különösen indokolt a viselkedésterápia (arousal konfrontáció, kognitív terápia, önbizalom tréning). A szorongáselkerülő tréning sajátossága, hogy deszenzitizációs modellen működik (a mindennapi helyzetek megfelelő feltételeire), a szorongáskezelési tréning pedig a fóbiás szituációba (árvízbe) való kényszermerülést és a megküzdési stratégiák kialakítását alkalmazza. Súlyos szorongásos zavarok esetén el kell végezni klinikai kezelés a pszichoterápia különféle modelljei segítségével.


02.10.2011, 21:27

Amiért megvert egy srácot és felakasztotta a pólóját egy fára.És pár kilométeren keresztül egyedül üldözte az idióta srácot és amikor elesett elkezdett pisilni.De megérdemelték.

Egy nagy társaságban zaklattam egy lányt, és azt mondtam, hogy a barátja megvette egy akción, és a kisbuszban banánt is evett, és mindenkinek az ölébe tettem a héját, és én is folyamatosan leszbikus műsorokat szervezek a bárokban, egyszer benéztem a szoknya alá. a pincérnők közül egy VIP klubban, és megjegyzéseket fűzött hozzám, de általában nagyon részeg vagyok, azonnal elfelejtem, hogy szeretem az embereket, akik azt mondják, ha felébredsz és szégyelled, de nem emlékszem, miért pont rólam

Az utolsó részegség után elegem van:
1. kiabált az erkélyről a srácnak, hogy "szívj meg"
2. evett egy cigarettát
3. almát dobott
4. felhívta a srácot, és azt mondta neki, hogy nem fogok neki durva módon szexelni
5. grapefruitlében fulladt bikák
6. felhívta anyukámat és közölte, hogy józan vagyok
7. Megkértem a barátom pasiját, hogy hozzon nekünk bort.
8. Elpisiltem a wc mellett, mivel 2-en voltak - rosszat választottam, majd elestem
9. kiesett a fürdőből

Egyszer késsel rohangáltam a lakásban a férjem után, pedig ittam pár pohár pezsgőt. Másnap reggel megijedtem – mi lenne, ha megütném egy késsel, de úgy döntöttem, megijesztem. És nem tudom, miért kaptam ekkora rúgást!

Mindig ugyanaz a helyzet, hogy amikor berúgok, kimegyek a parkba bunkót keresni, hogy kigúnyoljam őket, vagy létrehozom ezeket a témákat a fórumon... reggel arra gondolok, hülye vagyok?...

Egyszer rám ütött egy srác, és annyira részeg voltam, hogy elkezdtem neki népiesen magyarázni, hogy nem lesz semmi baj, mert én „Bloody Mary” vagyok (ők voltak), és ez a becenév annyira a lelkembe süllyedt, hogy majdnem Mindenkinek kiabálta, akivel találkoztam: „Én vagyok Bloody Mary”, szerencsére nem a szülővárosomban volt

-* felhívta az exemet, elmondott mindent, amit gondolok róla
*Felhívta a kedvesemet, elmondta, mennyire szeretném őt
*shawarmát evett fóliával
* káromkodott egy srácra, akit egy klubban ismertem meg, bár segített és hozott vizet
*egy versenyen sztriptízt táncolt egy klubban, második helyezést kapott
*jeget dobott egy idegenre
*az emberem barátja egy sárga Hummert vezet. Koreában még nem láttam ilyet. amikor mindannyian együtt mentünk bulizni. Kihajoltam az emberem autójából, és az előtte haladó Hummerre mutatva kiabáltam, hogy ez az autó a barátom.
*tegnap a klubban voltam. amikor reggel taxival mentem haza, azt mondtam a sofőrnek: [koreai fordítás. szó szerint!] „Az étel, amit ettem, azt mondta nekem, hogy ki akar jönni!”
*Van egy mongol barátom is. Felmásztam a hátára, kényszerítettem, hogy a hátán vigyen, és az egész utcán kiabáltam, hogy ő az én mongol lovam
de általában még sok minden volt, nem fogsz emlékezni...

Reggel 4 órakor írtam a srácnak " Jó éjszakát, Drága"

A barátaimmal berúgtunk a konyakból, mindenki hazament, én meg hülyén hívtam egy taxit (3 óra volt) és elmentem a volt pasimhoz, akivel 4 hónapja szakítottunk (barátok maradtunk). nem emlékszem, hogyan jutottam be a bejáraton, jutottam a lakásába, betörtem az ajtót és kiabáltam, hogy MARRY ME MARAT, szegény megőrült, hazavonszolt egy hideg zuhany alá, adott erős teát. Két óra elteltével elmentem, majd amikor rájöttem, hogy mit tettem, IGAZÁN SZÉGYEN VOLTAM.Utána kibékültünk és még mindig együtt vagyunk. Utána nem iszom még egy pohár pezsgőt.


...

02.10.2011, 22:09

A meggyilkolt nő egy sráccal sétált a kertben, és akkor úgy tűnt, valahogy megbántott azzal, hogy néhány lépéssel előttem ment, és nem mellettem. Megsértődtem és felmásztam egy fára, de ő észre sem vette... másfél óráig rohangált a kertben és keresett... én pedig nyugodtan elájultam a fán és aludtam reggelig. ...
...
De reggel nem jutott eszembe azonnal, hogyan kötöttem ki az ágakon. A fenébe, milyen volt utána
;D;D;D

Értelmezés

02.10.2011, 22:42

Szégyellem magam bizonyos józan cselekedetek miatt :) De ez közelebb áll a filozófiához. Részegen... sok minden mulatságos volt, zavarba ejtő... nem, bocsánat)))))

Elena Lotus

02.10.2011, 23:17

Tegnap, miután rájöttem, hogy a telefonom (OOO!!!) már nem az enyém, berúgtam.erősen.és (aki ismer, ne mondja, hogy úgy iszom, mint az egér) aztán csináltam valamit... csak a közeli barátoknak, nagy titkot aztán meggondolom, hogy kinek mondjam el... A Paberti étterem ismét sokkolt.Most a képgalériát nézegetem abban a reményben, hogy mi is történt:(de én Nem szégyellem... nem... Csak azt hittem, hogy rendes vagyok.

02.10.2011, 23:31

;D;D;D
Mindig is fenntartottam, hogy a nénik ne igyanak!!! MINDENKI!!!;)

..;D;D;D igazat mondasz

02.10.2011, 23:36

A részeg nő olyan, mint egy kínai kabát: puha és illeszkedik.
Galygin

Elena Lotus

02.10.2011, 23:41

De a férfiak szeretik az igent?Mindenki tud inni. és nénik és bácsik...csak vigyázni kell...ma nem fáj a fejed...fáj a lelked...isz egy italt?Ez csak egy ördögi kör;)

03.10.2011, 00:15

Igyál bármit és mindent, amíg fiatal és egészséges vagy :)

03.10.2011, 01:48

szelektíven a női fórumról lopva :)

Majdnem bepisiltem a szennyeskosárba anyám előtt..... összezavarodtam a wc-vel.... hopp....

A meggyilkolt nő egy sráccal sétált a kertben, és akkor úgy tűnt, valahogy megbántott azzal, hogy néhány lépéssel előttem ment, és nem mellettem. Megsértődtem és felmásztam egy fára, de ő észre sem vette... másfél óráig rohangált a kertben és keresett... én pedig nyugodtan elájultam a fán és aludtam reggelig. ...
...
De reggel nem jutott eszembe azonnal, hogyan kötöttem ki az ágakon. A fenébe, milyen volt utána

Az erkélyen medencék és cserepek voltak, ahol anyám hagymát termesztett. Én „gyengén” piszkáltam mindegyik edényben =((((a saját ágyamban ((persze nem mondom el anyámnak, dobj be mindent a fenébe). a szemét, itt vagyok úgy döntöttem, hogy felpiszkálom a zöldjét!Hát, tovább nőtt, aztán bekerült a salátába

03.10.2011, 05:35

A barátaimmal berúgtunk a konyakból, mindenki hazament, én meg hülyén hívtam egy taxit (3 óra volt) és elmentem a volt pasimhoz, akivel 4 hónapja szakítottunk (barátok maradtunk). nem emlékszem, hogyan jutottam be a bejáraton, jutottam a lakásába, betörtem az ajtót és kiabáltam, hogy MARRY ME MARAT, szegény megőrült, hazavonszolt egy hideg zuhany alá, adott erős teát. Két óra elteltével elmentem, majd amikor rájöttem, hogy mit tettem, IGAZÁN SZÉGYEN VOLTAM.Utána kibékültünk és még mindig együtt vagyunk. Utána nem iszom még egy pohár pezsgőt.

Ez eléggé igazi történet szerelem.
És az ivás előnyeiről is.

(Igyál, lányok, és eljön a boldogság.)

Jó néhány megoldás lebeg a weben a többszálú PHP emulálására. Leggyakrabban fork-on alapulnak, de vannak változatok is a témára curl, proc_open stb.

Valamilyen okból kifolyólag az összes lehetőség nem felelt meg nekem, és meg kellett írnom a saját megoldásomat.
A következő követelményrendszerem volt:

  • Villák használata;
  • Szinkron mód az interfész megőrzésével a szükséges bővítmények hiányában;
  • Gyermekfolyamatok újrafelhasználása;
  • Teljes adatcsere a folyamatok között. Azok. futtasson argumentumokkal, és kapja meg az eredményt, ha végzett;
  • Az események cseréjének képessége a gyermek „szál” folyamat és a fő folyamat között működés közben;
  • Dolgozzon szálkészlettel az újrafelhasználás, az argumentumok átadása és az eredmények elérése mellett;
  • Futásidejű hibák kezelése;
  • Munkavégzési időtúllépések, munkaszálonkénti várakozás, inicializálás;
  • Maximális teljesítmény;
Az eredmény egy könyvtár AzaThread(régi név - CThread).

A türelmetlenek kedvéért itt egy link a forráshoz:
github.com/Anizoptera/AzaThread

Leírás

Az AzaThread egyszerű felületet biztosít a szálosztályok létrehozásához. Amelyek valójában külön folyamatokat használnak az aszinkron működéshez, de ezzel nem szabad törődni. Küldhet eseményeket egy szálból, visszaküldheti az eredményeket, sokszor használhat egy szálat, amelyhez indítási argumentumot adva át, vagy létrehozhat egy 16 szálból álló készletet, amely úgy rakja össze a feladatait, mint a forró sütemények, anélkül, hogy odafigyelne arra, hogy a munka különböző területeken történik. folyamatokat.

Ezenkívül egyszerűen tesztelheti a könyvtár teljesítményét különböző módokban, ha kiválasztja az optimális szálszámot, és kiválasztja a folyamatok közötti adatátvitel lehetőségét kifejezetten az Ön konfigurációjához.

A teljes működéshez a következő bővítmények szükségesek: élősködő, pozixÉs pcntl.

A könyvtár a LibEventet és a párosított socketeket használja a folyamatok közötti kommunikációhoz. 5 adatátviteli lehetőséget támogat (érvek, eredmények és eseményadatok)!

A lehetőségeket azonnal bemutatom teljesítményadatokkal. Nyolc szálból álló készlettel tesztelve Intel Core i7 2600K 3,40 Ghz-en (Ubuntu 11.04 VMware virtuális gépen). Megadjuk a teszt 10 ismétlésének átlagos eredményeit jps-ben (jobs per second – azon feladatok száma, amelyek egyszerűen csak érveket fogadnak és adatokat küldenek másodpercenként).

Az aljzatokkal való munkavégzéshez szükséges bővítmény automatikusan kiválasztásra kerül. Ha elérhető, akkor a kiterjesztés használatos aljzatok, ami jobb teljesítményt biztosít. Ellenkező esetben használni fogják folyam.

A gyermekfolyamat az összes elérhető jelre figyel. Alapértelmezés szerint mindegyiket (kivéve SIGWINCH és SIGINFO) leállítás követi. De ez könnyen felülírható, ha létrehozunk egy metódust a szál osztályban a jel nevével. Például sigWinch.

A szülő folyamatban alapértelmezés szerint minden jelet elfog a rendszer. Ez az osztály paraméter beállításával módosítható hallgassa MasterSignals hogy hamis. Ebben az esetben csak a SIGCHLD kerül feldolgozásra. Könnyen hozzáadhatja saját kezelőit, ha létrehoz egy statikus metódust m< имя сигнала > . Például mSigTerm.

Ha egy gyermekfolyamat valamilyen oknál fogva elhal, az osztály automatikusan elágazik egy új feladat indításakor. Ez észrevétlenül történik, és egyáltalán nem kell gondolkodni rajta. A példányt egyszerűen nem kell újra létrehozni bármilyen hiba esetén.

A gyermekfolyamat időszakonként ellenőrzi a szülőfolyamat meglétét. Ha hirtelen meghal, a gyermek automatikusan véget ér.

A szál vagy szálkészlet által használt összes erőforrás automatikusan törlődik a destruktor meghívásakor. De a metódus meghívásával erőszakkal törölhetők takarítás. Ebben az esetben a szál/medence többé nem használható.

Nál nél szabványos beállításokat a szál előzetesen inicializálva van, közvetlenül az osztály létrehozásakor. Ha beállítja a paramétert előfork hamisra, akkor az elágazás csak a feladat indításakor fog bekövetkezni.

Általában elég sok testreszabható paraméter létezik. A gyermekfolyamat nevének megváltoztatása egy villa után (paraméter pName konstruktor), időtúllépés a feladat időtartamára ( timeoutWork), időtúllépés arra a maximális időtartamra, amely alatt egy gyermekfolyamat várhat a feladatokra ( timeoutMaxWait), időtúllépés az inicializálás előtti időhöz ( timeoutInit), socket olvasó puffer mérete ( pipeReadSize, pipeMasterReadSize).
Letilthatja a többfeladatos módot a szálaknál ( multitask). Ebben az esetben minden alkalommal, amikor a feladat befejeződik, a gyermekfolyamat elhal, és újra elágazik a következő indításhoz. Ez észrevehetően csökkenti a teljesítményt.

A kódot tesztek borítják és részletesen dokumentálják, a felhasználási példák megtekinthetők és futtathatók a fájlban példa.php.
Több összetett példák hibakezeléssel az egységteszt kódjában látható.

Van egy hibakeresési mód, amiben nagyon részletes információk hogy pontosan mi történik és hol.

Példák a felhasználásra

A fő jellemző a maximális egyszerűség. Ha csak egy külön "szálban" akarsz futtatni valamit, elég a következő kód:
class PéldaThread kiterjeszti Szálat ( védett függvény process() ( // Van itt néhány munka ) ) $thread = new PéldaThread(); $thread->wait()->run();
Ha minden szükséges a teljes értékű munkához, akkor a feladat aszinkron módon történik. Ha nem, akkor minden továbbra is működik, de szinkron módban.

Egy paraméter átadásával és az eredmény megszerzésével a kód kissé bonyolultabbnak tűnik:
class PéldaThread kiterjeszti Thread ( védett függvény process() ( return $this->getParam(0); ) ) $thread = new PéldaThread(); $thread->wait()->run(123); $eredmény = $thread->wait()->getResult();

Hasonlóképpen, enyhe kézlegyintéssel hozzáadjuk az eseményfeldolgozást a folyamból:
class PéldaThread kiterjeszti a szálat ( const EV_PROCESS = "folyamat"; védett függvény process() ( $events = $this->getParam(0); for ($i = 0; $i< $events; $i++) { $event_data = $i; $this->trigger(self::EV_PROCESS, $esemény_adatok); ) ) ) // További érv. $kiegészítő argumentum = 123; $thread->bind(PéldaThread::EV_PROCESS, function($esemény_neve, $esemény_adata, $additional_arg) ( // eseményfeldolgozás), $additionalArgument); $események = 10; // a szál által generált események száma // Annak elkerülése érdekében, hogy az első hívás előtt kézzel várjon a szálra, // felülírhatja a preforkWait tulajdonságot TRUE értékre a leszármazott osztályban $thread->wait(); $szál = new PéldaThread(); $thread->run($events)->wait();

És végül egy nyolc szálból álló készlet használata futásidejű hibakezeléssel:
$threads = 8 // Szálak száma $pool = new ThreadPool("ExampleThread", $threads); $szám = 25; // Feladatok száma $left = $num; // A fennmaradó feladatok száma ( // Ha vannak szabad szálak a készletben // És még mindig vannak végrehajtandó feladatok, míg ($pool->hasWaiting() && $left > 0) ( // Indításkor azt kapjuk a szál azonosítója $threadId = $pool->run(); $left--; ) if ($results = $pool->wait($sikertelen)) ( foreach ($results mint $threadId => $eredmény) ( / / Sikeresen befejezett feladat // Az eredmény azonosítható // a szál azonosítójával ($threadId) $num--; ) ) if ($sikertelen) ( // Végrehajtási hibák kezelése. // A feladat sikertelennek minősül // ha az utódfolyamat végrehajtás közben meghalt vagy // lejárt a feladatvégrehajtási időkorlát foreach ($sikertelen mint $threadId) ( $left++; ) ) ) while ($num > 0); // Leállítja az összes gyermekfolyamatot. Megtisztítjuk a medence által felhasznált erőforrásokat. $pool->cleanup();

Teljesítményteszt eredményei

A teszteket két gépen futtattam Ubuntu 11.04-el.
Az első az Intel Core i3 540 3,07 Ghz
A második az Intel Core i7 2600K 3,40 Ghz (az Ubuntu VMware virtuális gépen fut)

Az eredményeket egyszerűen azért mutatom be, hogy értékelni tudja a termelékenység növekedését.
Ezek ismét egy 10 tesztismétlésből álló sorozat átlagos eredményei jps-ben (jobs per second – feladatok száma másodpercenként).

Feladatként a szálak a következő szemetet hajtják végre:
for ($i = 0; $i< 1000; $i++) { $r = mt_rand(0, PHP_INT_MAX) * mt_rand(0, PHP_INT_MAX); }
Az első eredmény szinkron üzemmódban (villák nélkül) látható.
Az első konfigurációnál nem próbáltam ki a 18 és 20 szálat, mivel már 12-re a teljesítmény csökkenni kezdett.

A szálak száma Első konfiguráció Második
0 553 763
1 330 669
2 580 1254
4 1015 2188
8 1040 2618
10 1027 2719
12 970 2739
16 958 2904
18 - 2830
20 - 2730

Vagyis processzortól függően 2-4-szeresére vagy még többre nő a teljesítmény!

A kód, amely egy tesztsorozatot futtat a szükséges paraméterekkel, a fájlban található examples/speed_test.php. Így egyszerűen tesztelheti a teljesítményt, és kiválaszthatja magának az optimális számú szálat.

Jó néhány megoldás lebeg a weben a többszálú PHP emulálására. Leggyakrabban villákon alapulnak, de vannak változatok a témára vonatkozóan is becsavar, proc_open stb.

Az összes lehetőség, amivel találkoztam, ilyen vagy olyan okból nem felelt meg nekem, és meg kellett írnom a saját megoldásomat. A következő követelményrendszerem volt:

  • Villák használata;
  • Szinkron mód az interfész megőrzésével a szükséges bővítmények hiányában;
  • Gyermekfolyamatok újrafelhasználása;
  • Teljes adatcsere a folyamatok között. Azok. futtasson argumentumokkal, és kapja meg az eredményt, ha végzett;
  • Az események cseréjének képessége a gyermek „szál” folyamat és a fő folyamat között működés közben;
  • Dolgozzon szálkészlettel az újrafelhasználás, az argumentumok átadása és az eredmények elérése mellett;
  • Futásidejű hibák kezelése;
  • Munkavégzési időtúllépések, munkaszálonkénti várakozás, inicializálás;
  • Maximális teljesítmény.

Az eredmény az AzaThread könyvtár (korábban CThread) lett.

Leírás

Az AzaThread egyszerű felületet biztosít a szálosztályok létrehozásához. Amelyek valójában külön folyamatokat használnak az aszinkron működéshez, de ezzel nem szabad törődni. Küldhet eseményeket egy szálból, visszaküldheti az eredményeket, többször is használhat egyetlen szálat, indítási argumentumokat adva át neki, vagy létrehozhat egy 16 szálból álló készletet, amely úgy rakja össze a feladatait, mint a forró sütemények, anélkül, hogy odafigyelne a munka folyamatára. különböző folyamatokban.

Ezenkívül egyszerűen tesztelheti a könyvtár teljesítményét különböző módokban, ha kiválasztja az optimális szálszámot, és kiválasztja a folyamatok közötti adatátvitel lehetőségét kifejezetten az Ön konfigurációjához.

A teljes működéshez a következő bővítmények szükségesek: élősködő, pozixÉs pcntl.

A könyvtár a LibEventet és a párosított socketeket használja a folyamatok közötti kommunikációhoz. 5 adatátviteli lehetőséget támogat (érvek, eredmények és eseményadatok)!

A lehetőségeket azonnal bemutatom teljesítményadatokkal. Nyolc szálból álló készlettel tesztelve Intel Core i7 2600K 3,40 Ghz-en (Ubuntu 11.04 VMware virtuális gépen). Megadjuk a teszt 10 ismétlésének átlagos eredményeit jps-ben (jobs per second – azon feladatok száma, amelyek egyszerűen csak érveket fogadnak és adatokat küldenek másodpercenként).

A bővítmény automatikusan kiválasztásra kerül az aljzatokkal való munkavégzéshez. Ha elérhető, akkor a kiterjesztés használatos aljzatok, ami jobb teljesítményt biztosít. Ellenkező esetben használni fogják folyam.

A gyermekfolyamat az összes elérhető jelre figyel. Alapértelmezés szerint mindegyiket (kivéve SIGWINCH és SIGINFO) leállítás követi. De ez könnyen felülírható, ha létrehozunk egy metódust a szál osztályban a jel nevével. Például sigWinch.

A szülő folyamatban alapértelmezés szerint minden jelet elfog a rendszer. Ez megváltoztatható a listenMasterSignals osztályparaméter false értékre állításával. Ebben az esetben csak a SIGCHLD kerül feldolgozásra. Könnyen hozzáadhatja saját kezelőit az m nevű statikus metódus létrehozásával<имя сигнала>. Például mSigTerm.

Ha egy gyermekfolyamat bármilyen okból elhal, az osztály automatikusan elágazik egy új feladat indításakor. Ez észrevétlenül történik, és egyáltalán nem kell gondolkodni rajta. A példányt egyszerűen nem kell újra létrehozni bármilyen hiba esetén.

A gyermekfolyamat időszakonként ellenőrzi a szülőfolyamat meglétét. Ha hirtelen meghal, a gyermek automatikusan véget ér.

A szál vagy szálkészlet által használt összes erőforrás automatikusan törlődik a destruktor meghívásakor. De a tisztítási módszer meghívásával erőszakkal megtisztíthatók. Ebben az esetben a szál/medence többé nem használható.

Normál beállításokkal a szál előzetesen inicializálódik, azonnal az osztály létrehozásakor. Ha a prefork paramétert false értékre állítja, akkor a fork csak a feladat indításakor fog bekövetkezni.

Általában elég sok testreszabható paraméter létezik. Az utódfolyamat nevének megváltoztatása az elágazás után (a konstruktor pName paramétere), időtúllépés a feladat végrehajtásának idejére (timeoutWork), időtúllépés arra az időtartamra, amikor a gyermekfolyamat maximálisan várakozik a feladatokra (timeoutMaxWait), időtúllépés az elő- inicializálási idő (timeoutInit), az olvasási socketek puffereinek mérete (pipeReadSize , pipeMasterReadSize). A szálaknál letilthatja a többfeladatos módot (multitask). Ebben az esetben minden alkalommal, amikor a feladat befejeződik, a gyermekfolyamat elhal, és újra elágazik a következő indításhoz. Ez észrevehetően csökkenti a teljesítményt.

A kódot tesztek borítják és részletesen dokumentálják, a felhasználási példák az example.php fájlban tekinthetők meg és futtathatók. A hibakezelés bonyolultabb példái az egységteszt kódjában láthatók.

Van egy hibakeresési mód, amely nagyon részletes információkat jelenít meg arról, hogy pontosan mi és hol történik.

Példák a felhasználásra

A fő jellemző a maximális egyszerűség. Ha csak egy külön "szálban" akarsz futtatni valamit, elegendő a következő kód:

Osztály ExampleThread kiterjeszti Thread ( védett függvény process() ( // Itt dolgoznak néhányan ) ) $thread = new PéldaThread(); $thread->wait()->run();

Ha minden szükséges a teljes értékű munkához, akkor a feladat aszinkron módon történik. Ha nem, akkor minden továbbra is működik, de szinkron módban.

Egy paraméter átadásával és az eredmény megszerzésével a kód kissé bonyolultabbnak tűnik:

Class ExampleThread kiterjeszti a szálat ( védett függvény process() ( return $this->getParam(0); ) ) $thread = new ExampleThread(); $thread->wait()->run(123); $eredmény = $thread->wait()->getResult();

Hasonlóképpen, enyhe kézlegyintéssel hozzáadjuk az eseményfeldolgozást a folyamból:

Osztály PéldaThread kiterjeszti a szálat ( const EV_PROCESS = "folyamat"; védett függvény process() ( $events = $this->getParam(0); for ($i = 0; $i trigger(self::EV_PROCESS, $event_data); ) ) ) // További érv. $kiegészítő argumentum = 123; $thread->bind(PéldaThread::EV_PROCESS, function($esemény_neve, $esemény_adata, $additional_arg) ( // eseményfeldolgozás), $additionalArgument); $események = 10; // a szál által generált események száma // Annak elkerülése érdekében, hogy az első hívás előtt kézzel várjon a szálra, // felülírhatja a preforkWait tulajdonságot TRUE értékre a leszármazott osztályban $thread->wait(); $szál = new PéldaThread(); $thread->run($events)->wait();

És végül egy nyolc szálból álló készlet használata futásidejű hibakezeléssel:

$threads = 8 // Szálak száma $pool = new ThreadPool("ExampleThread", $threads); $szám = 25; // Feladatok száma $left = $num; // A fennmaradó feladatok száma ( // Ha vannak szabad szálak a készletben // És még mindig vannak végrehajtandó feladatok, míg ($pool->hasWaiting() && $left > 0) ( // Indításkor azt kapjuk a szál azonosítója $threadId = $pool->run(); $left--; ) if ($results = $pool->wait($sikertelen)) ( foreach ($results mint $threadId => $eredmény) ( / / Sikeresen befejezett feladat // Az eredmény azonosítható // a szál azonosítójával ($threadId) $num--; ) ) if ($sikertelen) ( // Végrehajtási hibák kezelése. // A feladat sikertelennek minősül // ha az utódfolyamat végrehajtás közben meghalt vagy // lejárt a feladatvégrehajtási időkorlát foreach ($sikertelen mint $threadId) ( $left++; ) ) ) while ($num > 0); // Leállítja az összes gyermekfolyamatot. Megtisztítjuk a medence által felhasznált erőforrásokat. $pool->cleanup();

Teljesítményteszt eredményei

A teszteket két gépen futtattam Ubuntu 11.04-el.
Az első az Intel Core i3 540 3,07 Ghz.
A második az Intel Core i7 2600K 3,40 Ghz (az Ubuntu VMware virtuális gépen fut).

Az eredményeket egyszerűen azért mutatom be, hogy értékelni tudja a termelékenység növekedését. Ezek ismét a teszt 10 ismétlésből álló sorozatának átlagos eredményei jps-ben (jobs per second – feladatok száma másodpercenként).

Feladatként a szálak a következő szemetet hajtják végre:

For ($i = 0; $i

Az első eredmény szinkron üzemmódban (villák nélkül) látható. Az első konfigurációnál nem próbáltam ki a 18 és 20 szálat, mivel már 12-re a teljesítmény csökkenni kezdett.

A szálak száma Első konfiguráció Második
0 553 763
1 330 669
2 580 1254
4 1015 2188
8 1040 2618
10 1027 2719
12 970 2739
16 958 2904
18 - 2830
20 - 2730

Vagyis processzortól függően 2-4-szeresére vagy még többre nő a teljesítmény!

A kód, amely egy tesztsorozatot futtat a szükséges paraméterekkel, az examples/speed_test.php fájlban található. Így egyszerűen tesztelheti a teljesítményt, és kiválaszthatja magának az optimális számú szálat.

Nagyon örülök, ha valakinek hasznos lesz a könyvtár. Bármilyen funkciókérést vagy észlelt hibát a Githubon hagyhat, azonnal kijavítom és javítom a könyvtárat.

Úgy tűnik, hogy a PHP-fejlesztők ritkán használják a párhuzamosságot. A szinkron kód egyszerűségéről nem beszélek, az egyszálú programozás természetesen egyszerűbb és áttekinthetőbb, de néha a párhuzamosság kis kihasználása is érezhető teljesítménynövekedést hozhat.

Ebben a cikkben megvizsgáljuk, hogyan érhető el többszálas működés a PHP-ben a pthreads kiterjesztéssel. Ehhez telepíteni kell a PHP 7.x ZTS (Zend Thread Safety) verzióját, valamint a pthreads v3 bővítményt. (A cikk írásakor a PHP 7.1-ben a felhasználóknak a fő ágból kell telepíteniük a pthreads tárolóban – lásd a harmadik féltől származó kiterjesztést.)

Egy kis pontosítás: a pthreads v2 a PHP 5.x-hez készült, és már nem támogatott, a pthreads v3 a PHP 7.x-hez való, és jelenleg is folyik a fejlesztés.

Egy ilyen kitérő után térjünk is közvetlenül a lényegre!

Egyszeri feladatok feldolgozása

Néha az egyszeri feladatokat többszálas módon szeretné feldolgozni (például valamilyen I/O-kötött feladat végrehajtása). Ilyen esetekben használhatja a Thread osztályt új szál létrehozására, és egy külön szálon futtathat feldolgozást.

Például:

$task = új osztály kiterjeszti a szálat ( privát $válasz; public function run() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+)~", $tartalom, $egyezések); $this->response = $egyezik; ) ); $task->start() && $task->join(); var_dump($task->response); // string (6) "Google"

Itt a futási metódus a mi feldolgozásunk, amely egy új szálon belül kerül végrehajtásra. A Thread::start meghívásakor egy új szál jön létre, és meghívódik a futtatási metódus. Ezután visszakapcsoljuk a gyermekszálat a főszálhoz a Thread::join meghívásával, amely addig blokkol, amíg a gyermekszál végrehajtása be nem fejeződik. Ez biztosítja, hogy a feladat végrehajtása befejeződjön, mielőtt megpróbálnánk kinyomtatni az eredményt (amely a $task->response mappában van tárolva).

Előfordulhat, hogy nem kívánatos egy osztályt az áramlási logikához kapcsolódó további felelősségekkel szennyezni (beleértve a futtatási módszer meghatározásának felelősségét). Az ilyen osztályokat úgy tudjuk megkülönböztetni, hogy örököljük őket a Threaded osztálytól. Ezután egy másik szálon belül futtathatók:

Az osztályfeladat kiterjeszti a szálakat ( publikus $válasz; nyilvános függvény someWork() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+) ~", $content, $matches); $ this->response = $egyezik; ) ) $task = new Task; $thread = new class($task) kiterjeszti Thread ( privát $feladat; public function __construct(Threaded $task) ( $this->task = $task; ) public function run() ( $this->task->someWork( ); ) ); $thread->start() && $thread->join(); var_dump($feladat->válasz);

Minden olyan osztály, amelyet külön szálban kell futtatni kellörökölni a Threaded osztályból. Ennek az az oka, hogy biztosítja a szükséges képességeket a különböző szálakon történő feldolgozáshoz, valamint implicit biztonságot és hasznos interfészeket (például erőforrás-szinkronizálást).

Vessünk egy pillantást a pthreads kiterjesztés által kínált osztályhierarchiára:

Menetes (átjárható, gyűjthető) Thread Worker Volatile Pool

A Thread és a Threaded osztályok alapjait már leírtuk és megtanultuk, most vessünk egy pillantást a másik háromra (Worker, Volatile és Pool).

Szálak újrafelhasználása

Egy új szál indítása minden párhuzamosítandó feladathoz meglehetősen költséges. Ennek az az oka, hogy a közös-semmi architektúrát kell megvalósítani a pthread-ekben, hogy a PHP-n belül többszálú legyen. Ez azt jelenti, hogy a PHP értelmező aktuális példányának teljes végrehajtási környezetét (beleértve minden osztályt, interfészt, tulajdonságot és függvényt) át kell másolni minden létrehozott szálhoz. Mivel ennek észrevehető hatása van a teljesítményre, az adatfolyamot mindig újra fel kell használni, amikor csak lehetséges. A szálak kétféleképpen használhatók fel újra: Workers vagy Pools használatával.

A Worker osztály számos feladat szinkron végrehajtására szolgál egy másik szálon belül. Ez úgy történik, hogy létrehoz egy új Worker-példányt (ami egy új szálat hoz létre), majd a feladatokat a különálló szál veremébe helyezi (a Worker::stack használatával).

Íme egy kis példa:

Az osztályfeladat kiterjeszti a szálakat ( privát $érték; nyilvános függvény __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Task: ($this->value) \n"; ) ) $dolgozó = new Dolgozó(); $dolgozó->start(); for ($i = 0; $i verem(new Task($i)); ) while ($worker->collect()); $dolgozó->leállítás();

A fenti példában 15 feladat egy új $worker objektumhoz kerül a verembe a Worker::stack metóduson keresztül, majd azokat a leküldés sorrendjében dolgozza fel. A fent látható Worker::collect metódus a feladatok azonnali megtisztítására szolgál, amint azok végrehajtása befejeződött. Ezzel egy while cikluson belül blokkoljuk a főszálat, amíg a veremben lévő összes feladat be nem fejeződik és törlődik – mielőtt meghívnánk a Worker::shutdown parancsot. Egy dolgozó korai leállítása (azaz amíg vannak még elvégzendő feladatok) továbbra is blokkolja a fő szálat mindaddig, amíg az összes feladat be nem fejezi a végrehajtását, csak hogy a feladatokat ne gyűjtsék össze (ami memóriaszivárgást jelent).

A Worker osztály számos más módszert is kínál a feladatveremhez, beleértve a Worker::unstacket az utolsó halmozott feladat eltávolításához és a Worker::getStackedet a végrehajtási veremben lévő feladatok számának lekéréséhez. A dolgozói verem csak azokat a feladatokat tartalmazza, amelyeket végre kell hajtani. Ha egy feladat a veremben elkészült, azt eltávolítjuk, és egy külön (belső) verembe helyezzük szemétgyűjtés céljából (a Worker::collect módszerrel).

A szálak több feladaton keresztüli újrafelhasználásának másik módja egy szálkészlet használata (a Pool osztályon keresztül). A szálkészlet Workers csoportot használ a feladatok végrehajtásának lehetővé tételére egyidejűleg, amelyben a párhuzamossági tényező (az általa használt készletszálak száma) a készlet létrehozásakor van beállítva.

Alkalmazzuk a fenti példát a dolgozók csoportjának használatához:

Az osztályfeladat kiterjeszti a szálakat ( privát $érték; nyilvános függvény __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Task: ($this->value) \n"; ) ) $pool = new Pool(4); for ($i = 0; $i submit(new Task($i)); ) while ($pool->collect()); $pool->shutdown();

Van néhány figyelemreméltó különbség a pool és a dolgozó használatakor. Először is, a készletet nem kell manuálisan elindítani, hanem azonnal megkezdi a feladatok végrehajtását, amint elérhetővé válnak. Másodszor, mi Küld feladatokat a medencéhez, nem rakd fel őket egy veremre. Ezenkívül a Pool osztály nem örökli a Threaded osztályt, ezért nem adható át más szálaknak (ellentétben a Workerrel).

Hogyan jó gyakorlatok A dolgozók és a csoportok esetében mindig meg kell tisztítani a feladataikat, amint befejezték, majd maguknak kell leállítaniuk azokat. A Thread osztály használatával létrehozott szálakat is csatolni kell a szülőszálhoz.

pszálak és (im)változatlanság

Az utolsó osztály, amelyet érinteni fogunk, a Volatile, a pthreads v3 új kiegészítése. A megváltoztathatatlanság fontos fogalommá vált a pszálakban, mert enélkül a teljesítmény jelentősen csökken. Ezért alapértelmezés szerint a Threaded osztályok tulajdonságai, amelyek maguk is Threaded objektumok, immár megváltoztathatatlanok, és ezért nem írhatók felül a kezdeti hozzárendelésük után. Az ilyen tulajdonságok explicit mutációja jelenleg előnyben részesített, és továbbra is elérhető az új Volatile osztály használatával.

Nézzünk egy példát, amely bemutatja az új megváltoztathatatlansági korlátozásokat:

Az osztályfeladat kiterjeszti a Threaded // a Threaded osztályt ( nyilvános függvény __construct() ( $this->data = new Threaded(); // A $this->data nem írható felül, mivel egy szálas osztály Threaded tulajdonsága) ) $task = new class(new Task()) kiterjeszti a szálat ( // egy szálas osztály, mivel a szál kiterjeszti a szálas nyilvános függvényt __construct($tm) ( $this->threadedMember = $tm; var_dump($this->threadedMember-> data); // object(Threaded)#3 (0) () $this->threadedMember = new StdClass(); // érvénytelen, mivel a tulajdonság egy szálas osztály Threaded tagja ) );

A volatile osztályok szálas tulajdonságai viszont változtathatók:

Az osztályfeladat kiterjeszti a Volatile-t ( nyilvános függvény __construct() ( $this->data = new Threaded(); $this->data = new StdClass(); // érvényes, mivel volatile osztályban vagyunk ) ) $task = new class(new Task()) kiterjeszti a szálat ( nyilvános függvény __construct($vm) ( $this->volatileMember = $vm; var_dump($this->volatileMember->data); // object(stdClass)#4 (0) () // továbbra is érvénytelen, mivel a Volatile kiterjeszti a Threaded-et, tehát a tulajdonság még mindig egy Threaded osztály Threaded tagja $this->volatileMember = new StdClass(); ) );

Láthatjuk, hogy a Volatile osztály felülírja a szülő Threaded osztály által előírt megváltoztathatatlanságot, hogy lehetővé tegye a Threaded tulajdonságok megváltoztatását (valamint unset()).

Van még egy vita tárgya a variabilitás és a volatile osztály – tömbök témájával. A pthreadekben a tömbök automatikusan átkerülnek a volatile objektumokhoz, ha a Threaded osztály egy tulajdonságához vannak hozzárendelve. Ennek az az oka, hogy egyszerűen nem biztonságos több PHP kontextusból álló tömb manipulálása.

Nézzünk még egyszer egy példát, hogy jobban megértsünk néhány dolgot:

$tömb = ; $task = new class($tömb) kiterjeszti Thread ( privát $adat; nyilvános függvény __construct(array $tömb) ( $this->data = $tömb; ) public function run() ( $this->data = 4; $ this->data = 5; print_r($this->data); ) ); $feladat->start() && $feladat->join(); /* Kimenet: illékony objektum ( => 1 => 2 => 3 => 4 => 5) */

Látjuk, hogy az illékony objektumokat úgy lehet kezelni, mintha tömbök lennének, mert támogatják a tömbműveleteket, például (amint fentebb látható) a subset() operátor. A Volatile osztályok azonban nem támogatják az olyan alapvető tömbfüggvényeket, mint az array_pop és az array_shift. Ehelyett a Threaded osztály beépített metódusként biztosít számunkra ilyen műveleteket.

Bemutatóként:

$adat = új osztály kiterjeszti Volatile ( nyilvános $a = 1; nyilvános $b = 2; nyilvános $c = 3; ); var_dump($adat); var_dump($adat->pop()); var_dump($adat->shift()); var_dump($adat); /* Kimenet: object(class@anonymous)#1 (3) ( ["a"]=> int(1) ["b"]=> int(2) ["c"]=> int(3) ) int(3) int(1) object(class@anonymous)#1 (1) ( ["b"]=> int(2) ) */

Egyéb támogatott műveletek közé tartozik a Threaded::chunk és a Threaded::merge .

Szinkronizálás

A cikk utolsó részében a pthread-ekben történő szinkronizálást nézzük meg. A szinkronizálás egy olyan módszer, amely lehetővé teszi a megosztott erőforrásokhoz való hozzáférés szabályozását.

Például valósítsunk meg egy egyszerű számlálót:

$számláló = új osztály kiterjeszti a szálat ( public $i = 0; public function run() ( for ($i = 0; $i i; ) ) ); $számláló->start(); for ($i = 0; $i i; ) $counter->join(); var_dump($számláló->i); // 10 és 20 közötti számot nyomtat

Szinkronizálás nélkül a kimenet nem determinisztikus. Több szál ír ugyanarra a változóra ellenőrzött hozzáférés nélkül, ami azt jelenti, hogy a frissítések elvesznek.

Javítsuk ki, hogy az időzítés hozzáadásával a helyes 20-as kimenetet kapjuk:

$számláló = new class kiterjeszti Thread ( public $i = 0; public function run() ( $this->synchronized(function () ( for ($i = 0; $i i; ) )); ) ); $számláló->start(); $számláló->szinkronizált(függvény ($számláló) ( for ($i = 0; $i i; ) ), $számláló); $counter->join(); var_dump($számláló->i); // int(20)

A szinkronizált kódblokkok a Threaded::wait és Threaded::notify (vagy Threaded::notifyAll) metódusokkal is kommunikálhatnak egymással.

Itt van egy alternatív növekmény két szinkronizált while ciklusban:

$számláló = új osztály kiterjeszti Thread ( public $cond = 1; public function run() ( $this->synchronized(function ()) ( for ($i = 0; $i notify();); if ($this->cond === 1) ( $this->cond = 2; $this->wait(); ) ) )); ) ); $számláló->start(); $számláló->szinkronizált(függvény ($számláló) ( if ($counter->cond !== 2) ( $counter->wait(); // várjon a Másik az első kezdéshez ) for ($i = 10; $i notify(); if ($counter->cond === 2) ( $counter->cond = 1; $counter->wait(); ) ) ) , $számláló); $counter->join(); /* Kimenet: int(0) int(10) int(1) int(11) int(2) int(12) int(3) int(13) int(4) int(14) int(5) int( 15) int(6) int(16) int(7) int(17) int(8) int(18) int(9) int(19) */

Észreveheti további feltételek, amelyek a Threaded::wait hívás köré kerültek. Ezek a feltételek kritikusak , mert lehetővé teszik a szinkronizált visszahívás folytatását , ha értesítést kapott , és a megadott feltétel igaz . Ez azért fontos, mert az értesítések más helyekről is érkezhetnek, mint a Threaded::notify meghívásakor. Így ha a Threaded::wait metódus hívásai nem lennének feltételekkel zárva, akkor végrehajtjuk hamis ébresztők, ami kiszámíthatatlan kódviselkedéshez vezet.

Következtetés

Megnéztük a pthreads csomag öt osztályát (Threaded, Thread, Worker, Volatile és Pool) és az egyes osztályok használatát. Megvizsgáltuk a változtathatatlanság új koncepcióját a pthread-ekben, készült rövid áttekintés támogatott szinkronizálási lehetőségek. Ha ezekkel az alapokkal a helyükön van, elkezdhetjük megvizsgálni, hogyan használhatók a pthreadek valós esetekben! Ez lesz a következő bejegyzésünk témája.

Ha érdekel a következő bejegyzés fordítása, jelezd: kommentelj a közösségi oldalakon. hálózatokon, szavazzon pozitívan, és ossza meg a bejegyzést kollégáival és barátaival.

Betöltés...Betöltés...