Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Zope sur linux multi-processeur

14 réponses
Avatar
Cedric Foll
Bonjour,

tout d'abord je ne suis pas programmeur python mais admin système/réseaux.
Je voudrais mettre en place un serveur Zope et faire tourner Plone dessus.
J'ai fait un test sur une Redaht AS 3.0 ça se passe bien avec un zope
2.6.4 et un python 2.2.3. C'est celui par defaut de Redhat 3.0 et qu'il
est difficile d'upgrader parce que les outils d'admin de redhat sont
écrites en python.
La machine de tests est un quadri-Xeon avec 2Go de ram. Là ou le bas
blaisse c'est que je ne dépasse pas les 5-6 connexions à la seconde. Ce
qui est ridiculement faible pour les besoins de l'appli.
En fait je me suis apperçu que je n'avais qu'un process python me
prenant 100% d'un de mes CPU, zéro sur les 3 autres.
Il n'est pas possible avec Zope|Python de gérer plusiers processeurs.
1) Zope est il capable de pre-forker pour utiliser tous les CPU (comme
un apache) ? Ou de gérer des thread posix ?
2) En ce qui concerne la gestion des thread sous python, comment ça se
passe ? Je pense qu'il doit être possible d'utiliser soit des
green-thread soit des pthread (threads posix) comme avec Perl. Sous Perl
c'est une option de compilation et il est possible de voir avec un "Perl
-v" si perl a été compilée avec des pthread ou pas. Comment fait on en
python ?
Si les thread sont générés en utilisant l'appèle système clone() de
linux, les thread devraient pouvoir être répartis sur plusieurs procs.

On pourrait m'arguer qu'il suffit d'acheter une ferme de serveurs avec
un système de load balacing devant (genre CSS de Cisco) mais c'est très
lourd et bcp plus cher.

Quelles sont les solutions simples pour utiliser toutes les ressources
CPU. Le problème vient il du fait que g un vieux python et un vieux zope
sur ma machine ?


Cdt.

10 réponses

1 2
Avatar
Tibi
On Fri, 24 Sep 2004 14:45:17 +0200, Cedric Foll
wrote:

C'est celui par defaut de Redhat 3.0 et qu'il est difficile d'upgrader
parce que les outils d'admin de redhat sont écrites en python.


C'est pas bien, hein, RedHat ;-)
Avec Debian on peut sans problème avoir plusieurs versions de Python
installées en parallele.

1) Zope est il capable de pre-forker pour utiliser tous les CPU (comme
un apache) ? Ou de gérer des thread posix ?


ZServer, le serveur web, ftp etc.. intégré dans Zope est multithread et
traite bien les requetes en parallele, par contre je ne sais pas ce qu'il
en est des autres composants de Zope comme la ZODB ou le "moteur"
principal de Zope.

2) En ce qui concerne la gestion des thread sous python, comment ça se
passe ? Je pense qu'il doit être possible d'utiliser soit des


oui c'est possible, c'est compilé par défaut normalement, à vérifier avec
ta version

On pourrait m'arguer qu'il suffit d'acheter une ferme de serveurs avec
un système de load balacing devant (genre CSS de Cisco) mais c'est très
lourd et bcp plus cher.


On pourrait aussi te conseiller d'installer Apache en front-end à la place
de ZServer mais dans ton cas je ne pense pas que ce soit la solution.

Quelles sont les solutions simples pour utiliser toutes les ressources
CPU. Le problème vient il du fait que g un vieux python et un vieux zope
sur ma machine ?


Je ne pense pas, la version de python que tu utilises n'est pas si vieille.
Je n'ai pas de solution, peut-être ce document te donnera-t-il des pistes:
http://www.zope.org/Members/glpb/solaris/multiproc

Avatar
Cedric Foll
ZServer, le serveur web, ftp etc.. intégré dans Zope est multithread et
traite bien les requetes en parallele, par contre je ne sais pas ce
qu'il en est des autres composants de Zope comme la ZODB ou le
"moteur" principal de Zope.


Multi-thread ça ne veut pas dire grand chôse.
Ce qu'il faut savoir c'est si il utilise la commande système clone ou
s'il fait des green-thread.
Dans le premier cas le scheduler du kernel sera capable de répartir la
charge sur plusieur CPU.
Dans le second il ne vera qu'un process mono-thread et ne poura rien faire.

Je ne pense pas, la version de python que tu utilises n'est pas si vieille.
Je n'ai pas de solution, peut-être ce document te donnera-t-il des pistes:
http://www.zope.org/Members/glpb/solaris/multiproc


D'après ce j'ai lu on ne peut pas faire grand chose...

Avatar
Gilles Lenfant
"Cedric Foll" a écrit dans le message de
news:
Bonjour,

[...]


Quelles sont les solutions simples pour utiliser toutes les ressources
CPU. Le problème vient il du fait que g un vieux python et un vieux zope
sur ma machine ?


Le problème vient du fait que Python ne sait pas (encore) tirer parti d'une
architecture multiproc.
S'il y a moyen de contrôler manuellement la distribution des processus sur
les différents processeurs, il est envisageable d'utiliser ZEO (fourni avec
Zope depuis Zope 2.7) pour partager la même ZODB entre plusieurs instances
Zope.

--
Gilles

Avatar
Cedric Foll
Gilles Lenfant wrote:
"Cedric Foll" a écrit dans le message de
news:

Bonjour,



[...]

Quelles sont les solutions simples pour utiliser toutes les ressources
CPU. Le problème vient il du fait que g un vieux python et un vieux zope
sur ma machine ?



Le problème vient du fait que Python ne sait pas (encore) tirer parti d'une
architecture multiproc.


Python ne connait pas la commande fork ??? ;-)
En fait pour utiliser toutes les ressources CPU d'une machine multi-proc
lorsque l'on écrit un serveur il suffit de forker. Ce n'est pas bien
compliqué. Cf http://pleac.sourceforge.net/pleac_perl/sockets.html,
section "Pre-Forking Servers" pour un exemple en Perl. Apache fait
exactement la même chose.
C'est aussi comme ça que fonctionne tous les serveur d'appli java
(weblogic, tomcat, ...)
------
# ps ax | fgrep java | wc -l
477
------
Donc visiblement Zope ne fait pas ça. On m'a parlé de Zeo, je vais donc
devoir me tourner vers ça. Mais c'est bien compliqué comme méthode ...


Avatar
Tibi
On Fri, 24 Sep 2004 16:46:27 +0200, Cedric Foll
wrote:

Multi-thread ça ne veut pas dire grand chôse.
Ce qu'il faut savoir c'est si il utilise la commande système clone ou
s'il fait des green-thread.
Dans le premier cas le scheduler du kernel sera capable de répartir la
charge sur plusieur CPU.
Dans le second il ne vera qu'un process mono-thread et ne poura rien
faire.


Python utilise des threads POSIX.
La notion de green-threads n'existe pratiquement que dans Java, non?

Avatar
Cedric Foll
Python utilise des threads POSIX.
La notion de green-threads n'existe pratiquement que dans Java, non?


Oui c'est vrai. En fait green-thread est le nom que donne java aux "user
level thread".
Donc le terme approprié est "user level thread" par opposition aux "OS
threads".
Mais ce qui est étonnant si Python utilise des "Thread OS" que je n'ais
qu'un seul CPU utilisé à 100% et rien sur les autres.

Cdt.

Avatar
mordicus
Cedric Foll wrote:

Désolé pour le mail, ma souris à glisser ...

Python ne connait pas la commande fork ??? ;-)
En fait pour utiliser toutes les ressources CPU d'une machine multi-proc
lorsque l'on écrit un serveur il suffit de forker.


Non!

Sur AIX par exemple, quand tu fork tu reste sur le meme processeur, ce n'est
que quand tu utilise les threads que les autre CPU sont utilisés!

Ce n'est pas bien
compliqué. Cf http://pleac.sourceforge.net/pleac_perl/sockets.html,
section "Pre-Forking Servers" pour un exemple en Perl. Apache fait
exactement la même chose.


Plus tout à fait vrai pour Apache 2.0

C'est aussi comme ça que fonctionne tous les serveur d'appli java
(weblogic, tomcat, ...)


Non, Java utilise les threads et c'est pas parce que un kernel
2.4 te montre plusieur processus que c'est "forké". Avec un kernel
2.4 les threads sont vues comme des processus. Sur un kernel 2.6 tu ne
les vois plus...


------
# ps ax | fgrep java | wc -l
     477
------
Donc visiblement Zope ne fait pas ça. On m'a parlé de Zeo, je vais donc
devoir me tourner vers ça. Mais c'est bien compliqué comme méthode ...


Python (donc Zope), je n'ai tester en multitache que sur du 2.6 en
multiprocesseurs, et la, on ne vois d'un processus (mais les threads peuvent
être repartis sur tout les processeurs). J'avoue que je n'ai pas chercher
bien
loin, mais Python utilise les Posix threads et il n'y a aucune raisons pour
que les threads restent sur un seul processeur.

Le plus simple, sur un multiprocesseur c'est d'ecrire un  petit programme
python qui utilise les threads, avec autant de threads que de processeur.
Chaque threads executant une boucle pour bouffer du CPU, ensuite un petit
top
(puis f et j pour afficher l'utilisation de chaque processeur) et on est
fixé.

Je peux faire le progs si ca interesse quelqu'un.

Avatar
Tibi
On Mon, 27 Sep 2004 19:16:23 +0200, mordicus wrote:

loin, mais Python utilise les Posix threads et il n'y a aucune raisons
pour que les threads restent sur un seul processeur.


Bon oui mais le problème qui préoccupe Cedric c'est que le core de Zope et
la ZODB sont monoprocess et pour ça je vois pas bien ce qu'on peut faire.
La charge sur le serveur web (ZServer ou Apache, selon comment c'est
configuré) est bien répartie sur les 4 procs mais je pense que c'est pas
là que ça coince, c'est certainement le core de Zope qui ralenti tout. Et
pour ça, soit le core Zope est prévu pour être multiprocess et il faut
activer cette option qqpart (j'en doute) soit il ne reste que ZEO et c'est
plutot lourd à mettre en place.
Et si c'est la ZODB qui coince alors là il y a rien à faire.

Pour autant que j'aie compris quelque chose, le multithread en Python sur
une machine multiprocesseurs n'apporte aucun gain de performance à cause
du Global Interpreter Lock, il faut donc faire du multiprocessus pour
avoir plusieurs interpréteurs Python qui tournent.
Je dirais donc que ZEO est la seule solution pour profiter des 4
processeurs.

Sinon il y a pas mal d'astuces autres que hardware/OS pour optimiser les
performances de Zope et Plone...

Avatar
Cedric Foll

Plus tout à fait vrai pour Apache 2.0



Si.
La différence des Apache2 c'est qu'il utilise AUSSI des threads.
Alors que apache 1 ne faisait que du preforking et ensuite n'utilisait
des select pour gérer plusieur clients à partir d'un seul process.


C'est aussi comme ça que fonctionne tous les serveur d'appli java
(weblogic, tomcat, ...)



Non, Java utilise les threads et c'est pas parce que un kernel
2.4 te montre plusieur processus que c'est "forké". Avec un kernel
2.4 les threads sont vues comme des processus. Sur un kernel 2.6 tu ne
les vois plus...


Je viens d'écrire un petit script Perl qui lance des threads (dsl, j'ai
pas le temps de chercher comment faire ça en python malgrès la sympathie
que je porte à ce dernier)
Le voici:
---------
#!/usr/bin/perl
use threads;
$thr1 = threads->new(&sub1);
$thr2 = threads->new(&sub1);
$thr3 = threads->new(&sub1);
$thr4 = threads->new(&sub1);
$thr1->join;
$thr2->join;
$thr3->join;
$thr4->join;
sub sub1 {
while(1) {
}
}
---------

Je lance ça sur mon quadri-pro Redhat AS3.
# uname -a
Linux blake 2.4.21-9.0.1.ELsmp #1 SMP Mon Feb 9 22:26:51 EST 2004 i686
i686 i386 GNU/Linux

Je ne vois qu'un seul process Perl (contrairement à ce que vous me dire,
mais je sais que les noyaux Redhat AS sont bcp patchés par redhat pour
améliorer les SMP...)
Mais avec un CPU de 400% (399.4 pour chippoter):
-----
24967 root 23 0 3912 3912 1592 S 399,4 0,1 1:47 3 perl
-----
en faisant un top:
-----
CPU states: cpu user nice system irq softirq iowait idle
total 399,6% 0,0% 0,0% 0,0% 0,0% 0,0% 0,0%
cpu00 100,0% 0,0% 0,0% 0,0% 0,0% 0,0% 0,0%
cpu01 99,8% 0,0% 0,1% 0,0% 0,0% 0,0% 0,0%
cpu02 100,0% 0,0% 0,0% 0,0% 0,0% 0,0% 0,0%
cpu03 100,0% 0,0% 0,0% 0,0% 0,0% 0,0% 0,0%
-----
Donc mon prog perl avec mes trois threads utilise de manière optimale
toutes mes ressources CPU.

Quand j'avais lancé mon Zope j'avais un de mes quatres processeurs à
100% et quasiment rien sur les autres.

Voilà ou j'en suis...


Avatar
Cedric Foll

Je lance ça sur mon quadri-pro Redhat AS3.
# uname -a
Linux blake 2.4.21-9.0.1.ELsmp #1 SMP Mon Feb 9 22:26:51 EST 2004 i686
i686 i386 GNU/Linux

Je ne vois qu'un seul process Perl (contrairement à ce que vous me dire,
mais je sais que les noyaux Redhat AS sont bcp patchés par redhat pour
améliorer les SMP...)


En fait j'ai finalement fait la même chose (je crois) en Python:
------------------
#!/usr/bin/python
import threading
class TestThread(threading.Thread):
def run(self):
while 1:
a = 1
t1 = TestThread()
t1.start()
t2 = TestThread()
t2.start()
t3 = TestThread()
t3.start()
t4 = TestThread()
t4.start()
t1.join()
-----------------

Voici ce que ça me donne comme conso:
-----------------
CPU states: cpu user nice system irq softirq iowait idle
total 37,6% 0,0% 296,0% 0,0% 0,0% 0,0% 66,0%
cpu00 9,1% 0,0% 73,4% 0,0% 0,0% 0,0% 17,3%
cpu01 9,7% 0,0% 74,8% 0,0% 0,0% 0,0% 15,3%
cpu02 8,3% 0,0% 76,0% 0,0% 0,0% 0,0% 15,5%
cpu03 10,5% 0,0% 71,6% 0,0% 0,0% 0,0% 17,7%
(...)
root 21 0 1932 1932 1172 S 328,6 0,0 0:27 2 thread.py
-----------------

D'une part il consomme bien tous les CPU (328,6%) mais là ou c'est très
étrange c'est que la plupart du CPU est pris par "system" plutôt que par
"user". Ca serait le scheduler du kernel qui prendrait tout ce CPU ?

J'ai fait une petite comparaison entre Perl et Python pour les thread.
Je lance dans les deux cas 4 threads qui compte jusqu'à 100 000. Voici
le résultats du test:
-----------
# time ./thread.pl

real 0m0.112s
user 0m0.170s
sys 0m0.020s

# time ./thread.py

real 0m5.071s
user 0m1.770s
sys 0m15.040s
------------
C'est clair il y a un problème... Enfin c'est peut être que je m'y prend
mal pour lancer mes threads. Je n'ai aucun recul sur python ...


Ensuite lorsque je fais un bench sur Zope/Plone sur la même machine:
$ab -n 200 -c 10 http://localhost:9090/plone/

Resultat du top pdt le bench:
----------
total 95,6% 0,0% 10,0% 0,0% 0,0% 0,0% 293,6%
cpu00 21,5% 0,0% 2,1% 0,0% 0,0% 0,0% 76,2%
cpu01 23,9% 0,0% 1,7% 0,0% 0,0% 0,0% 74,3%
cpu02 25,0% 0,0% 3,1% 0,0% 0,0% 0,0% 71,7%
cpu03 25,2% 0,0% 3,1% 0,0% 0,0% 0,1% 71,3%
follc 22 0 3424 3424 1204 S 104,4 0,1 2:32 3 python
----------

En fait, à bien y regarder, tous les CPU ont l'air de marcher.
Donc le goulet d'étranglement (le nombre dérisoir de requêtes que le
serveur est capabable de servire vient d'autre chôse).
Car le bench renvoit un résultat ridicul de seulement 4 pages/seconde !!!
J'ai quand même 2 Go de ram sur la machine (done je doute que cela
vienne de la conf mémoire).
Donc qu'est ce qui merde ? Trop de lock dans la synchro des threads ?
C'est Plone qui est mal foutu ?

Le même bench me renvoie 100 requêtes à la seconde si j'attaque Zope à
la racine. ie:
$ab -n 200 -c 10 http://localhost:9090/

En fait avec 100 clients simultannés avec Zope/Plone j'ai des requêtes
moyennes de 40 secondes (ha ha ha!).
Avec juste Zope, pour 100 clients, de l'ordre d'une seconde ce qui est
jouable.

Quelqu'un utilise Zope/Plone sur un serveur qui est visité par plus de
4-5 personnes ? Comment s'en sortir ? Avec un reverse proxy qui cache la
quasi totalité des pages ?

Cdt.

1 2