Quelles sont les performances du java dans un environnement serveur?
Je viens de coder un serveur NNTP, il fonctionne bien, mais il est
extraordinairement lent lorsqu'il s'agit de récupérer des articles avec
pièces jointes. Pour vous donner un ordre d'idées, en localhost il me
faut plusieurs minutes pour poster un fichier de 1 MO mais 2 secondes
seulement pour un fichier texte de 60 ko. Le serveur tourne sur mon
portable cadencé à 2,4 Ghz.
Voici la partie de code (dans les grandes lignes) que j'aimerais
optimiser :
public class connexion extends Thread {
Socket client;
DataInputStream C;
PrintStream S;
public connexion(Socket client) {
this.client = client;
C = new DataInputStream(client.getInputStream());
S = new PrintStream(client.getOutputStream());
[...]
new Thread(this).start();
}
public void run() {
String line, result;
while ((line = C.readLine()) != null)
{
resultat = Appel_ma_métode_NNTP(line);
[...]
S.print(resultat);
}
}
Il semblerait que ce soit l'instruction C.readLine() qui ralentit la
transmission. Mon code peut-il être encore optimisé?
Quelles sont les performances du java dans un environnement serveur?
Je viens de coder un serveur NNTP, il fonctionne bien, mais il est
extraordinairement lent lorsqu'il s'agit de récupérer des articles avec
pièces jointes. Pour vous donner un ordre d'idées, en localhost il me
faut plusieurs minutes pour poster un fichier de 1 MO mais 2 secondes
seulement pour un fichier texte de 60 ko. Le serveur tourne sur mon
portable cadencé à 2,4 Ghz.
Voici la partie de code (dans les grandes lignes) que j'aimerais
optimiser :
public class connexion extends Thread {
Socket client;
DataInputStream C;
PrintStream S;
public connexion(Socket client) {
this.client = client;
C = new DataInputStream(client.getInputStream());
S = new PrintStream(client.getOutputStream());
[...]
new Thread(this).start();
}
public void run() {
String line, result;
while ((line = C.readLine()) != null)
{
resultat = Appel_ma_métode_NNTP(line);
[...]
S.print(resultat);
}
}
Il semblerait que ce soit l'instruction C.readLine() qui ralentit la
transmission. Mon code peut-il être encore optimisé?
Quelles sont les performances du java dans un environnement serveur?
Je viens de coder un serveur NNTP, il fonctionne bien, mais il est
extraordinairement lent lorsqu'il s'agit de récupérer des articles avec
pièces jointes. Pour vous donner un ordre d'idées, en localhost il me
faut plusieurs minutes pour poster un fichier de 1 MO mais 2 secondes
seulement pour un fichier texte de 60 ko. Le serveur tourne sur mon
portable cadencé à 2,4 Ghz.
Voici la partie de code (dans les grandes lignes) que j'aimerais
optimiser :
public class connexion extends Thread {
Socket client;
DataInputStream C;
PrintStream S;
public connexion(Socket client) {
this.client = client;
C = new DataInputStream(client.getInputStream());
S = new PrintStream(client.getOutputStream());
[...]
new Thread(this).start();
}
public void run() {
String line, result;
while ((line = C.readLine()) != null)
{
resultat = Appel_ma_métode_NNTP(line);
[...]
S.print(resultat);
}
}
Il semblerait que ce soit l'instruction C.readLine() qui ralentit la
transmission. Mon code peut-il être encore optimisé?
Quelles sont les performances du java dans un environnement serveur?
Je viens de coder un serveur NNTP, il fonctionne bien, mais il est
extraordinairement lent lorsqu'il s'agit de récupérer des articles avec
pièces jointes. Pour vous donner un ordre d'idées, en localhost il me
faut plusieurs minutes pour poster un fichier de 1 MO mais 2 secondes
seulement pour un fichier texte de 60 ko. Le serveur tourne sur mon
portable cadencé à 2,4 Ghz.
Voici la partie de code (dans les grandes lignes) que j'aimerais
optimiser :
public class connexion extends Thread {
Socket client;
DataInputStream C;
PrintStream S;
public connexion(Socket client) {
this.client = client;
C = new DataInputStream(client.getInputStream());
S = new PrintStream(client.getOutputStream());
[...]
new Thread(this).start();
}
public void run() {
String line, result;
while ((line = C.readLine()) != null)
{
resultat = Appel_ma_métode_NNTP(line);
[...]
S.print(resultat);
}
}
Il semblerait que ce soit l'instruction C.readLine() qui ralentit la
transmission. Mon code peut-il être encore optimisé?
Quelles sont les performances du java dans un environnement serveur?
Je viens de coder un serveur NNTP, il fonctionne bien, mais il est
extraordinairement lent lorsqu'il s'agit de récupérer des articles avec
pièces jointes. Pour vous donner un ordre d'idées, en localhost il me
faut plusieurs minutes pour poster un fichier de 1 MO mais 2 secondes
seulement pour un fichier texte de 60 ko. Le serveur tourne sur mon
portable cadencé à 2,4 Ghz.
Voici la partie de code (dans les grandes lignes) que j'aimerais
optimiser :
public class connexion extends Thread {
Socket client;
DataInputStream C;
PrintStream S;
public connexion(Socket client) {
this.client = client;
C = new DataInputStream(client.getInputStream());
S = new PrintStream(client.getOutputStream());
[...]
new Thread(this).start();
}
public void run() {
String line, result;
while ((line = C.readLine()) != null)
{
resultat = Appel_ma_métode_NNTP(line);
[...]
S.print(resultat);
}
}
Il semblerait que ce soit l'instruction C.readLine() qui ralentit la
transmission. Mon code peut-il être encore optimisé?
Quelles sont les performances du java dans un environnement serveur?
Je viens de coder un serveur NNTP, il fonctionne bien, mais il est
extraordinairement lent lorsqu'il s'agit de récupérer des articles avec
pièces jointes. Pour vous donner un ordre d'idées, en localhost il me
faut plusieurs minutes pour poster un fichier de 1 MO mais 2 secondes
seulement pour un fichier texte de 60 ko. Le serveur tourne sur mon
portable cadencé à 2,4 Ghz.
Voici la partie de code (dans les grandes lignes) que j'aimerais
optimiser :
public class connexion extends Thread {
Socket client;
DataInputStream C;
PrintStream S;
public connexion(Socket client) {
this.client = client;
C = new DataInputStream(client.getInputStream());
S = new PrintStream(client.getOutputStream());
[...]
new Thread(this).start();
}
public void run() {
String line, result;
while ((line = C.readLine()) != null)
{
resultat = Appel_ma_métode_NNTP(line);
[...]
S.print(resultat);
}
}
Il semblerait que ce soit l'instruction C.readLine() qui ralentit la
transmission. Mon code peut-il être encore optimisé?
J'utilise beaucoup les sockets, pour un volume de donnée très important
chez bon nombre de clients. Mes problèmes de performances sont plus liès
à la configuration du réseau qu'au code Java lui même.
Tout d'abord, j'utilise beaucoup de threads - ce que tu fais apparament.
Ensuite, je n'utilise JAMAIS readLine, mais je lis les
données en binaire. Ca n'a l'air de rien mais que fait readLine() ? Il
lit les octets un par un jusqu'à la détection du code de fin de ligne.
Chez moi, pour jouer, j'ai fait un - petit - serveur HTTP en Lisp. J'ai
abandonné l'équivalent Lisp de readLine() et je travaille directement
sur les octets que j'interprète.
Pratiquement, je dis au socket qu'il doit bufferiser sur 64 Ko - que ce
soit en Java ou en Lisp, cela me donne de bonne performance mais
peut-être que ton appli à besoin d'une autre valeur. Ensuite, je lis
caractère par caractère. Dans le cas du serveur HTTP, la détection de
CRLF me donne la fin de la ligne que j'envoie à un processus (thread,
c'est en Lisp) qui fait le traitement.
lecture des données jusqu'à la détection de fin de fichier (le socket
est fermé par l'appli en face) ou d'un time-out.
Voilà donc une solution - mais il y en a peut-être d'autres.
Bon courage,
Narberd.
J'utilise beaucoup les sockets, pour un volume de donnée très important
chez bon nombre de clients. Mes problèmes de performances sont plus liès
à la configuration du réseau qu'au code Java lui même.
Tout d'abord, j'utilise beaucoup de threads - ce que tu fais apparament.
Ensuite, je n'utilise JAMAIS readLine, mais je lis les
données en binaire. Ca n'a l'air de rien mais que fait readLine() ? Il
lit les octets un par un jusqu'à la détection du code de fin de ligne.
Chez moi, pour jouer, j'ai fait un - petit - serveur HTTP en Lisp. J'ai
abandonné l'équivalent Lisp de readLine() et je travaille directement
sur les octets que j'interprète.
Pratiquement, je dis au socket qu'il doit bufferiser sur 64 Ko - que ce
soit en Java ou en Lisp, cela me donne de bonne performance mais
peut-être que ton appli à besoin d'une autre valeur. Ensuite, je lis
caractère par caractère. Dans le cas du serveur HTTP, la détection de
CRLF me donne la fin de la ligne que j'envoie à un processus (thread,
c'est en Lisp) qui fait le traitement.
lecture des données jusqu'à la détection de fin de fichier (le socket
est fermé par l'appli en face) ou d'un time-out.
Voilà donc une solution - mais il y en a peut-être d'autres.
Bon courage,
Narberd.
J'utilise beaucoup les sockets, pour un volume de donnée très important
chez bon nombre de clients. Mes problèmes de performances sont plus liès
à la configuration du réseau qu'au code Java lui même.
Tout d'abord, j'utilise beaucoup de threads - ce que tu fais apparament.
Ensuite, je n'utilise JAMAIS readLine, mais je lis les
données en binaire. Ca n'a l'air de rien mais que fait readLine() ? Il
lit les octets un par un jusqu'à la détection du code de fin de ligne.
Chez moi, pour jouer, j'ai fait un - petit - serveur HTTP en Lisp. J'ai
abandonné l'équivalent Lisp de readLine() et je travaille directement
sur les octets que j'interprète.
Pratiquement, je dis au socket qu'il doit bufferiser sur 64 Ko - que ce
soit en Java ou en Lisp, cela me donne de bonne performance mais
peut-être que ton appli à besoin d'une autre valeur. Ensuite, je lis
caractère par caractère. Dans le cas du serveur HTTP, la détection de
CRLF me donne la fin de la ligne que j'envoie à un processus (thread,
c'est en Lisp) qui fait le traitement.
lecture des données jusqu'à la détection de fin de fichier (le socket
est fermé par l'appli en face) ou d'un time-out.
Voilà donc une solution - mais il y en a peut-être d'autres.
Bon courage,
Narberd.
Pratiquement, je dis au socket qu'il doit bufferiser sur 64 Ko - que
ce soit en Java ou en Lisp, cela me donne de bonne performance mais
peut-être que ton appli à besoin d'une autre valeur. Ensuite, je l is
caractère par caractère. Dans le cas du serveur HTTP, la détect ion de
CRLF me donne la fin de la ligne que j'envoie à un processus (thread ,
c'est en Lisp) qui fait le traitement.
Pas bête, c'est peut être ça qui fait défaut dans mon code, j'o uvre un
thread pour chaque socket crée à la connection d'un nouveau client,
ensuite je gère le stream à l'intérieur du thread.
Mon thread principal continue lalecture des données jusqu'à la détection de fin de fichier (le s ocket
est fermé par l'appli en face) ou d'un time-out.
Et que se passe t-il si le client envoie une courte commande qui ne
dépasse pas 64 ko? Le serveur va attendre que le tampon se remplisse
pour répondre au client?
Dans le cas d'un serveur NNTP chaque commande est validée par un "r n"
ou par un "rn.rn" (pour poster un article) et exige une réponse
immédiate, même si je mets un tout petit buffer de 16 octets, je ne
résoudrai pas le problème pour un faible trafic. Si le client tape la
commande "HELP", il aura rempli le tampon de 6 octets seulement.
Voilà donc une solution - mais il y en a peut-être d'autres.
Bon courage,
Narberd.
Pratiquement, je dis au socket qu'il doit bufferiser sur 64 Ko - que
ce soit en Java ou en Lisp, cela me donne de bonne performance mais
peut-être que ton appli à besoin d'une autre valeur. Ensuite, je l is
caractère par caractère. Dans le cas du serveur HTTP, la détect ion de
CRLF me donne la fin de la ligne que j'envoie à un processus (thread ,
c'est en Lisp) qui fait le traitement.
Pas bête, c'est peut être ça qui fait défaut dans mon code, j'o uvre un
thread pour chaque socket crée à la connection d'un nouveau client,
ensuite je gère le stream à l'intérieur du thread.
Mon thread principal continue la
lecture des données jusqu'à la détection de fin de fichier (le s ocket
est fermé par l'appli en face) ou d'un time-out.
Et que se passe t-il si le client envoie une courte commande qui ne
dépasse pas 64 ko? Le serveur va attendre que le tampon se remplisse
pour répondre au client?
Dans le cas d'un serveur NNTP chaque commande est validée par un "r n"
ou par un "rn.rn" (pour poster un article) et exige une réponse
immédiate, même si je mets un tout petit buffer de 16 octets, je ne
résoudrai pas le problème pour un faible trafic. Si le client tape la
commande "HELP", il aura rempli le tampon de 6 octets seulement.
Voilà donc une solution - mais il y en a peut-être d'autres.
Bon courage,
Narberd.
Pratiquement, je dis au socket qu'il doit bufferiser sur 64 Ko - que
ce soit en Java ou en Lisp, cela me donne de bonne performance mais
peut-être que ton appli à besoin d'une autre valeur. Ensuite, je l is
caractère par caractère. Dans le cas du serveur HTTP, la détect ion de
CRLF me donne la fin de la ligne que j'envoie à un processus (thread ,
c'est en Lisp) qui fait le traitement.
Pas bête, c'est peut être ça qui fait défaut dans mon code, j'o uvre un
thread pour chaque socket crée à la connection d'un nouveau client,
ensuite je gère le stream à l'intérieur du thread.
Mon thread principal continue lalecture des données jusqu'à la détection de fin de fichier (le s ocket
est fermé par l'appli en face) ou d'un time-out.
Et que se passe t-il si le client envoie une courte commande qui ne
dépasse pas 64 ko? Le serveur va attendre que le tampon se remplisse
pour répondre au client?
Dans le cas d'un serveur NNTP chaque commande est validée par un "r n"
ou par un "rn.rn" (pour poster un article) et exige une réponse
immédiate, même si je mets un tout petit buffer de 16 octets, je ne
résoudrai pas le problème pour un faible trafic. Si le client tape la
commande "HELP", il aura rempli le tampon de 6 octets seulement.
Voilà donc une solution - mais il y en a peut-être d'autres.
Bon courage,
Narberd.
Et que se passe t-il si le client envoie une courte commande qui ne
dépasse pas 64 ko? Le serveur va attendre que le tampon se remplisse
pour répondre au client?
Dans le cas d'un serveur NNTP chaque commande est validée par un
"rn" ou par un "rn.rn" (pour poster un article) et exige une
réponse immédiate, même si je mets un tout petit buffer de 16 octets,
je ne résoudrai pas le problème pour un faible trafic. Si le client
tape la commande "HELP", il aura rempli le tampon de 6 octets seulement.
Le thread de lecture doit faire une détection de fin de ligne.
De manière plus précise, mon serveur HTTP en Lisp qui traite bien des
lignes - mes autres applis traitent vraiment du binaire - a trois
threads par connexions. Le principal qui lit les données caractère par
caractère. Lorsqu'une fin de ligne est détectée, il la rajoute à une
liste de lignes et réveille un autre thread qui vide cette liste de
lignes. Le troisième thread gère l'écriture sur le socket. Ma machine
étant lente (233 MHz et 196 Mo de Ram lente), j'ai pu multiplier par 2.5
les temps de traitement.
En fait, on peut certainement utiliser readLine. L'avantage de ma
méthode est que je fait un peu plus que la détection de fin de ligne. Je
décode en partie le contenu à la volée. Le protocole HTTP, c'est
essaentielement quelque chose comme :
COMMANDE le reste
et donc je découpe déjà la ligne en deux parties. Cela aussi doit
modifier singulièrement la vitesse de traitement.
Un autre point : mon tableau de lignes est vidé régulièrement, je ne me
retrouve jamais (j'ai bien testé) avec plus de 20 ou 30 lignes en
mémoire en même temps. Si ton process de vidage de la liste est trop
lent, la liste augmente, bouffe de la mémoire et l'application est vite
pénalisée - les temps d'allocation augmente sérieusement lorsqu'on
commence à swapper. Au début, j'avais des problèmes de synchronisation
de process qui m'engorgeait la mémoire et faisait tout écrouler.
Maintenant, je suis à peu près aussi performant que mon serveur Apache -
mais avec moins de possibilités quand même - pour environ 15-20
connexions. Au delà, Apache est plus fort que moi, car il a une gestion
de connexions plus sophistiquée que la mienne, une méthode de mise en
cache des pages très plus mieux et plein d'autres trucs.
Et que se passe t-il si le client envoie une courte commande qui ne
dépasse pas 64 ko? Le serveur va attendre que le tampon se remplisse
pour répondre au client?
Dans le cas d'un serveur NNTP chaque commande est validée par un
"rn" ou par un "rn.rn" (pour poster un article) et exige une
réponse immédiate, même si je mets un tout petit buffer de 16 octets,
je ne résoudrai pas le problème pour un faible trafic. Si le client
tape la commande "HELP", il aura rempli le tampon de 6 octets seulement.
Le thread de lecture doit faire une détection de fin de ligne.
De manière plus précise, mon serveur HTTP en Lisp qui traite bien des
lignes - mes autres applis traitent vraiment du binaire - a trois
threads par connexions. Le principal qui lit les données caractère par
caractère. Lorsqu'une fin de ligne est détectée, il la rajoute à une
liste de lignes et réveille un autre thread qui vide cette liste de
lignes. Le troisième thread gère l'écriture sur le socket. Ma machine
étant lente (233 MHz et 196 Mo de Ram lente), j'ai pu multiplier par 2.5
les temps de traitement.
En fait, on peut certainement utiliser readLine. L'avantage de ma
méthode est que je fait un peu plus que la détection de fin de ligne. Je
décode en partie le contenu à la volée. Le protocole HTTP, c'est
essaentielement quelque chose comme :
COMMANDE le reste
et donc je découpe déjà la ligne en deux parties. Cela aussi doit
modifier singulièrement la vitesse de traitement.
Un autre point : mon tableau de lignes est vidé régulièrement, je ne me
retrouve jamais (j'ai bien testé) avec plus de 20 ou 30 lignes en
mémoire en même temps. Si ton process de vidage de la liste est trop
lent, la liste augmente, bouffe de la mémoire et l'application est vite
pénalisée - les temps d'allocation augmente sérieusement lorsqu'on
commence à swapper. Au début, j'avais des problèmes de synchronisation
de process qui m'engorgeait la mémoire et faisait tout écrouler.
Maintenant, je suis à peu près aussi performant que mon serveur Apache -
mais avec moins de possibilités quand même - pour environ 15-20
connexions. Au delà, Apache est plus fort que moi, car il a une gestion
de connexions plus sophistiquée que la mienne, une méthode de mise en
cache des pages très plus mieux et plein d'autres trucs.
Et que se passe t-il si le client envoie une courte commande qui ne
dépasse pas 64 ko? Le serveur va attendre que le tampon se remplisse
pour répondre au client?
Dans le cas d'un serveur NNTP chaque commande est validée par un
"rn" ou par un "rn.rn" (pour poster un article) et exige une
réponse immédiate, même si je mets un tout petit buffer de 16 octets,
je ne résoudrai pas le problème pour un faible trafic. Si le client
tape la commande "HELP", il aura rempli le tampon de 6 octets seulement.
Le thread de lecture doit faire une détection de fin de ligne.
De manière plus précise, mon serveur HTTP en Lisp qui traite bien des
lignes - mes autres applis traitent vraiment du binaire - a trois
threads par connexions. Le principal qui lit les données caractère par
caractère. Lorsqu'une fin de ligne est détectée, il la rajoute à une
liste de lignes et réveille un autre thread qui vide cette liste de
lignes. Le troisième thread gère l'écriture sur le socket. Ma machine
étant lente (233 MHz et 196 Mo de Ram lente), j'ai pu multiplier par 2.5
les temps de traitement.
En fait, on peut certainement utiliser readLine. L'avantage de ma
méthode est que je fait un peu plus que la détection de fin de ligne. Je
décode en partie le contenu à la volée. Le protocole HTTP, c'est
essaentielement quelque chose comme :
COMMANDE le reste
et donc je découpe déjà la ligne en deux parties. Cela aussi doit
modifier singulièrement la vitesse de traitement.
Un autre point : mon tableau de lignes est vidé régulièrement, je ne me
retrouve jamais (j'ai bien testé) avec plus de 20 ou 30 lignes en
mémoire en même temps. Si ton process de vidage de la liste est trop
lent, la liste augmente, bouffe de la mémoire et l'application est vite
pénalisée - les temps d'allocation augmente sérieusement lorsqu'on
commence à swapper. Au début, j'avais des problèmes de synchronisation
de process qui m'engorgeait la mémoire et faisait tout écrouler.
Maintenant, je suis à peu près aussi performant que mon serveur Apache -
mais avec moins de possibilités quand même - pour environ 15-20
connexions. Au delà, Apache est plus fort que moi, car il a une gestion
de connexions plus sophistiquée que la mienne, une méthode de mise en
cache des pages très plus mieux et plein d'autres trucs.
En fait, on peut certainement utiliser readLine. L'avantage de ma
méthode est que je fait un peu plus que la détection de fin de ligne. Je
décode en partie le contenu à la volée. Le protocole HTTP, c'est
essaentielement quelque chose comme :
COMMANDE le reste
et donc je découpe déjà la ligne en deux parties. Cela aussi doit
modifier singulièrement la vitesse de traitement.
Un autre point : mon tableau de lignes est vidé régulièrement, je ne me
retrouve jamais (j'ai bien testé) avec plus de 20 ou 30 lignes en
mémoire en même temps. Si ton process de vidage de la liste est trop
lent, la liste augmente, bouffe de la mémoire et l'application est vite
pénalisée - les temps d'allocation augmente sérieusement lorsqu'on
commence à swapper. Au début, j'avais des problèmes de synchronisation
de process qui m'engorgeait la mémoire et faisait tout écrouler.
En fait, on peut certainement utiliser readLine. L'avantage de ma
méthode est que je fait un peu plus que la détection de fin de ligne. Je
décode en partie le contenu à la volée. Le protocole HTTP, c'est
essaentielement quelque chose comme :
COMMANDE le reste
et donc je découpe déjà la ligne en deux parties. Cela aussi doit
modifier singulièrement la vitesse de traitement.
Un autre point : mon tableau de lignes est vidé régulièrement, je ne me
retrouve jamais (j'ai bien testé) avec plus de 20 ou 30 lignes en
mémoire en même temps. Si ton process de vidage de la liste est trop
lent, la liste augmente, bouffe de la mémoire et l'application est vite
pénalisée - les temps d'allocation augmente sérieusement lorsqu'on
commence à swapper. Au début, j'avais des problèmes de synchronisation
de process qui m'engorgeait la mémoire et faisait tout écrouler.
En fait, on peut certainement utiliser readLine. L'avantage de ma
méthode est que je fait un peu plus que la détection de fin de ligne. Je
décode en partie le contenu à la volée. Le protocole HTTP, c'est
essaentielement quelque chose comme :
COMMANDE le reste
et donc je découpe déjà la ligne en deux parties. Cela aussi doit
modifier singulièrement la vitesse de traitement.
Un autre point : mon tableau de lignes est vidé régulièrement, je ne me
retrouve jamais (j'ai bien testé) avec plus de 20 ou 30 lignes en
mémoire en même temps. Si ton process de vidage de la liste est trop
lent, la liste augmente, bouffe de la mémoire et l'application est vite
pénalisée - les temps d'allocation augmente sérieusement lorsqu'on
commence à swapper. Au début, j'avais des problèmes de synchronisation
de process qui m'engorgeait la mémoire et faisait tout écrouler.
Dans la boucle principale j'utilisais une variable de type String pour
stocker les requêtes (String contenu_article += chaine_lue;) en virant
cette simple instruction je suis environ 5000 fois plus rapide !!!!!!!
Comme les String sont immutables, cette concaténation exige chaque
Dans la boucle principale j'utilisais une variable de type String pour
stocker les requêtes (String contenu_article += chaine_lue;) en virant
cette simple instruction je suis environ 5000 fois plus rapide !!!!!!!
Comme les String sont immutables, cette concaténation exige chaque
Dans la boucle principale j'utilisais une variable de type String pour
stocker les requêtes (String contenu_article += chaine_lue;) en virant
cette simple instruction je suis environ 5000 fois plus rapide !!!!!!!
Comme les String sont immutables, cette concaténation exige chaque