[cours d'optimisation inside] Détournement de topic (merci phenix )

Détournement de topic (merci phenix ) [cours d'optimisation inside] - Java - Programmation

Marsh Posté le 25-09-2002 à 17:28:05    

Code :
  1. Runtime rt = Runtime.getRuntime();
  2.  long usage = (rt.totalMemory() - rt.freeMemory()) >> 10;


 

  • le ">>" c un décalage de bit?
  • usage correspond a la memoire vive utilisé par le prog?


 
edit: pour l optimisation c un peu plus bas ds cette meme page


Message édité par veryfree le 26-09-2002 à 15:42:32
Reply

Marsh Posté le 25-09-2002 à 17:28:05   

Reply

Marsh Posté le 25-09-2002 à 17:30:10    


 
C'est pour obtenir le resultat en KB, le KB valant 1024 soit 2^10


Message édité par kadreg le 25-09-2002 à 17:30:21

---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 25-09-2002 à 23:27:36    

ok
 et pour la premeiere explication j ai bon?
 

Citation :

usage correspond a la memoire vive utilisé par le prog?


Reply

Marsh Posté le 25-09-2002 à 23:31:06    

http://java.sun.com/j2se/1.3/docs/ [...] ntime.html
 
a peu pres, ouais. (Mémoire prise par la jvm) - (Memoire libre dans la jvm)

Reply

Marsh Posté le 26-09-2002 à 00:01:51    

lorill a écrit a écrit :

http://java.sun.com/j2se/1.3/docs/ [...] ntime.html
 
a peu pres, ouais. (Mémoire prise par la jvm) - (Memoire libre dans la jvm)




 
 :jap:

Reply

Marsh Posté le 26-09-2002 à 01:14:24    

mais euh pq on fait pas /1024 au lieu de >>10? :/


---------------
#19b | Mardi 18 Février 2003 - nous fêtons les Bernadette | contre le fleur icq!
Reply

Marsh Posté le 26-09-2002 à 09:02:27    

--greg-- a écrit a écrit :

mais euh pq on fait pas /1024 au lieu de >>10? :/




 
Tu peux, mais le "bit shifting" est l'operation la plus rapide qu'il soit avec la comparaison avec 0.
 
Juste une question de performance.
 
Bye

Reply

Marsh Posté le 26-09-2002 à 09:50:41    

phenixl a écrit a écrit :

 
 
Tu peux, mais le "bit shifting" est l'operation la plus rapide qu'il soit avec la comparaison avec 0.
 
Juste une question de performance.




 
 :jap:


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 26-09-2002 à 10:46:18    

ok, bon quand j'aurai quelques neurones qui seront revenus de voyage j'essaierai de comprendre comment ça marche [:dawa]

Reply

Marsh Posté le 26-09-2002 à 11:11:22    

Moi j'ai compris. Au passage, bon topic ! Instructif.


---------------
Le site de ma maman
Reply

Marsh Posté le 26-09-2002 à 11:11:22   

Reply

Marsh Posté le 26-09-2002 à 11:12:21    

tu décale le chiffre bianire de 10 => c'est comme si tu divisais 10 fois par 2 => comme si tu divisait par 10^2 => comme si tu divisais par 1024.
 
mais bon si ca se trouve, le compilateur repère ce genre de truc (division par une puissance de 2) et fait la modif tout seul ... ;)

Reply

Marsh Posté le 26-09-2002 à 11:14:42    

--greg-- a écrit a écrit :

ok, bon quand j'aurai quelques neurones qui seront revenus de voyage j'essaierai de comprendre comment ça marche [:dawa]




 
Simple. Imaginons un codage sur un octet (plus cout a ecrire)
 
00000001 = 1 = 2^0
00000010 = 2 = 2^1
00000100 = 4 = 2^2
00001000 = 8 = 2^3
...
 
Bon. Tu peux donc voir que quand tu decales le bit a gauche tu multiplie par 2, et si tu décale a droite tu divises par 2. C'est tout  :D

Reply

Marsh Posté le 26-09-2002 à 11:31:52    

benou a écrit a écrit :

tu décale le chiffre bianire de 10 => c'est comme si tu divisais 10 fois par 2 => comme si tu divisait par 10^2 => comme si tu divisais par 1024.
 
mais bon si ca se trouve, le compilateur repère ce genre de truc (division par une puissance de 2) et fait la modif tout seul ... ;)




Les bons compilo oui ...
Les tres bon font meme mieux
 
A*3 = a*2 + a = a << 1 + a


Message édité par Joel F le 26-09-2002 à 11:31:58
Reply

Marsh Posté le 26-09-2002 à 11:48:09    

euh vi en fait ça j'avais compris :D
mais c quoi que j'avais pas compris finalement? :D
 
à ouais: qu'advient-il des bits qui tombent dans le vide?

Reply

Marsh Posté le 26-09-2002 à 11:50:01    

--greg-- a écrit a écrit :

 
à ouais: qu'advient-il des bits qui tombent dans le vide?




 
plouf.

Reply

Marsh Posté le 26-09-2002 à 11:51:08    

Selon le decalage utilisé, soit ils bouclent, soit ils sont perdus, soit ils changent un obscur flag dans le processeur. Avec l'operateur >> ils disparaissent tout simplement.

Reply

Marsh Posté le 26-09-2002 à 11:57:11    

:jap:
 
je vais me taper un ptit résumé des opérateurs méconnus moua

Reply

Marsh Posté le 26-09-2002 à 11:59:17    

--greg-- a écrit a écrit :

 
je vais me taper un ptit résumé des opérateurs méconnus moua




 
Euh le decalage qui reinsere les bits a droite, je pense pas qu'il soit accessible via java. C'est ce qui me reste de mes cours d'asm

Reply

Marsh Posté le 26-09-2002 à 12:05:29    

tu veux dire à gauche :)

Reply

Marsh Posté le 26-09-2002 à 12:07:59    

ca depends dans quel sens tu parles  :D  
 
mais je voulais bien dire reinsertion a droite apres decalage a gauche :
 
10100000 -> 01000001

Reply

Marsh Posté le 26-09-2002 à 12:11:07    

euh ouais :)

Reply

Marsh Posté le 26-09-2002 à 14:41:06    

benou a écrit a écrit :

mais bon si ca se trouve, le compilateur repère ce genre de truc (division par une puissance de 2) et fait la modif tout seul ... ;)




De manière générale, il est déconseillé d'effectuer ce genre d'optimisations au niveau source, qui ne font que rendre plus difficile à lire le code, sans apporter de réel gain, car, comme le souligne très justement benou, la plupart des compilateurs incluent un optimiseur capable d'effectuer tout seul de telles optimisations à lucarne.
 
Maintenant, parlons Java. Le compilateur Java (JavaC comme Jikes) n'est pas, ou très peu, optimisant. La philosophie de Sun étant, je suppose, "on ne fait pas d'a priori sur le matériel sous-jacent quand on génère le bytecode". Vous retrouverez donc, au niveau du bytecode, la division par 1024 telle que vous l'avez écrite dans votre code source Java (d'ailleurs c'est logique d'un autre point de vue : si JavaC transformait la division par 1024 en un décalage à droite de 10 bits, on ne retrouverait pas le source original en décompilant le .class, ce qui est contraire à la philosophie de Java).
 
Mais de toute façon, le bytecode est lui-même interprété par la machine virtuelle, et cette dernière a la possibilité de faire l'optimisation, n'est-ce pas ? Pour le vérifier, j'ai fait un test avec mon JDK 1.4 et le code suivant :

Code :
  1. public class Test {
  2.     static final int NumIter = 100000000; // 100 millions
  3.     public static void main(String[] args) {
  4.         long toto = 0;
  5.         long titi = 204251345345342534L;
  6.         long start;
  7.         long end;
  8.         start = System.currentTimeMillis();
  9.         for (int i = 0; i < NumIter; i++) {
  10.             toto += titi / 1048576;
  11.         }
  12.         end = System.currentTimeMillis();
  13.         System.out.println("Division: " + (end - start) + " ms.   toto=" + toto);
  14.         toto = 0;
  15.         start = System.currentTimeMillis();
  16.         for (int i = 0; i < NumIter; i++) {
  17.             toto += titi >> 20;
  18.         }
  19.         end = System.currentTimeMillis();
  20.         System.out.println("Décalage: " + (end - start) + " ms.   toto=" + toto);
  21.     }
  22. }


 

> javac Test
Division: 9063 ms.   toto=1032182140990448384
Décalage: 1903 ms.   toto=1032182140990448384


Pas fameux. Mais Sun fournit une machine virtuelle bien plus optimisante qu'HotSpot : HotSpot Server. Et en effet :

> javac -server Test
Division: 391 ms.   toto=1032182140990448384
Décalage: 380 ms.   toto=1032182140990448384


(Note : sans le += dans la boucle, HotSpot Server aurait éliminé entièrement la boucle, car il aurait vu qu'elle ne servait à rien...)
 
Moralité : Avec HotSpot Server, oubliez la réécriture optimisante du code source. Le gain est nul, sauf en maintenabilité du code, où vous êtes perdant à tous les coups. Et quoi que vous fassiez, les optimiseurs des compilateurs, ou, ici, de la JVM, seront infiniment plus efficaces. Le pire, c'est qu'en optimisant à la main votre code source, vous risquez fort d'entraver le boulot, donc l'efficacité, de l'optimiseur...


Message édité par BifaceMcLeOD le 26-09-2002 à 14:42:28
Reply

Marsh Posté le 26-09-2002 à 14:48:19    

tres interessant tout ca merci Biface :jap:
 
 
 
 
perso y a encore qq chose que je comprend pas
 
lorsque mon programme tourne ,la valeur de usage varie entre 4000 - et 6000  
 
mais lorsque je regarde le gestionnaire de tache de win2k ca grimpe a 30 000 Ko parfois
pourquoi les valeurs ne correspondent pas?

Reply

Marsh Posté le 26-09-2002 à 14:50:47    

veryfree a écrit a écrit :

 
mais lorsque je regarde le gestionnaire de tache de win2k ca grimpe a 30 000 Ko parfois
pourquoi les valeurs ne correspondent pas?




 
parce que usage te file la mémoire prise par ton prog dans la jvm, w2k te file la mémoire prise par la jvm.

Reply

Marsh Posté le 26-09-2002 à 14:59:17    

Joel F a écrit a écrit :

 
Les bons compilo oui ...
Les tres bon font meme mieux
 
A*3 = a*2 + a = a << 1 + a




 
Ce genre de trucs tu peux oublier en java... les compilos existants ne le font pas ou tres peu...
 
Vu qu'on parle d'optimisation je me lache un coup :) :
 
Je parlais un peu plus haut de la comparaison avec 0 : c'est pareil, on ne pense que rarement a optimiser les boucles du genre :
 

Code :
  1. for (int i = 0; i < monVecteur.size(); i++) {
  2.   ...
  3. }


 
La pluspart des gens font ceci en pensant qu'ils ont optimise leur code en inlinant l'appel a la methode :
 

Code :
  1. int a = monVecteur.size();
  2. for (int i = 0; i < a; i++) {
  3.   ...
  4. }


 
Alors que le code le plus efficace et rapide est :
 

Code :
  1. for (int i = monVecteur.size(); i > 0; i--) {
  2.   ...
  3. }


 
Bien entendu si le but est de parcourir une STD l'ordre de parcours doit etre indifferent (on commence par la fin sinon), mais dans ce cas les temsp d'execution peuvent etre tres fortement reduits, car la comparaison avec 0 est immediate et ne demande aucun calcul.
 
Toujours au niveau de la performance : ca ne sert a rien de diminuer systematiquement la taille du code en inlinant certaines perties du code. Voici un exemple simple de HashTable optimise :  
 
Si on prend une fonction de hash bien equilibree et que l'on utilise une methode de stockage efficace, la collision lors de la l'insertion dans la table doit etre exceptionnelle. Ca c'est la theorie qui le veut.
 
Pourtant ce que l'on voit souvent dans les hashtables perso c'est un truc du genre :
 

Code :
  1. public void put(Object objet) {
  2.   while(pastrouveunemplacementlibre) {
  3.     chercher emplacement
  4.   }
  5.   inserer objet;
  6. }


 
Dans ce cas on adopte une attitude ou on pense que "ca ne va pas marcher"... et la theorie dit "ca marche presque toujours". Il est donc bien plus interessant de faire ainsi :
 

Code :
  1. public void put(Object objet) {
  2.   // loop unroll
  3.   inserer objet;
  4.   if (ca a marche) return;
  5.  
  6.   do {
  7.     chercher emplacement
  8.   }
  9.   while(pastrouveunemplacementlibre);
  10.   inserer objet;
  11. }


 
Oui il y a plus d'operations, mais UNIQUEMENT si on se trouve dans le cas exceptionnel ou l'insertion ne marche pas du premier coup ! Le loop unroll permet dans les cas normaux de gagner ENORMEMENT en termes d'efficacite.
 
Juste pour donner un ordre d'idee : en deux semaines, a force de bouquiner et chercher une solution theorique qui tient la route, on a reussi a diminuer le footprint de 150% et augmenter la vitesse de pres de 200% par rapport a une HT *deja optimisee* de maniere grossiere. On a code pendant 4 jours a tout casser pour tester differentes versions de nos HT :)  
 
Ah oui : le test consistait a lire et charger en memoire le bytecode de la jdk 1.3.1 en virant les redondances dues au constant pool.  
 
Le code n'etait pas minimal, mais bon la lisibilite etait la et le resultat aussi ;)
 
A+

Reply

Marsh Posté le 26-09-2002 à 15:00:58    

Biface toujours aussi efficace. :jap:


---------------
Le site de ma maman
Reply

Marsh Posté le 26-09-2002 à 15:19:45    

Cherrytree a écrit a écrit :

Biface toujours aussi efficace. :jap:  



une belle rime digne d'un NTM des grands jours :o

Reply

Marsh Posté le 26-09-2002 à 15:20:30    

--greg-- a écrit a écrit :

une belle rime digne d'un NTM des grands jours :o



:lol: Pff... Je frappe pas les singes. Sauf Joey Starr. [:ddr555]


---------------
Le site de ma maman
Reply

Marsh Posté le 26-09-2002 à 15:31:51    

BifaceMcLeOD a écrit a écrit :

 
difficile à lire le code, sans apporter de réel gain




 
Les compilos ne font que rarement des optimisations efficaces... et ne parlons meme pas de -O qui en gros ne fait que virer certains attributs du constant pool (linenumber, source file, deprecated...) et fait du inlining plus pousse.
 
Quant au gain je t'assure qu'utiliser le bit shift est TRES utile et te permet de gagner enormement (p.ex. travaux sur les flux video). Maintenant oui c'est moins lisible et il faut bien documenter le code... Dans certains cas c'est du "needed pain".
 
 

Citation :


je suppose, "on ne fait pas d'a priori sur le matériel sous-jacent quand on génère le bytecode". Vous retrouverez donc, au niveau du bytecode, la division par 1024 telle que vous l'avez écrite dans votre code source Java (d'ailleurs c'est logique d'un autre point de vue : si JavaC transformait la division par 1024 en un décalage à droite de 10 bits, on ne retrouverait pas le source original en décompilant le .class, ce qui est contraire à la philosophie de Java).


 
Sun n'a jamais voulu que l'on retrouve le code original a partir du bytecode apres decompilation. C'est une feature du bytecode, feature longtemps critiquee par les gens du mon C++, mais largement appreciee depuis.
 
Le compilo est simplement non optimisant, c'est tout (l'idee derriere etant que le JIT va faire du bon boulot, ce qui est souvent le cas, mais on peut AMELIORER ce comportement en suivant certaines regles). Oui la relecture est plus difficile, mais il faut savoir ce que l'on desire.
 
Pareil en C, C++, etc... Tu n'est pas oblige de faire certaines optimisations, mais tu as la possibilite de les faire, car tu sais que le compilo ne les fera jamais.
 

Citation :


Moralité : Avec HotSpot Server, oubliez la réécriture optimisante du code source. Le gain est nul, sauf en maintenabilité du code, où vous êtes perdant à tous les coups. Et quoi que vous fassiez, les optimiseurs des compilateurs, ou, ici, de la JVM, seront infiniment plus efficaces. Le pire, c'est qu'en optimisant à la main votre code source, vous risquez fort d'entraver le boulot, donc l'efficacité, de l'optimiseur...


 
Tu prends un test minimaliste pour tirer des conclusions hatives :  
 
- 100 mio d'operations ce n'est rien dans les cas ou tu fais du calcul intensif,  
 
- ta facon de calculer le temps pris par tes operations est tres discutable : ne JAMAIS prendre System.currentTimeMillis() ! tu ne vois nullement le temps cpu exact pris par tes calculs... Un meilleur test serait de faire deux tests separes et les lancer via la commande unix "time". La tu peux comparer tes resultats (tu lances tes tests 20 fois chacuns, tu vires le bruit et tu compares)
 
- Enfin dire que 11ms sur un calcul aussi simple ce n'est rien me fait sourrir (c'est quand meme 3%) :)  
 
Dans un contexte plus complique des optimisations faites a la main peuvent enormement faire varier les resultats : l'homme peut remettre dans un contexte particulier un probleme (cf mon post sur le loop unroll) et faire des optimisations qu'aucun JIT ne fera car a priori ce n'est pas une optimisation (le unroll est un cas bien particulier ou on s'appuie sur le contexte et non pas uniquement sur la grammaire) ou celle ci risque de modifier le sens du code (c.f. boucles inversees). C'est la qu'il faut se creuser les meninges.
 
Sinon oui pour les petits trucs le JIT se derbrouille bien mais pas toujours optimalement.
 
A+


Message édité par phenixl le 26-09-2002 à 15:33:00
Reply

Marsh Posté le 26-09-2002 à 15:41:25    

merci infiniment phenix
 
vraiment tres interessant  :jap:  
 
 
ps: j ai renommer le topic en consequence  :)

Reply

Marsh Posté le 26-09-2002 à 15:49:42    

tiré de : http://www.club-internet.fr/encyclopedie/
 
 
phénix [feniks] n. masc.  MYTH. Chez les Égyptiens, oiseau lié au culte du Soleil, dont il était l'image. Les Grecs, reprenant le mythe, firent du phénix, appelé boïnou chez les Égyptiens, un oiseau fabuleux qui, consumé dans les flammes, renaissait de ses cendres. Fig. (et souvent iron.) Personne qui a une intelligence, des capacités exceptionnelles

 
:jap: phenixl

Reply

Marsh Posté le 26-09-2002 à 16:22:17    

par exemple : "Mais t'es un vrai phénix, toi !" (Pensées, tome 2, Cherrytree)


---------------
Le site de ma maman
Reply

Marsh Posté le 26-09-2002 à 16:57:29    

phenixl> Je ne tirais pas de conclusions hâtives à partir d'un exemple très simple, j'ai illustré mon propos par un exemple très simple, nuance. Et contrairement à ce que tu sembles dire, cette illustration était parfaitement judicieuse : elle a permis de montrer qu'utiliser une JVM optimisante est incroyablement plus efficace que de rajouter une petite optimisation à lucarne à la main dans son source, optimisation qui rend par ailleurs celui-ci moins compréhensible.
 
Maintenant, je ne dis pas qu'il ne faut jamais optimiser à la main, mais je dis que l'optimisation est une discipline qui demande rigueur, et que ce genre d'optimisation à lucarne est exactement ce qu'il ne faut pas faire. Contrairement à ce que tu dis, la plupart des compilateurs modernes ont un mode optimisant très efficace. La doc de gcc en donne une bonne idée (quoique ne sont pas détaillées les optimisations concernant, par exemple, la gestion des parcours de tableaux en utilisant des pointeurs).
 
Malheureusement, JavaC est le parfait contre-exemple, et Jikes ne fait pas mieux car il a été conçu pour être un clone de JavaC du point de vue comportement (mais pas vitesse d'exécution ;) ).
 
Ce que je vais dire est le résultat d'études poussées sur des centaines voire des milliers de projets (ce n'est pas moi qui les ai fait, je vous rassure ;) ) : l'optimisation manuelle est rarement bénéfique, et sans mesures préalables précises et localisées (j'insiste sur ce dernier mot), elle ne l'est quasiment jamais. D'ailleurs le nombre de programmes qui requièrent d'être vraiment optimisés sont rares, surtout en Java (au passage, remplacer un algorithme par un autre pour que le programme soit plus rapide, je n'appelle pas ça à proprement parler de l' "optimisation" ).
 
Il est inutile et dangereux d'optimiser son source, sans avoir préalablement mesuré très précisément quels étaient ses goulots d'étranglement. Et le seul moyen d'obtenir ces mesures précises et localisées, ce n'est :

  • ni avec time(), qui est certes précis, mais ne donne absolument pas d'informations localisées -- il mesure un temps d'exécution global uniquement -- (et merci pour les utilisateurs de PC... ;) )
  • ni avec System.currentTimeMillisec(), je te l'accorde, qui permet d'avoir des informations localisées, certes, mais peu précises -- mais il est cependant capable de donner des ordres de grandeur, et c'est précisément l'usage que j'en ai fait dans mon illustration précédente.

Non, le seul outil véritablement valable, c'est le profileur, qui mesure précisément le temps d'exécution passé sur chacune des lignes de code source, et le nombre de fois qu'une ligne a été exécutée. Et souvent, un programme est lent parce qu'il a été mal conçu (mauvaise architecture), ou qu'une ou plusieurs fonctions sont appelées beaucoup trop souvent, alors qu'on pourrait garder leur résultat en mémoire entre les appels. Revoir l'architecture du programme ou appeler beaucoup moins souvent une fonction coûteuse est souvent bien plus efficace que faire une petite optimisation à lucarne dans un coin que l'on suppose souvent exécuté et/ou "trop" coûteux.
 
Exemples de profileurs pour Java : JProfiler, OptimizeIt, J-Sprint, ou le profileur fourni avec le J2SDK de Sun.
En C++, je n'en connais qu'un (ce qui ne veut pas dire qu'il n'y en a pas d'autre ;) ) : Rational Quantify.
 
Maintenant, c'est clair que dans certaines situations, on a besoin d'avoir un programme plus rapide que ce qu'il n'est, et plus rapide que ce que le compilateur peut générer. Dans ce cas, il est tout à fait possible de réécrire quelques fonctions en assembleur (tu vois, je n'imagine même pas qu'on puisse avoir ce besoin en Java), mais ces réécritures doivent être, autant que possible, localisées, pour minimiser le coût de maintenance future, et dans tous les cas dirigées par les informations que donne le profileur. Sinon, c'est du temps de développement perdu, et beaucoup de temps supplémentaire perdu dans le futur pour la maintenance et l'évolution du logiciel.
 
PS: Les posts aussi longs qui ne sont pas du flood sont rares en ces lieux. Merci de m'avoir lu jusqu'au bout ! ;)


Message édité par BifaceMcLeOD le 26-09-2002 à 17:07:01
Reply

Marsh Posté le 26-09-2002 à 17:10:13    

putain le mec qui prend4h pour écrire son post  :sleep:  
 
[:prosterne] :D

Reply

Marsh Posté le 26-09-2002 à 17:13:30    

--greg-- a écrit a écrit :

putain le mec qui prend4h pour écrire son post  :sleep:  
 
[:prosterne] :D




[:tapai] on ne décourage pas les bons eleves de ce forum :o


Message édité par veryfree le 26-09-2002 à 17:13:48
Reply

Marsh Posté le 26-09-2002 à 17:14:16    

veryfree a écrit a écrit :

 
[:tapai] on ne décourage pas les bons eleves de ce forum :o



ha bah non hein, j'ai mis un [:prosterne] justement...

Reply

Marsh Posté le 26-09-2002 à 17:27:41    

veryfree a écrit a écrit :

 
[:tapai] on ne décourage pas les bons eleves de ce forum :o



Les bons profs, j'aurais dit.


---------------
Le site de ma maman
Reply

Marsh Posté le 26-09-2002 à 17:35:02    

Cherrytree a écrit a écrit :

Les bons profs, j'aurais dit.




 
trop tard j ai deja été quoté 2 fois :D

Reply

Marsh Posté le 26-09-2002 à 17:43:46    

veryfree a écrit a écrit :

 
 
trop tard j ai deja été quoté 2 fois :D



Spagrave. Pour la peine, tu vas dire si c'est mieux un profkiroxxduluc ou un élèvekisuxxdubek.


---------------
Le site de ma maman
Reply

Marsh Posté le 26-09-2002 à 17:48:53    

Cherrytree a écrit a écrit :

Spagrave. Pour la peine, tu vas dire si c'est mieux un profkiroxxduluc ou un élèvekisuxxdubek.




non pitié ne detourne pas ce topic c pas c++ vs java ici :D
 [:totoz]

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed