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

socket: optimisation python vs java

9 réponses
Avatar
titi
Bonjour,

afin de tester la rapidité d'un lien de réseau LAN, j'ai écrit un petit
client/serveur expérimental en python.
N'étant pas satisfait es performances, je l'ai réécrit en java.

Les sources sont disponibles aux adresses suivantes:

python:
http://www.culte.org/listes/linux-31/2007-10/msg00008.html

java:
http://www.culte.org/listes/linux-31/2007-10/msg00009.html
http://www.culte.org/listes/linux-31/2007-10/msg00010.html


Est-il possible d'améliorer les performances de ce code python, à la
fois dans le client et dans le serveur?

Par ailleurs, qu'est ce qui justifie que python soit plus lent que java?

9 réponses

Avatar
Bruno Desthuilliers
(snip)
Reste à savoir comment passer de 7 à 50 ...



1/ En sortant les expressions constantes des boucles pour éviter de les
réévaluer à chaque iteration (voire, quand c'est possible, à les sortir
des fonctions). Par exemple, million = 1024*1024 devrait être défini en
dehors de toute fonction, et refaire l'affectation Mo=million à chaque
tour de boucle est inepte. Jusque là, ce n'est pas spécifique à Python,
mais vu le peu d'optimisation effectuées par le compilo, il vaut mieux
le faire soi-même.

2/ en aliasant les appels de méthodes (du moins celles appelées dans les
boucles). Là, par contre, c'est spécifique à Python (et probablement aux
autres langages objets dynamiques): la résolution d'un attribut est
une opération coûteuse et non optimisable par le compilo, alors que la
resolution d'une variable locale est très rapide. Par exemple,
chrono.restart, chrono.get_value, self.wfile.write,self.rfile.read

3/ éventuellement en utilisant de préférence les 'augmented
assignments', ie:
machin += 1
plutôt que
machin = machin + 1


Ca ne te fera probablement pas passer "de 7 à 50", mais ça pourrait aider...

Avatar
William Dode
On 04-10-2007, titi wrote:
Bonjour,

afin de tester la rapidité d'un lien de réseau LAN, j'ai écrit un petit
client/serveur expérimental en python.
N'étant pas satisfait es performances, je l'ai réécrit en java.


j'ai pas regardé tes sources, mais peut-être est-ce du à un appel à la
résolution de nom. Essaye d'enlever la fonction getfqdn

def getfqdn(name=''):
return name
import socket
socket.getfqdn=getfqdn

--
William Dodé - http://flibuste.net
Informaticien indépendant

Avatar
titi
On 04-10-2007, titi wrote:
Bonjour,

afin de tester la rapidité d'un lien de réseau LAN, j'ai écrit un petit
client/serveur expérimental en python.
N'étant pas satisfait es performances, je l'ai réécrit en java.


j'ai pas regardé tes sources, mais peut-être est-ce du à un appel à la
résolution de nom. Essaye d'enlever la fonction getfqdn

def getfqdn(name=''):
return name
import socket
socket.getfqdn=getfqdn



Je pense qu'
Il ne s'agit pas de cela pour plusieurs raisons:

1/ je n'utilise pas la fonction getfqdn
hostname = socket.gethostname()
ip_address = socket.gethostbyname(hostname)

2/ j'utilise 'localhost' et '127.0.0.1' pour faire les tests
s.connect(('127.0.0.1', port))

3/ L'exécution du code montre que la lenteur n'est pas à l'état initial,
mais en régime établi.

Par ailleurs, la différence de débit semble assez significative:

en python de 0.9 à 2.6 Mo/s
en java de 78 à 123 Mo/s

Le ratio est donc de l'ordre de 50 à 80 fois plus rapide pour java.
De plus, en python, les performances se détériorent progressivement,
alors qu'elles restent constantes en java.

Un problème de garbage collector et d'allocation mémoire?


en python de 0.9 à 2.6 Mo/s:

delta : 3.80408096313 ... 10000000
débit montant: 2.62875582747 Mo/s
delta : 5.41259384155 ... 10000000
débit montant: 1.84754302516 Mo/s
delta : 6.65622591972 ... 10000000
débit montant: 1.50235285289 Mo/s
delta : 10.6284270287 ... 10000000
débit montant: 0.940872997767 Mo/s
delta : 2.35716700554 ... 10000000


en java de 78 à 123 Mo/s:

débit montant: 45.248867Mo/s
------>361.99094Mbits/s
delta : 0.846...104857600
débit montant: 118.20331Mo/s
------>945.62646Mbits/s
delta : 8.834...1048576000
débit montant: 113.199005Mo/s
------>905.59204Mbits/s
delta : 0.138...10485760
débit montant: 72.46377Mo/s
------>579.71014Mbits/s
delta : 0.698...104857600
débit montant: 143.26648Mo/s
------>1146.1318Mbits/s
delta : 8.455...1048576000
débit montant: 118.27321Mo/s
------>946.18567Mbits/s
delta : 0.139...10485760
débit montant: 71.942444Mo/s
------>575.53955Mbits/s
delta : 0.811...104857600
débit montant: 123.304565Mo/s


Avatar
Cémoi
Salut,

le résultat de mes essais, Python 2.5.1, Windows XP SP2, lancé dans
IPython 0.8.1:

In [2]: run server.py
detection : 127.0.0.1
Utilise : 127.0.0.1 3700
handle
delta : 0.0309998989105 ... 1048576
debit montant: 32.2581697084 Mo/s
------> 258.065357667 Mbits/s
Pause debut
Pause fin
delta : 0.109000205994 ... 5242880
debit montant: 45.8714729428 Mo/s
------> 366.971783543 Mbits/s
Pause debut
Pause fin
delta : 1.03099989891 ... 52428800
debit montant: 48.4966099927 Mo/s
------> 387.972879942 Mbits/s
Pause debut
Pause fin
delta : 0.0160000324249 ... 1048576
debit montant: 62.4998733404 Mo/s
------> 499.998986723 Mbits/s
Pause debut
Pause fin
delta : 0.0780000686646 ... 5242880
debit montant: 64.1025076722 Mo/s
------> 512.820061377 Mbits/s
Pause debut
Pause fin
delta : 1.0 ... 52428800
debit montant: 50.0 Mo/s
------> 400.0 Mbits/s
Pause debut
Pause fin
delta : 0.0309998989105 ... 1048576
debit montant: 32.2581697084 Mo/s
------> 258.065357667 Mbits/s
Pause debut
Pause fin
delta : 0.109999895096 ... 5242880
debit montant: 45.4545888034 Mo/s
------> 363.636710427 Mbits/s
Pause debut
Pause fin
delta : 1.07800006866 ... 52428800
debit montant: 46.382186285 Mo/s
------> 371.05749028 Mbits/s
Pause debut
Pause fin
delta : 0.0160000324249 ... 1048576
debit montant: 62.4998733404 Mo/s
------> 499.998986723 Mbits/s
Pause debut
Pause fin
delta : 0.108999967575 ... 5242880
debit montant: 45.8715732787 Mo/s
------> 366.97258623 Mbits/s
Pause debut
Pause fin
delta : 1.0 ... 52428800
debit montant: 50.0 Mo/s
------> 400.0 Mbits/s

Par rapport à ton code rien de changé, à part ip_address = '127.0.0.1'
dans le __main__, et viré les accents (IPython les gère mal).
Et comme tu peux le voir, je ne constate pas de baisse de régime.
Est tu sûr de réellement passer par 127.0.0.1 lors de tes essais en Python ?
Sur quel OS fais tu tes essais ?
Quelle version de Python ?

Au passage, SocketServer.ThreadingMixIn ne sert à rien, un petit coup de
PEP-8 dans ton code ferait du bien à tes yeux, et une ligne du style #
-*- coding: latin-1 -*- juste après celle du "hashbang" soulagerait
l'interpréteur ;o)
Je suis tellement loin de tes perfs que je n'ai même pas cherché si une
quelconque optimisation était de rigueur.

Mes 2 centimes (d'euros, bien sûr),

Laurent
Avatar
titi
Salut,

le résultat de mes essais, Python 2.5.1, Windows XP SP2, lancé dans
IPython 0.8.1:

In [2]: run server.py
detection : 127.0.0.1
Utilise : 127.0.0.1 3700
handle
delta : 0.0309998989105 ... 1048576
debit montant: 32.2581697084 Mo/s
------> 258.065357667 Mbits/s
Pause debut
Pause fin
delta : 0.109000205994 ... 5242880
debit montant: 45.8714729428 Mo/s
------> 366.971783543 Mbits/s
Pause debut
Pause fin
delta : 1.03099989891 ... 52428800
debit montant: 48.4966099927 Mo/s
------> 387.972879942 Mbits/s
Pause debut
Pause fin
delta : 0.0160000324249 ... 1048576
debit montant: 62.4998733404 Mo/s
------> 499.998986723 Mbits/s
Pause debut
Pause fin
delta : 0.0780000686646 ... 5242880
debit montant: 64.1025076722 Mo/s
------> 512.820061377 Mbits/s
Pause debut
Pause fin
delta : 1.0 ... 52428800
debit montant: 50.0 Mo/s
------> 400.0 Mbits/s
Pause debut
Pause fin
delta : 0.0309998989105 ... 1048576
debit montant: 32.2581697084 Mo/s
------> 258.065357667 Mbits/s
Pause debut
Pause fin
delta : 0.109999895096 ... 5242880
debit montant: 45.4545888034 Mo/s
------> 363.636710427 Mbits/s
Pause debut
Pause fin
delta : 1.07800006866 ... 52428800
debit montant: 46.382186285 Mo/s
------> 371.05749028 Mbits/s
Pause debut
Pause fin
delta : 0.0160000324249 ... 1048576
debit montant: 62.4998733404 Mo/s
------> 499.998986723 Mbits/s
Pause debut
Pause fin
delta : 0.108999967575 ... 5242880
debit montant: 45.8715732787 Mo/s
------> 366.97258623 Mbits/s
Pause debut
Pause fin
delta : 1.0 ... 52428800
debit montant: 50.0 Mo/s
------> 400.0 Mbits/s

Par rapport à ton code rien de changé, à part ip_address = '127.0.0.1'


okay.

dans le __main__,


et viré les accents (IPython les gère mal).


Bizarre, et inattendu!

Et comme tu peux le voir, je ne constate pas de baisse de régime.
Est tu sûr de réellement passer par 127.0.0.1 lors de tes essais en Python ?


Non.

Sur quel OS fais tu tes essais ?


Debian GNU/Linux 4.0


et plus précisément:

Linux 2.6.18.070711 #2 SMP Wed Jul 11 09:25:23 CEST 2007 i686 GNU/Linux

mais aussi

Linux 2.6.18-4-amd64 #1 SMP Fri May 4 00:37:33 UTC 2007 x86_64 GNU/Linux

Le système est paramétré avec des locales françaises-UTF-8:
LANG=fr_FR.UTF-8
LC_CTYPE="fr_FR.UTF-8"
LC_NUMERIC="fr_FR.UTF-8"
LC_TIME="fr_FR.UTF-8"
LC_COLLATE="fr_FR.UTF-8"
LC_MONETARY="fr_FR.UTF-8"
LC_MESSAGES="fr_FR.UTF-8"
LC_PAPER="fr_FR.UTF-8"
LC_NAME="fr_FR.UTF-8"
LC_ADDRESS="fr_FR.UTF-8"
LC_TELEPHONE="fr_FR.UTF-8"
LC_MEASUREMENT="fr_FR.UTF-8"
LC_IDENTIFICATION="fr_FR.UTF-8"

Quelle version de Python ?


essentielement
Python 2.4.4 (#2, Apr 5 2007, 20:11:18)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2

mais aussi
Python 2.4.4 (#2, Apr 5 2007, 18:43:10)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2



Au passage, SocketServer.ThreadingMixIn ne sert à rien,


Même si je veux un thread différent pour chaque client?

un petit coup de
PEP-8 dans ton code ferait du bien à tes yeux,


http://www.python.org/dev/peps/pep-0008/

Certes, mais pour le moment, il s'agissait juste d'un test très
expérimental.

et une ligne du style #
-*- coding: latin-1 -*- juste après celle du "hashbang" soulagerait
l'interpréteur ;o)


Le problème c'est qu'un mélange de fichiers latin-1 et utf-8 n'est pas
très facile à gérer.

Je suis tellement loin de tes perfs que je n'ai même pas cherché si une
quelconque optimisation était de rigueur.


L'utilisation de l'option -O me permet de passer de 0,7 à 7.
Elle me permet également d'avoir un temps d'exécution constant.
La ligne latin1 ne semble pas avoir d'impact.

Reste à savoir comment passer de 7 à 50 ...

Avatar
jean-michel bain-cornu
Bonsoir,
et une ligne du style #
-*- coding: latin-1 -*- juste après celle du "hashbang" soulagerait
l'interpréteur ;o)


Le problème c'est qu'un mélange de fichiers latin-1 et utf-8 n'est pas
très facile à gérer.


A partir du moment où l'indication de charset est correcte dans le
source (avec -*- coding etc...), et qu'elle correspond avec les chaînes
de caractères du dit source, il n'y a pas de problème avec
l'interprêteur, mais plutôt avec l'éditeur que tu utilises pour las saisie !
Si le traitement des chaînes te pose un problème, il faut peut-être
songer à utiliser l'unicode, avec unicode('chaîne',encodage).


Avatar
Laurent Pointal
Bruno Desthuilliers wrote:

Ca ne te fera probablement pas passer "de 7 à 50", mais ça pourrait
aider...


J'ai aussi repéré des range() qui seraient peut-être mieux en xrange().

Avatar
William Dode
On 04-10-2007, titi wrote:
Reste à savoir comment passer de 7 à 50 ...


Si ça rame coté cpu, tente avec psyco
http://psyco.sourceforge.net/

--
William Dodé - http://flibuste.net
Informaticien indépendant

Avatar
JBB

en python de 0.9 à 2.6 Mo/s:

en java de 78 à 123 Mo/s:



sur mon Pc ( dualcore 3Ghz + 1Go ram + windows XP)
en python j'obtient ( en utilisant 127.0.0.1)
- 500 Mo/s
- 800 Mo/s en utisant -O
ton pc a un probleme !!