Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
#1 17/12/2010 16:26:05
- djeauh
- Membre
Lecture sur une socket plus lente dans une procédure C
Bonjour à tous,
j'ai un petit soucis avec l'utilisation des procédures C (fonction que je trouve géniale dans POSTGRES soit dit en passant).
J'ai écrit un shared object (je suis sous DEBIAN) me permettant de faire une requete HTTP vers un serveur se trouvant sur internet.
Lorsque j'utilise cette librairie dans une application dédié, la lecture de la réponse prends toujours environ 20 sec.
Lorsque j'utilise cette librairie dans une procédure intégrée à POSTGRES, la même requete prends environ 60 sec!!
J'ai mis des traces dans ma librairie, et il semblerait que je soit toujours bloqué au niveau de la reception des données.
Auriez-vous un indice? Merci d'avance et bonne journée.
djeauh
Hors ligne
#2 17/12/2010 16:29:19
- Marc Cousin
- Membre
Re : Lecture sur une socket plus lente dans une procédure C
Bonjour,
Pouvez vous détailler la façon dont vous faites ce test ? C'est un appel à la procédure qui dure 60 secondes, ou bien y a t'il de nombreux appels consécutifs ?
Marc.
Hors ligne
#3 17/12/2010 17:07:49
- djeauh
- Membre
Re : Lecture sur une socket plus lente dans une procédure C
Bonjour et merci de votre réactivité.
Il s'agit en fait d'un appel à une procédure, laquelle procédure appel la fameuse librairie que j'ai écrit. Lorsque j'appel la fonction définie dans la librairie à partir de la procédure postgres le temps d'éxecution de cette fonction est de 60s. Lorsque j'appel la même fonction sans passer par la base de données, l'appel dure 20s.
Voici en gros comment ça se passe:
//Fichier my_func.c pour génération myfunc.so
void myFunc() {
//Mes traitements....
//......
}
//------------------------
//Application externe liée à myfunc.so
int main() {
myFunc(); //L'appel prends 20 s
}
//-------------------------
//Fichier procedure.c, pour intégration, à POSTGRES et lié à myfunc.so
PG_FUNCTION_INFO_V1( test );
Datum test( PG_FUNCTION_ARGS );
Datum test( PG_FUNCTION_ARGS ) {
//Appel à ma fonction défini dans mon so:
myFunction(); //L'appel prends 60 s
PG_RETURN_NULL();
}
J'espere que je suis plus clair à présent. A noter que le code contenu dans myFunc ne fait principalement que des lectures sur une socket et que d'après mes logs je reste bloqué sur mon epoll_wait en attente de la réponse du serveur distant.
Je vais essayer d'écrire un programme de test afin de reproduire le problème.
Merci encore de votre aide.
Hors ligne
#4 17/12/2010 17:19:02
- Marc Cousin
- Membre
Re : Lecture sur une socket plus lente dans une procédure C
C'est assez étonnant en effet, vu que PostgreSQL ne rajoute pas grand chose autour de la librairie à ma connaissance. Il y a un coût pour la résolution de l'objet de la fonction, et le coût de l'appel de la fonction, mais ça se chiffre plutôt en microsecondes qu'en secondes.
Difficile de vous dire ce qui pourrait poser problème. Il y a forcément quelque chose de différent, mais je ne vois pas ce que ça pourrait être comme ça, puisque le myfunc.so est le même.
Vous pouvez toujours commencer par comparer le comportement via strace:
dans un cas strace -ttt -fF mon_programme
dans l'autre, trouver le pid du backend, puis strace -ttt -p pid
Et comparer ce qui se passe…
Sinon, vous avez gagné le droit de passer dans un profiler, comme oprofile, pour essayer de comprendre ce qui se passe. Mais on change de registre, ça devient très compliqué.
Marc.
Hors ligne
#5 17/12/2010 17:32:39
- djeauh
- Membre
Re : Lecture sur une socket plus lente dans une procédure C
En effet, c'est d'autant plus étrange que j'ai déjà écrit pas mal de fonction C pour POSTGRES utilisant des librairies et que c'est la première fois que j'obtient ce comportement.
Je vais essayer le strace et je vous tiens au courant.
Hors ligne
#6 20/12/2010 10:36:53
- djeauh
- Membre
Re : Lecture sur une socket plus lente dans une procédure C
J'ai suivi vos conseils en utilisant strace. Les logs produits confirment mes doutes.
Pour mes tests, j'ai utilisé le même serveur, avec la même connexion internet et la même version de ma librairie.
J'utilise epoll afin de détecter l'arrivée de données sur la socket.
1) Voici un extrait du log produit par strace avec mon programme de test:
--------------------------------------------------------------------------------------------------------------------------------------------------------
1292601158.915700 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 5
1292601158.915745 connect(5, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("XXX.XXX.XXX.XXX")}, 16) = 0
1292601158.970697 sendto(5, "POST XXXXXXXXXXXXXXXXXXX"..., 181, 0, NULL, 0) = 181
1292601158.970778 sendto(5, "<SOAP-ENV:Envelope xmlns:SOAP-ENV"..., 45450, 0, NULL, 0) = 45450
1292601159.190492 epoll_create(1) = 6
1292601159.190548 epoll_ctl(6, EPOLL_CTL_ADD, 5, {EPOLLIN, {u32=5, u64=18276150996369413}}) = 0
1292601159.190638 epoll_wait(6, {{EPOLLIN, {u32=5, u64=18276150996369413}}}, 1, 120000) = 1
1292601170.874392 recvfrom(5, "HTTP/1.1 200 OK\r\nServer: XXXXX"..., 2048, 0, NULL, NULL) = 150
1292601170.874451 epoll_wait(6, {{EPOLLIN, {u32=5, u64=18276150996369413}}}, 1, 120000) = 1
1292601170.875557 recvfrom(5, "<?xml version='1.0' encoding='UTF"..., 2048, 0, NULL, NULL) = 1380
...............
--------------------------------------------------------------------------------------------------------------------------------------------------------
2) Voici un extrait équivalent, avec l'appel à la librairie depuis une fonction POSTGRES:
--------------------------------------------------------------------------------------------------------------------------------------------------------
1292601990.698854 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 18
1292601990.698897 connect(18, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("XXX.XXX.XXX.XXX")}, 16) = 0
1292601990.754671 sendto(18, "POST XXXXXXXXXXXXXXXXXXX"..., 181, 0, NULL, 0) = 181
1292601990.754775 sendto(18, "<SOAP-ENV:Envelope xmlns:SOAP-ENV"..., 46945, 0, NULL, 0) = 46945
1292601990.963530 epoll_create(1) = 19
1292601990.963617 epoll_ctl(19, EPOLL_CTL_ADD, 18, {EPOLLIN, {u32=18, u64=7213054800882040850}}) = 0
1292601990.963670 epoll_wait(19, {{EPOLLIN, {u32=18, u64=7213054800882040850}}}, 1, 120000) = 1
1292602044.286214 recvfrom(18, "HTTP/1.1 200 OK\r\nServer: XXXXX"..., 2048, 0, NULL, NULL) = 150
1292602044.286270 epoll_wait(19, {{EPOLLIN, {u32=18, u64=7213054800882040850}}}, 1, 120000) = 1
1292602044.287482 recvfrom(18, "<?xml version='1.0' encoding='UTF"..., 2048, 0, NULL, NULL) = 1380
...................
--------------------------------------------------------------------------------------------------------------------------------------------------------
Comme vous pourrez le constater, le délai entre mon premier epoll_wait et le début de ma réponse du serveur est d'environ 11s dans le premier test. Lors du second test, cette même durée est de 54s!!!!
A noter que j'ai essayé d'enlever les epoll de mon code en ne faisant que des read et que le résultat est le même.
Je vais continuer mes tests et essayer de modifier mon code faisant les appels réseaux afin d'en savoir plus.
Bonne journée.
Hors ligne
#7 20/12/2010 11:28:04
- Marc Cousin
- Membre
Re : Lecture sur une socket plus lente dans une procédure C
Bonjour,
L'appel SOAP n'est pas strictement identique (le sendto n'a pas la même taille). Êtes-vous sûr de comparer la même requête ? Tant qu'on n'en est pas sûr, on peut toujours supposer que le service soap met plus longtemps à répondre parce qu'il a plus de travail à effectuer…
Vous pouvez, si vous avez un doute, voir le contenu complet du sendto, c'est l'option -s de strace (-s 2048 par exemple, pour voir 2038 octets de paramètres pour chaque appel système).
Marc.
Hors ligne
#8 20/12/2010 12:48:11
- djeauh
- Membre
Re : Lecture sur une socket plus lente dans une procédure C
J'ai trouvé la réponse à mon problème: comme vous l'avez soulevé il y avait en effet une différence entre les 2 requêtes SOAP. Mea culpa: c'était un bug dans une de mes fonctions
Merci encore pour votre aide et désolé pour la perte de temps
Hors ligne