De quels actes commis en état d'ébriété avez-vous vraiment honte ? Résultats des tests de performance sur les troubles paniques

NEUROSE CARDIAQUE (CARDIOPHOBIE). Une forme particulière de phobie, avec le syndrome panique, est la cardiophobie, qui doit être décrite notamment en raison de son tableau clinique caractéristique et de sa fréquence importante. Elle survient principalement chez les jeunes, plus souvent chez les hommes, ainsi que chez les enfants.

Paroxystique états d'anxiété, dans laquelle les patients craignent que le cœur cesse de fonctionner et meure, peut survenir sans la présence d'une maladie somatique. Au début de la prochaine crise, des nausées, des vertiges, une anxiété interne et une légère compression du cœur apparaissent.

Cependant, dans de nombreux cas, sans aucun avertissement, une attaque grave survient : palpitations ressenti dans tout le corps, certains augmentent pression artérielle, une forte sensation de compression et d'oppression au niveau du cœur, un manque d'air, des sueurs, des étourdissements et une sensation d'évanouissement (mais pas de perte de conscience), des tremblements dans tout le corps et une peur fondamentale. Le patient croit que son cœur va s’arrêter dans une seconde et qu’il va mourir. C'est la peur de l'autodestruction et de la mort. À forte excitation les malades courent et demandent de l'aide. Si une crise de peur survient lors d'un voyage en voiture, le patient est obligé de s'arrêter et de faire une pause.

Après la première attaque, un développement phobique se produit. Les patients perdent leur équilibre mental, vivent dans une peur constante, attendant la prochaine attaque ou la mort, éprouvant la peur de la peur (peur de l'anticipation, phobie). En même temps, ils ne sont pas aidés par le message du thérapeute sur indicateurs normaux fonction cardiaque, ni la conviction que les attaques précédentes n'avaient eu aucune conséquence. La fréquence des attaques et les intervalles entre elles sont irréguliers. À intervalles réguliers, le patient surveille attentivement ses fonctions cardiaques, contrôle son pouls et enregistre ses moindres écarts. Il perçoit les extrasystoles aléatoires comme des signes incontestables d'une maladie à l'issue désespérée.

Les patients observent avec prudence d'autres manifestations végétatives, ainsi que de légères fluctuations de leur bien-être. Les patients prennent soin d'eux-mêmes, osent à peine marcher, s'efforcent d'éliminer tout stress, soucis et, avant tout, situations difficiles afin de prévenir une agression (comportement évasif). Au lieu de la peur de la mort, dans de nombreux cas, la peur de la peur et des situations qui suscitent la peur apparaît de plus en plus.

CONDITIONS D'APPARENCE. La raison de la première crise cardiophobe est souvent un conflit aigu et un surmenage, une séparation et une déception, une situation de solitude et d'abandon, ainsi qu'une anxiété en cas de mort cardiaque d'un proche.

Savoir que la mort cardiaque peut toujours survenir, même chez les jeunes et en bonne santé, devient un facteur inquiétant. Une consommation intensive de café et de nicotine peut déclencher ce processus. Le début vient souvent de l’enfance. Sont concernés principalement les enfants gâtés et dépendants, avec une dépendance prononcée à l'égard de la mère, en grande partie avec des attitudes ambivalentes : l'attente d'amour, d'une part, et le désir d'indépendance avec des pulsions agressives, de l'autre, avec des fantasmes contradictoires d'attachement et d'attachement. séparation. De telles attitudes sont particulièrement dangereuses lorsque les liens sont rompus, que des séparations et des déceptions surviennent. Un cardiophobe vit souvent dans la peur de la séparation avant de se rendre compte qu'il la souhaite et qu'il en a peur. Des problèmes communs avec les parents et des conflits avec les partenaires surviennent régulièrement.

TRAITEMENT
Si dans état aigu la présence d'un médecin et une conversation avec lui n'entraînent pas d'amélioration ; les tranquillisants ou les bêtabloquants sont indiqués ; Comme d'autres patients souffrant de névroses de peur, de nombreux phobiques tentent de s'auto-médicamenter avec de l'alcool ; mais son effet est insuffisant et le danger de devenir dépendant de l'alcool est grand. La pharmacothérapie n'est qu'un remède auxiliaire, principalement dans les cas aigus, ainsi qu'en traitement initial. recours efficace.

La psychothérapie est décisive. Plus tôt cela commencera, mieux ce sera. Étudier les causes et situations de conflit immédiatement après les premières crises cardiophobes peut arrêter le développement phobique ultérieur. Le traitement ultérieur est plus difficile et une psychothérapie à long terme est nécessaire.

Pour ces troubles anxieux et d’autres, la thérapie comportementale (confrontation d’excitation, thérapie cognitive, entraînement à la confiance en soi) est particulièrement indiquée. Une particularité de la formation à l'évitement de l'anxiété est qu'elle fonctionne sur un modèle de désensibilisation (aux conditions correspondantes des situations quotidiennes), et la formation à la gestion de l'anxiété utilise l'immersion forcée dans une situation phobique (inondation) et la formation de stratégies d'adaptation. Pour les troubles anxieux sévères, il est nécessaire de réaliser traitement clinique en utilisant différents modèles de psychothérapie.


02.10.2011, 21:27

Pour avoir tabassé un mec et accroché son T-shirt à un arbre. Et elle a poursuivi cet idiot toute seule pendant quelques kilomètres et quand il est tombé, elle a commencé à lui faire pipi dessus. Mais ils l'ont mérité.

Dans une grande entreprise, j'ai harcelé une fille et lui ai dit que son petit ami l'avait achetée lors d'une vente et qu'il mangeait aussi des bananes et mettait les pelures sur les genoux de tout le monde dans le minibus, et j'organise aussi constamment des spectacles lesbiens dans les bars, une fois que j'ai regardé sous les jupes des serveuses d'un club VIP et j'ai fait des commentaires, mais en général je suis très ivre, j'oublie tout de suite que j'aime les gens qui disent que si tu te réveilles, tu as honte mais je ne me souviens plus pourquoi exactement de moi

Après la dernière ivresse j'en ai marre :
1. a crié depuis le balcon au gars « suce-moi »
2. j'ai mangé une cigarette
3. jeté des pommes
4. j'ai appelé le gars et lui ai dit que je ne lui ferais pas l'amour de manière grossière
5. taureaux noyés dans du jus de pamplemousse
6. j'ai appelé ma mère et m'a dit que j'étais sobre
7. J’ai demandé au petit ami de mon ami de nous apporter du vin.
8. J'ai fait pipi devant les toilettes, car il y en avait 2 - j'ai choisi la mauvaise, puis je suis tombé
9. tombé du bain

J'ai couru une fois dans l'appartement avec un couteau après mon mari, même si j'ai bu quelques verres de champagne. Le lendemain matin, j'ai eu peur - et si je le frappais avec un couteau, mais j'ai juste décidé de lui faire peur. Et je ne sais pas pourquoi j’ai eu un tel coup de pied !

C'est toujours la même chose, comme quand je suis bourré, je vais au parc chercher des branleurs pour me moquer d'eux, ou je crée ces sujets sur le forum... le matin je me dis, je suis bête ?...

Une fois, un gars me draguait, et j'étais tellement ivre que j'ai commencé à lui expliquer populairement que rien n'irait mal, parce que j'étais « Bloody Mary » (ils l'étaient) et ce surnom est tellement entré dans mon âme que j'ai failli me J'ai crié à tous ceux que je rencontrais : « Je m'appelle Bloody Mary », heureusement, ce n'était pas dans ma ville natale

-* a appelé mon ex, lui a exprimé tout ce que je pensais de lui
*a appelé mon bien-aimé, lui a dit combien je le voulais
*mangé du shawarma avec du papier d'aluminium
* j'ai injurié le gars que j'ai rencontré au club, même s'il m'a aidé et m'a apporté de l'eau
*a dansé un strip-tease dans un club lors d'une compétition, a reçu la deuxième place
*a jeté de la glace sur un inconnu
*L'ami de mon homme conduit un Hummer jaune. Je n'ai jamais rien vu de pareil en Corée. quand nous sommes tous allés faire la fête ensemble. Je me suis penché hors de la voiture de mon homme et, désignant le Hummer qui me précédait, j'ai crié que cette voiture était mon amie.
*hier j'étais au club. alors que je prenais un taxi pour rentrer chez moi le matin, j'ai dit au chauffeur : [traduit du coréen. mot pour mot !] « La nourriture que j'ai mangée vient de me dire qu'elle veut sortir ! »
*J'ai aussi un ami mongol. Je suis monté sur son dos, je l'ai forcé à me porter sur son dos et j'ai crié dans toute la rue qu'il était mon cheval mongol.
mais en général il y en avait beaucoup plus, vous ne vous en souviendrez pas...

J’ai écrit au gars à 4 heures du matin » Bonne nuit, Cher"

Mes amis et moi nous sommes saoulés au cognac, tout le monde est rentré chez soi, et j'ai bêtement appelé un taxi (il était 3 heures du matin) et je suis allé voir mon ex-petit ami avec qui j'ai rompu il y a 4 mois (nous sommes restés amis, je ne le fais pas). Je ne me souviens pas comment je suis entré dans l'entrée, je suis arrivé à son appartement, j'ai enfoncé sa porte et j'ai crié «ÉPOUSE-MOI MARAT», lui, le pauvre, est devenu fou. Il m'a traîné chez moi et a pris une douche froide, m'a donné du thé fort. .Au bout de deux heures, je suis parti, et puis quand j'ai réalisé ce que j'avais fait, J'AI VRAIMENT HONTÉ Après cela, nous nous sommes réconciliés et sommes toujours ensemble. Après, je ne bois plus de coupe de champagne.


...

02.10.2011, 22:09

La femme assassinée marchait avec un homme dans le jardin, puis il m'a semblé qu'il m'avait offensé d'une manière ou d'une autre en marchant quelques pas devant moi et non à côté de moi. J'ai été offensé et j'ai grimpé à un arbre, mais il ne l'a même pas remarqué... il a couru dans le jardin pendant une heure et demie à ma recherche... et je me suis évanoui calmement sur l'arbre et j'ai dormi jusqu'au matin. ...
...
Mais le matin, je ne me souvenais pas immédiatement de la façon dont je me suis retrouvé sur les branches. Putain de merde, comment c'était après
;D;D;D

Interprétation

02.10.2011, 22:42

J'ai honte de certains actes commis en étant sobre :) Mais cela est plus proche de la philosophie. En état d'ébriété... beaucoup de choses étaient amusantes, embarrassantes... non, désolé)))))

Elena Lotus

02.10.2011, 23:17

Hier, après avoir réalisé que mon téléphone (OOO !!!) n'était plus à moi, je me suis beaucoup saoulé et (qui me connaît, ne dis pas que je bois comme une souris) alors j'ai fait quelque chose... ça. seulement à des amis proches, en grande partie secret et ensuite je réfléchirai à qui je peux le dire... Le restaurant Paberti a de nouveau été choqué. Maintenant, je regarde la galerie de photos dans l'espoir de voir ce qui s'est passé : (mais je. Je n'ai pas honte... non... Je pensais juste que j'étais décent.

02.10.2011, 23:31

;D;D;D
J'ai toujours soutenu que les tantes ne devraient pas boire !!! TOUT LE MONDE!!!;)

..;D;D;D tu dis la vérité

02.10.2011, 23:36

Une femme ivre est comme une doudoune chinoise : douce et ajustée.
Galygine

Elena Lotus

02.10.2011, 23:41

Mais les hommes aiment oui ? Tout le monde peut boire. et tantes et oncles... vous devez juste faire attention... aujourd'hui, vous n'avez pas mal à la tête... votre âme vous fait mal... voulez-vous boire un verre ? C'est juste un cercle vicieux ;)

03.10.2011, 00:15

Buvez tout et n'importe quoi pendant que vous êtes jeune et en bonne santé :)

03.10.2011, 01:48

sélectivement volé sur le forum des femmes :)

J'ai failli faire pipi dans le panier à linge devant ma mère..... confondu avec les toilettes.... oups....

La femme assassinée marchait avec un homme dans le jardin, puis il m'a semblé qu'il m'avait offensé d'une manière ou d'une autre en marchant quelques pas devant moi et non à côté de moi. J'ai été offensé et j'ai grimpé à un arbre, mais il ne l'a même pas remarqué... il a couru dans le jardin pendant une heure et demie à ma recherche... et je me suis évanoui calmement sur l'arbre et j'ai dormi jusqu'au matin. ...
...
Mais le matin, je ne me souvenais pas immédiatement de la façon dont je me suis retrouvé sur les branches. Putain de merde, comment c'était après

Sur le balcon, il y avait des bassines et des pots où ma mère faisait pousser des oignons. J'ai pissé « faiblement » dans chacun de ces pots =((((dans mon propre lit ((bien sûr, je ne le dirai pas à ma mère, jette tout dedans) la poubelle, je suis là j'ai décidé de pisser sur tes légumes verts ! Bon, ça a continué à pousser, puis c'est parti dans la salade !

03.10.2011, 05:35

Mes amis et moi nous sommes saoulés au cognac, tout le monde est rentré chez soi, et j'ai bêtement appelé un taxi (il était 3 heures du matin) et je suis allé voir mon ex-petit ami avec qui j'ai rompu il y a 4 mois (nous sommes restés amis, je ne le fais pas). Je ne me souviens pas comment je suis entré dans l'entrée, je suis arrivé à son appartement, j'ai enfoncé sa porte et j'ai crié «ÉPOUSE-MOI MARAT», lui, le pauvre, est devenu fou. Il m'a traîné chez moi et a pris une douche froide, m'a donné du thé fort. .Au bout de deux heures, je suis parti, et puis quand j'ai réalisé ce que j'avais fait, J'AI VRAIMENT HONTÉ Après cela, nous nous sommes réconciliés et sommes toujours ensemble. Après, je ne bois plus de coupe de champagne.

C'est tout à fait histoire vraie amour.
Et sur les avantages de boire aussi.

(Buvez, les filles, et le bonheur viendra à vous.)

Il existe de nombreuses solutions sur le Web pour émuler le multithreading en PHP. Le plus souvent, ils sont basés sur des forks, mais il existe également des variations sur le thème utilisant curl, proc_open, etc.

Pour une raison ou une autre, toutes les options que j'ai rencontrées ne me convenaient pas et j'ai dû écrire ma propre solution.
J'avais l'ensemble d'exigences suivant :

  • Utilisation de fourchettes ;
  • Mode synchrone avec préservation de l'interface en l'absence des extensions nécessaires ;
  • Réutilisation des processus enfants ;
  • Échange complet de données entre les processus. Ceux. exécuter avec des arguments et obtenir le résultat une fois terminé ;
  • La possibilité d'échanger des événements entre un processus « thread » enfant et le processus principal pendant le fonctionnement ;
  • Travailler avec un pool de threads tout en conservant la réutilisation, en passant des arguments et en obtenant des résultats ;
  • Gestion des erreurs d'exécution ;
  • Délais d'attente pour effectuer le travail, attente du travail d'un thread, initialisation ;
  • Performance maximum;
Le résultat est une bibliothèque AzaThread(ancien nom - CThread).

Pour les impatients, voici un lien vers la source :
github.com/Anizoptera/AzaThread

Description

AzaThread fournit une interface simple pour créer des classes de thread. Qui utilisent en fait des processus distincts pour fonctionner de manière asynchrone, mais vous ne devriez pas vous en soucier. Vous pouvez envoyer des événements à partir d'un thread, renvoyer des résultats, utiliser un thread plusieurs fois en lui transmettant des arguments de lancement ou créer un pool de 16 threads ratissant vos tâches comme des petits pains chauds sans prêter attention au fait que le travail se déroule dans différents processus. .

De plus, vous pouvez facilement tester les performances de la bibliothèque dans différents modes en sélectionnant le nombre optimal de threads et la possibilité de transférer des données entre les processus spécifiquement pour votre configuration.

Les extensions suivantes sont requises pour un fonctionnement complet : libévent, posix Et pcntl.

La bibliothèque utilise LibEvent et des sockets appariés pour la communication entre les processus. Prend en charge 5 options pour transmettre des données (arguments, résultats et données d'événement) !

Je présente immédiatement les options avec les données de performances. Testé avec un pool de huit threads sur un Intel Core i7 2600K 3,40 Ghz (Ubuntu 11.04 sur une machine virtuelle VMware). Les résultats moyens pour 10 répétitions du test sont donnés en jps (tâches par seconde - le nombre de tâches recevant simplement des arguments et envoyant des données par seconde).

L'extension pour travailler avec les sockets est automatiquement sélectionnée. Si disponible, l'extension est utilisée prises, ce qui donne des performances améliorées. Sinon, il sera utilisé flux.

Le processus enfant écoute tous les signaux disponibles. Par défaut, tous (sauf SIGWINCH et SIGINFO) sont suivis d'un arrêt. Mais cela peut facilement être annulé en créant une méthode dans la classe thread avec le nom du signal. Par exemple sigWinch.

Dans le processus parent, tous les signaux sont également interceptés par défaut. Cela peut être modifié en définissant le paramètre de classe écouterMasterSignalsà faux. Dans ce cas, seul SIGCHLD sera traité. Vous pouvez facilement ajouter vos propres gestionnaires en créant une méthode statique appelée m< имя сигнала > . Par exemple mSigTerm.

Si un processus enfant meurt pour une raison quelconque, la classe sera automatiquement bifurquée lorsqu'une nouvelle tâche est lancée. Cela passe inaperçu et vous n’avez pas du tout besoin d’y penser. L'instance n'a tout simplement pas besoin d'être recréée en cas d'erreur.

Le processus enfant vérifie périodiquement l'existence du processus parent. S'il meurt subitement, l'enfant disparaîtra automatiquement.

Toutes les ressources utilisées par un thread ou un pool de threads sont automatiquement nettoyées lorsque le destructeur est appelé. Mais ils peuvent être effacés de force en appelant la méthode nettoyer. Dans ce cas, le thread/pool ne peut plus être utilisé.

À paramètres standards le thread est initialisé à l'avance, immédiatement lors de la création de la classe. Si vous définissez le paramètre préfourche sur false, alors le fork ne se produira qu'au moment du lancement de la tâche.

En général, il existe de nombreux paramètres personnalisables. Changer le nom du processus enfant après un fork (paramètre pNom constructeur), timeout pour la durée de la tâche ( timeoutWork), délai d'attente pour la durée maximale pendant laquelle un processus enfant peut attendre des tâches ( timeoutMaxWait), timeout pour le temps de pré-initialisation ( timeoutInit), tailles de tampon de lecture de socket ( pipeReadSize, pipeMasterReadSize).
Vous pouvez désactiver le mode multitâche pour les threads ( multitâche). Dans ce cas, chaque fois que la tâche est terminée, le processus enfant mourra et se renouvellera pour le prochain lancement. Cela réduira sensiblement les performances.

Le code est couvert de tests et documenté en détail ; des exemples d'utilisation peuvent être visualisés et exécutés dans le fichier ; exemple.php.
Plus exemples complexes avec la gestion des erreurs peut être vu dans le code de test unitaire.

Il existe un mode de débogage dans lequel très des informations détaillées sur ce qui se passe exactement et où.

Exemples d'utilisation

La principale caractéristique est une simplicité maximale. Si vous souhaitez simplement exécuter quelque chose dans un « thread » séparé, le code suivant suffit :
class SampleThread extends Thread ( protected function process() ( // Certains fonctionnent ici ) ) $thread = new ExempleThread(); $thread->attendre()->run();
S'il y a tout le nécessaire pour un travail à part entière, la tâche sera accomplie de manière asynchrone. Sinon, tout fonctionnera toujours, mais en mode synchrone.

En passant un paramètre et en obtenant le résultat, le code paraîtra un peu plus compliqué :
la classe ExempleThread étend le fil (fonction protégée process() ( return $this->getParam(0); ) ) $thread = new ExempleThread(); $thread->attendre()->run(123); $result = $thread->wait()->getResult();

De même, d’un léger geste de la main, on ajoute le traitement des événements du flux :
la classe ExempleThread étend le fil ( const EV_PROCESS = "process"; fonction protégée process() ( $events = $this->getParam(0); for ($i = 0; $i< $events; $i++) { $event_data = $i; $this->trigger(self::EV_PROCESS, $event_data); ) ) ) // Argument supplémentaire. $argument supplémentaire = 123 ; $thread->bind(ExampleThread::EV_PROCESS, function($event_name, $event_data, $additional_arg) ( // traitement des événements), $additionalArgument); $événements = 10 ; // nombre d'événements que le thread va générer // Pour éviter d'attendre manuellement le thread avant le premier appel, // vous pouvez remplacer la propriété preforkWait par TRUE dans la classe descendante $thread->wait(); $thread = new ExempleThread(); $thread->run($events)->wait();

Et enfin, en utilisant un pool de huit threads avec gestion des erreurs d'exécution :
$threads = 8 // Nombre de threads $pool = new ThreadPool("ExampleThread", $threads); $num = 25 ; // Nombre de tâches $left = $num; // Nombre de tâches restantes à faire ( // S'il y a des threads libres dans le pool // Et nous avons encore des tâches à exécuter while ($pool->hasWaiting() && $left > 0) ( // Au démarrage, on obtient l'identifiant du thread $threadId = $pool->run(); $left--; ) if ($results = $pool->wait($failed)) ( foreach ($results as $threadId => $result) ( / / Tâche terminée avec succès // Le résultat peut être identifié // par l'identifiant du thread ($threadId) $num-- ) ) if ($failed) ( // Gestion des erreurs d'exécution. // Le travail est considéré comme terminé sans succès / / si le processus enfant est mort pendant l'exécution ou // a expiré le délai d'exécution de la tâche pour chaque ($failed as $threadId) ( $left++; ) ) ) while ($num > 0); // Termine tous les processus enfants. Nous nettoyons les ressources utilisées par la piscine. $pool->nettoyage();

Résultats des tests de performances

J'ai effectué les tests sur deux machines avec Ubuntu 11.04.
Le premier est un Intel Core i3 540 3,07 Ghz
Le second est un Intel Core i7 2600K 3,40 Ghz (Ubuntu fonctionne sur une machine virtuelle VMware)

Je présente les résultats simplement afin que vous puissiez évaluer l'augmentation de la productivité.
Encore une fois, ce sont les résultats moyens pour une série de 10 répétitions de tests en jps (tâches par seconde - nombre de tâches par seconde).

En tant que tâche, les threads effectuent les tâches suivantes :
pour ($i = 0; $i< 1000; $i++) { $r = mt_rand(0, PHP_INT_MAX) * mt_rand(0, PHP_INT_MAX); }
Le premier résultat est indiqué pour le mode de fonctionnement synchrone (sans fourchettes).
Je n'ai pas essayé 18 et 20 threads sur la première configuration, car déjà pour 12 les performances ont commencé à baisser.

Le nombre de fils Première configuration Deuxième
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

C'est-à-dire que les performances augmentent de 2 à 4 fois ou plus, selon le processeur !

Le code qui exécute une série de tests avec les paramètres requis se trouve dans le fichier exemples/speed_test.php. Ainsi, vous pouvez facilement tester les performances et choisir vous-même le nombre optimal de threads.

Il existe de nombreuses solutions sur le Web pour émuler le multithreading en PHP. Le plus souvent, ils sont basés sur des forks, mais il existe également des variations sur le thème utilisant boucle, proc_open et ainsi de suite.

Toutes les options que j'ai rencontrées ne me convenaient pas pour une raison ou une autre et j'ai dû écrire ma propre solution. J'avais l'ensemble d'exigences suivant :

  • Utilisation de fourchettes ;
  • Mode synchrone avec préservation de l'interface en l'absence des extensions nécessaires ;
  • Réutilisation des processus enfants ;
  • Échange complet de données entre les processus. Ceux. exécuter avec des arguments et obtenir le résultat une fois terminé ;
  • La possibilité d'échanger des événements entre un processus « thread » enfant et le processus principal pendant le fonctionnement ;
  • Travailler avec un pool de threads tout en conservant la réutilisation, en passant des arguments et en obtenant des résultats ;
  • Gestion des erreurs d'exécution ;
  • Délais d'attente pour effectuer le travail, attente du travail d'un thread, initialisation ;
  • Performance maximum.

Le résultat fut la bibliothèque AzaThread (anciennement CThread).

Description

AzaThread fournit une interface simple pour créer des classes de thread. Qui utilisent en fait des processus distincts pour fonctionner de manière asynchrone, mais vous ne devriez pas vous en soucier. Vous pouvez envoyer des événements à partir d'un thread, renvoyer des résultats, utiliser un seul thread plusieurs fois, lui transmettre des arguments de démarrage ou créer un pool de 16 threads ratissant vos tâches comme des petits pains chauds, sans prêter attention au fait que le travail est en cours. dans différents processus.

De plus, vous pouvez facilement tester les performances de la bibliothèque dans différents modes en sélectionnant le nombre optimal de threads et la possibilité de transférer des données entre les processus spécifiquement pour votre configuration.

Les extensions suivantes sont requises pour un fonctionnement complet : libévent, posix Et pcntl.

La bibliothèque utilise LibEvent et des sockets appariés pour la communication entre les processus. Prend en charge 5 options pour transmettre des données (arguments, résultats et données d'événement) !

Je présente immédiatement les options avec les données de performances. Testé avec un pool de huit threads sur un Intel Core i7 2600K 3,40 Ghz (Ubuntu 11.04 sur une machine virtuelle VMware). Les résultats moyens pour 10 répétitions du test sont donnés en jps (tâches par seconde - le nombre de tâches recevant simplement des arguments et envoyant des données par seconde).

L'extension pour travailler avec les sockets est automatiquement sélectionnée. Si disponible, l'extension est utilisée prises, ce qui donne des performances améliorées. Sinon, il sera utilisé flux.

Le processus enfant écoute tous les signaux disponibles. Par défaut, tous (sauf SIGWINCH et SIGINFO) sont suivis d'un arrêt. Mais cela peut facilement être annulé en créant une méthode dans la classe thread avec le nom du signal. Par exemple sigWinch.

Dans le processus parent, tous les signaux sont également interceptés par défaut. Cela peut être modifié en définissant le paramètre ListenMasterSignals de la classe sur false . Dans ce cas, seul SIGCHLD sera traité. Vous pouvez facilement ajouter vos propres gestionnaires en créant une méthode statique appelée m<имя сигнала>. Par exemple, mSigTerm.

Si un processus enfant meurt pour une raison quelconque, la classe sera automatiquement bifurquée lorsqu'une nouvelle tâche est lancée. Cela passe inaperçu et vous n’avez pas du tout besoin d’y penser. L'instance n'a tout simplement pas besoin d'être recréée en cas d'erreur.

Le processus enfant vérifie périodiquement l'existence du processus parent. S'il meurt subitement, l'enfant disparaîtra automatiquement.

Toutes les ressources utilisées par un thread ou un pool de threads sont automatiquement nettoyées lorsque le destructeur est appelé. Mais ils peuvent être nettoyés de force en appelant la méthode de nettoyage. Dans ce cas, le thread/pool ne peut plus être utilisé.

Avec les paramètres standards, le thread est initialisé à l'avance, immédiatement lors de la création de la classe. Si vous définissez le paramètre prefork sur false , le fork ne se produira qu'au moment du lancement de la tâche.

En général, il existe de nombreux paramètres personnalisables. Modification du nom du processus enfant après le fork (paramètre pName du constructeur), timeout pour la durée d'exécution de la tâche (timeoutWork), timeout pour le temps maximum pendant lequel le processus enfant attend les tâches (timeoutMaxWait), timeout pour le pré- temps d'initialisation (timeoutInit), taille des buffers de lecture des sockets (pipeReadSize , pipeMasterReadSize). Vous pouvez désactiver le mode multitâche pour les threads (multitâche). Dans ce cas, chaque fois que la tâche est terminée, le processus enfant mourra et se renouvellera pour le prochain lancement. Cela réduira sensiblement les performances.

Le code est couvert de tests et documenté en détail ; des exemples d'utilisation peuvent être visualisés et exécutés dans le fichier example.php. Des exemples plus complexes de gestion des erreurs peuvent être vus dans le code de test unitaire.

Il existe un mode de débogage qui affiche des informations très détaillées sur ce qui se passe exactement et où.

Exemples d'utilisation

La principale caractéristique est une simplicité maximale. Si vous souhaitez simplement exécuter quelque chose dans un "thread" séparé, le code suivant est suffisant :

La classe ExempleThread étend le fil (fonction protégée process() ( // Certains fonctionnent ici ) ) $thread = new ExempleThread(); $thread->attendre()->run();

S'il y a tout le nécessaire pour un travail à part entière, la tâche sera accomplie de manière asynchrone. Sinon, tout fonctionnera toujours, mais en mode synchrone.

En passant un paramètre et en obtenant un résultat, le code paraîtra un peu plus compliqué :

La classe ExempleThread étend le fil ( protected function process() ( return $this->getParam(0); ) ) $thread = new ExempleThread(); $thread->attendre()->run(123); $result = $thread->wait()->getResult();

De même, d’un léger geste de la main, on ajoute le traitement des événements du flux :

La classe ExempleThread étend le fil ( const EV_PROCESS = "process"; fonction protégée process() ( $events = $this->getParam(0); for ($i = 0; $i trigger(self::EV_PROCESS, $event_data); ) ) ) // Argument supplémentaire. $argument supplémentaire = 123 ; $thread->bind(ExampleThread::EV_PROCESS, function($event_name, $event_data, $additional_arg) ( // traitement des événements), $additionalArgument); $événements = 10 ; // nombre d'événements que le thread va générer // Pour éviter d'attendre manuellement le thread avant le premier appel, // vous pouvez remplacer la propriété preforkWait par TRUE dans la classe descendante $thread->wait(); $thread = new ExempleThread(); $thread->run($events)->wait();

Et enfin, en utilisant un pool de huit threads avec gestion des erreurs d'exécution :

$threads = 8 // Nombre de threads $pool = new ThreadPool("ExampleThread", $threads); $num = 25 ; // Nombre de tâches $left = $num; // Nombre de tâches restantes à faire ( // S'il y a des threads libres dans le pool // Et nous avons encore des tâches à exécuter while ($pool->hasWaiting() && $left > 0) ( // Au démarrage, on obtient l'identifiant du thread $threadId = $pool->run(); $left--; ) if ($results = $pool->wait($failed)) ( foreach ($results as $threadId => $result) ( / / Tâche terminée avec succès // Le résultat peut être identifié // par l'identifiant du thread ($threadId) $num-- ) ) if ($failed) ( // Gestion des erreurs d'exécution. // Le travail est considéré comme terminé sans succès / / si le processus enfant est mort pendant l'exécution ou // a expiré le délai d'exécution de la tâche pour chaque ($failed as $threadId) ( $left++; ) ) ) while ($num > 0); // Termine tous les processus enfants. Nous nettoyons les ressources utilisées par la piscine. $pool->nettoyage();

Résultats des tests de performances

J'ai effectué les tests sur deux machines avec Ubuntu 11.04.
Le premier est un Intel Core i3 540 3,07 Ghz.
Le second est un Intel Core i7 2600K 3,40 Ghz (Ubuntu fonctionne sur une machine virtuelle VMware).

Je présente les résultats simplement afin que vous puissiez évaluer l'augmentation de la productivité. Encore une fois, ce sont les résultats moyens pour une série de 10 répétitions du test en jps (tâches par seconde - nombre de tâches par seconde).

En tant que tâche, les threads effectuent les tâches suivantes :

Pour ($i = 0 ; $i

Le premier résultat est indiqué pour le mode de fonctionnement synchrone (sans fourchettes). Je n'ai pas essayé 18 et 20 threads sur la première configuration, car déjà pour 12 les performances ont commencé à baisser.

Le nombre de fils Première configuration Deuxième
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

C'est-à-dire que les performances augmentent de 2 à 4 fois ou plus, selon le processeur !

Le code qui exécute une série de tests avec les paramètres requis se trouve dans le fichier examples/speed_test.php. Ainsi, vous pouvez facilement tester les performances et choisir vous-même le nombre optimal de threads.

Je serai très heureux si la bibliothèque est utile à quelqu'un. Toutes les demandes de fonctionnalités ou bogues détectés peuvent être laissés sur Github, je corrigerai et améliorerai rapidement la bibliothèque.

Il semble que les développeurs PHP utilisent rarement la concurrence. Je ne parlerai pas de la simplicité du code synchrone ; la programmation monothread est bien sûr plus simple et plus claire, mais parfois une petite utilisation du parallélisme peut apporter une augmentation notable des performances.

Dans cet article, nous verrons comment le multithreading peut être réalisé en PHP à l'aide de l'extension pthreads. Cela nécessitera l'installation de la version ZTS (Zend Thread Safety) de PHP 7.x, ainsi que de l'extension pthreads v3. (Au moment de la rédaction, dans PHP 7.1, les utilisateurs devront installer à partir de la branche master dans le référentiel pthreads - voir extension tierce.)

Une petite précision : pthreads v2 est destiné à PHP 5.x et n'est plus supporté, pthreads v3 est pour PHP 7.x et est activement en cours de développement.

Après une telle digression, allons droit au but !

Traitement des tâches ponctuelles

Parfois, vous souhaitez traiter des tâches ponctuelles de manière multithread (par exemple, exécuter une tâche liée aux E/S). Dans de tels cas, vous pouvez utiliser la classe Thread pour créer un nouveau thread et exécuter un traitement sur un thread distinct.

Par exemple:

$task = la nouvelle classe étend le fil de discussion ( private $response; public function run() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+)~", $content, $matches); $this->response = $matches; ) ); $task->start() && $task->join(); var_dump($task->response); // chaîne (6) "Google"

Ici, la méthode run est notre traitement, qui sera exécuté dans un nouveau thread. Lorsque Thread::start est appelé, un nouveau thread est généré et la méthode run est appelée. Nous rejoignons ensuite le thread enfant au thread principal en appelant Thread::join , qui bloquera jusqu'à ce que le thread enfant ait fini de s'exécuter. Cela garantit que l'exécution de la tâche est terminée avant que nous essayions d'imprimer le résultat (qui est stocké dans $task->response).

Il n'est peut-être pas souhaitable de polluer une classe avec des responsabilités supplémentaires associées à la logique de flux (y compris la responsabilité de définir une méthode d'exécution). Nous pouvons distinguer ces classes en les héritant de la classe Threaded. Ensuite, ils peuvent être exécutés dans un autre thread :

La tâche de classe étend Threaded ( public $response; public function someWork() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+) ~", $content, $matches); $ this->response = $matchs; ) ) $task = nouvelle tâche ; $thread = new class ($task) extends Thread ( private $task; public function __construct(Threaded $task) ( $this->task = $task; ) public function run() ( $this->task->someWork( ); ) ); $thread->start() && $thread->join(); var_dump ($ tâche-> réponse);

Toute classe qui doit être exécutée dans un thread séparé doit hérite de la classe Threaded. En effet, il fournit les fonctionnalités nécessaires pour effectuer des traitements sur différents threads, ainsi qu'une sécurité implicite et des interfaces utiles (telles que la synchronisation des ressources).

Jetons un coup d'œil à la hiérarchie de classes proposée par l'extension pthreads :

Fileté (implémente Traversable, Collectable) Thread Worker Volatile Pool

Nous avons déjà couvert et appris les bases des classes Thread et Threaded, jetons maintenant un œil aux trois autres (Worker, Volatile et Pool).

Réutiliser les fils de discussion

Démarrer un nouveau thread pour chaque tâche à paralléliser coûte assez cher. En effet, une architecture sans commun doit être implémentée dans pthreads pour réaliser le multithreading au sein de PHP. Ce qui signifie que l'intégralité du contexte d'exécution de l'instance actuelle de l'interpréteur PHP (y compris chaque classe, interface, trait et fonction) doit être copié pour chaque thread créé. Étant donné que cela a un impact notable sur les performances, le flux doit toujours être réutilisé autant que possible. Les threads peuvent être réutilisés de deux manières : en utilisant des Workers ou en utilisant des Pools.

La classe Worker est utilisée pour effectuer un certain nombre de tâches de manière synchrone au sein d'un autre thread. Cela se fait en créant une nouvelle instance de Worker (qui crée un nouveau thread), puis en poussant les tâches sur la pile de ce thread séparé (en utilisant Worker :: stack).

Voici un petit exemple :

La tâche de classe étend Threaded ( valeur privée $; fonction publique __construct(int $i) ( $this->value = $i; ) fonction publique run() ( usleep(250000); echo "Tâche : ($this->value) \n"; ) ) $worker = new Worker(); $worker->start(); for ($i = 0; $i stack(new Task($i)); ) while ($worker->collect()); $worker->shutdown();

Dans l'exemple ci-dessus, 15 tâches pour un nouvel objet $worker sont poussées sur la pile via la méthode Worker::stack, puis elles sont traitées dans l'ordre dans lequel elles ont été poussées. La méthode Worker::collect, comme indiqué ci-dessus, est utilisée pour nettoyer les tâches dès la fin de leur exécution. Avec lui, dans une boucle while, nous bloquons le thread principal jusqu'à ce que toutes les tâches de la pile soient terminées et effacées - avant d'appeler Worker::shutdown . Terminer un travailleur plus tôt (c'est-à-dire alors qu'il reste encore des tâches à accomplir) bloquera toujours le thread principal jusqu'à ce que toutes les tâches aient terminé leur exécution, simplement que les tâches ne seront pas récupérées (ce qui implique des fuites de mémoire).

La classe Worker fournit plusieurs autres méthodes liées à sa pile de tâches, notamment Worker::unstack pour supprimer la dernière tâche empilée et Worker::getStacked pour obtenir le nombre de tâches dans la pile d'exécution. La pile d'un travailleur contient uniquement les tâches qui doivent être exécutées. Une fois qu'une tâche sur la pile est terminée, elle est supprimée et placée sur une pile distincte (interne) pour le garbage collection (à l'aide de la méthode Worker::collect).

Une autre façon de réutiliser un thread sur plusieurs tâches consiste à utiliser un pool de threads (via la classe Pool). Un pool de threads utilise un groupe de Workers pour permettre l'exécution de tâches simultanément, dans lequel le facteur de concurrence (le nombre de threads du pool avec lequel il fonctionne) est défini lors de la création du pool.

Adaptons l'exemple ci-dessus pour utiliser un pool de travailleurs :

La tâche de classe étend Threaded ( valeur privée $; fonction publique __construct(int $i) ( $this->value = $i; ) fonction publique run() ( usleep(250000); echo "Tâche : ($this->value) \n"; ) ) $pool = nouveau Pool(4); for ($i = 0; $i submit(new Task($i)); ) while ($pool->collect()); $pool->shutdown();

Il existe quelques différences notables entre l’utilisation d’une piscine et celle d’un travailleur. Premièrement, le pool n'a pas besoin d'être démarré manuellement ; il commence à exécuter les tâches dès qu'elles sont disponibles. Deuxièmement, nous envoyer tâches à la piscine, pas mettez-les sur une pile. De plus, la classe Pool n'hérite pas de Threaded et ne peut donc pas être transmise à d'autres threads (contrairement à Worker).

Comment bonnes pratiques Pour les travailleurs et les pools, vous devez toujours nettoyer leurs tâches dès qu'elles sont terminées, puis les terminer manuellement vous-même. Les threads créés à l'aide de la classe Thread doivent également être attachés au thread parent.

pthreads et (im)mutabilité

La dernière classe que nous aborderons est Volatile, un nouvel ajout à pthreads v3. L'immuabilité est devenue un concept important dans pthreads car sans elle, les performances en souffrent considérablement. Par conséquent, par défaut, les propriétés des classes Threaded qui sont elles-mêmes des objets Threaded sont désormais immuables et ne peuvent donc pas être écrasées après leur affectation initiale. Une mutabilité explicite pour de telles propriétés est actuellement préférée et peut toujours être obtenue en utilisant la nouvelle classe Volatile.

Regardons un exemple qui démontrera les nouvelles restrictions d'immuabilité :

Class Task étend Threaded // une classe Threaded ( public function __construct() ( $this->data = new Threaded(); // $this->data n'est pas écrasable, car il s'agit d'une propriété Threaded d'une classe Threaded ) ) $task = new class(new Task()) extends Thread ( // une classe Threaded, puisque Thread étend la fonction publique Threaded __construct($tm) ( $this->threadedMember = $tm; var_dump($this->threadedMember-> data); // object(Threaded)#3 (0) () $this->threadedMember = new StdClass(); // invalide, puisque la propriété est un membre Threaded d'une classe Threaded ) );

Les propriétés threadées des classes volatiles, en revanche, sont modifiables :

Class Task extends Volatile ( fonction publique __construct() ( $this->data = new Threaded(); $this->data = new StdClass(); // valide, puisque nous sommes dans une classe volatile ) ) $task = new class(new Task()) étend Thread ( public function __construct($vm) ( $this->volatileMember = $vm; var_dump($this->volatileMember->data); // object(stdClass)#4 (0) () // toujours invalide, puisque Volatile étend Threaded, donc la propriété est toujours un membre Threaded d'une classe Threaded $this->volatileMember = new StdClass() );

Nous pouvons voir que la classe Volatile remplace l'immuabilité imposée par sa classe Threaded parent pour offrir la possibilité de modifier les propriétés Threaded (ainsi que de les supprimer()).

Il existe un autre sujet de discussion pour couvrir le sujet de la variabilité et de la classe Volatile : les tableaux. Dans pthreads, les tableaux sont automatiquement convertis en objets Volatile lorsqu'ils sont affectés à une propriété de la classe Threaded. En effet, il n'est tout simplement pas sûr de manipuler un tableau de plusieurs contextes PHP.

Regardons à nouveau un exemple pour mieux comprendre certaines choses :

$tableau = ; $task = new class($array) extends Thread ( private $data; public function __construct(array $array) ( $this->data = $array; ) public function run() ( $this->data = 4; $ ceci->données = 5; print_r($this->données) ); $task->start() && $task->join(); /* Sortie : Objet volatile ( => 1 => 2 => 3 => 4 => 5) */

Nous voyons que les objets Volatile peuvent être traités comme s'il s'agissait de tableaux car ils prennent en charge les opérations sur les tableaux telles que (comme indiqué ci-dessus) l'opérateur subset(). Cependant, les classes Volatile ne prennent pas en charge les fonctions de tableau de base telles que array_pop et array_shift. Au lieu de cela, la classe Threaded nous fournit des opérations telles que des méthodes intégrées.

En guise de démonstration :

$data = la nouvelle classe étend Volatile ( public $a = 1; public $b = 2; public $c = 3; ); var_dump($données); var_dump($data->pop()); var_dump($data->shift()); var_dump($données); /* Sortie : 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) ) */

Les autres opérations prises en charge incluent Threaded::chunk et Threaded::merge .

Synchronisation

Dans la dernière section de cet article, nous examinerons la synchronisation dans pthreads. La synchronisation est une méthode qui vous permet de contrôler l'accès aux ressources partagées.

Par exemple, implémentons un compteur simple :

$counter = la nouvelle classe étend Thread ( public $i = 0; public function run() ( for ($i = 0; $i i; ) ) ); $counter->start(); pour ($i = 0; $i i; ) $counter->join(); var_dump($counter->i); // affichera un nombre de 10 à 20

Sans l’utilisation de la synchronisation, le résultat n’est pas déterministe. Plusieurs threads écrivent dans la même variable sans accès contrôlé, ce qui signifie que les mises à jour seront perdues.

Corrigeons ce problème afin d'obtenir le résultat correct de 20 en ajoutant du timing :

$counter = nouvelle classe étend Thread ( public $i = 0; public function run() ( $this->synchronized(function () ( for ($i = 0; $i i; ) )); ) ); $counter->start(); $counter->synchronized(function ($counter) ( for ($i = 0; $i i; ) ), $counter); $counter->join(); var_dump($counter->i); //int(20)

Les blocs de code synchronisés peuvent également communiquer entre eux à l'aide des méthodes Threaded::wait et Threaded::notify (ou Threaded::notifyAll).

Voici un incrément alternatif en deux boucles while synchronisées :

$counter = la nouvelle classe étend le Thread ( public $cond = 1; public function run() ( $this->synchronized(function () ( for ($i = 0; $i notify(); if ($this->cond === 1) ( $this->cond = 2; $this->wait(); ) ) )); $counter->start(); $counter->synchronized(function ($counter) ( if ($counter->cond !== 2) ( $counter->wait(); // attendre pour le autre pour commencer en premier) for ($i = 10; $i notify(); if ($counter->cond === 2) ( $counter->cond = 1; $counter->wait(); ) ) ) , $compteur); $counter->join(); /* Sortie : 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) */

Vous remarquerez peut-être conditions additionnelles, qui ont été placés autour de l'appel à Threaded::wait . Ces conditions sont critiques car elles permettent au rappel synchronisé de reprendre lorsqu'il a reçu une notification et que la condition spécifiée est vraie. Ceci est important car les notifications peuvent provenir d’endroits autres que le moment où Threaded::notify est appelé. Ainsi, si les appels à la méthode Threaded::wait n'étaient pas enfermés dans des conditions, nous exécuterons faux réveils, ce qui entraînera un comportement imprévisible du code.

Conclusion

Nous avons examiné les cinq classes du package pthreads (Threaded, Thread, Worker, Volatile et Pool) et la manière dont chaque classe est utilisée. Nous avons également examiné le nouveau concept d'immuabilité dans pthreads, créé brève revue capacités de synchronisation prises en charge. Une fois ces bases en place, nous pouvons maintenant commencer à examiner comment les pthreads peuvent être utilisés dans des cas réels ! Ce sera le sujet de notre prochain article.

Si vous êtes intéressé par la traduction du prochain article, faites-le moi savoir : commentez sur les réseaux sociaux. réseaux, votez pour et partagez la publication avec vos collègues et amis.

Chargement...Chargement...