[java] - Classe Vector

Fermé
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 - 22 sept. 2008 à 13:37
Marco la baraque Messages postés 996 Date d'inscription vendredi 9 mai 2008 Statut Contributeur Dernière intervention 5 novembre 2009 - 26 sept. 2008 à 00:40
Bonjour bonjour,

Aujourd'hui c'est moi qui poste.

Je suis en train de faire une application pour uploader des fichiers sur un serveur, ce n'est pas là sa seule utilité mais c'est celle-ci qui me pose problème.

En effet il m'a semblé voir quelque part que la classe Vector était gourmande en ressources et qu'il était préférable d'en utiliser une autre mais je ne me souviens plus laquelle? List ? JList?

Parce que mon upload se fait bien mais il me semble lent. Donc j'aurais voulu essayer avec cette autre classe.

Si Marco ou quelqu'un voit de quoi je parle :)

Si vous voulez du code je vous en donne.
A voir également:

30 réponses

kij_82 Messages postés 4088 Date d'inscription jeudi 7 avril 2005 Statut Contributeur Dernière intervention 30 septembre 2013 857
23 sept. 2008 à 10:21
Re,

Oui ce sera la même chose. Il s'agit ici de flux de donnée (inputStream, file, etc.) et non d'objet représentant le fichier réellement (et donc ayant ses données).
Chose non possible avec RMI donc.

Par contre, puisque tu t'intéresse à transférer une suite d'octet de taille fixe (maximale je veux dire), effectivement, l'utilisation de la classe Vector ne sert à rien.
Pour ton besoin, un simple tableau de byte suffit : tu lis par paquet XX byte (que tu met dans ton tableau "buffer"), et hop, tu l'envoi.
Attention toutefois, RMI requière que les objets transmis soit Serizlisable, donc je te conseille de créer un objet java "conteneur" qui possèdera comme propriété ton tableau de byte de taille maximum celle que tu as définie.

Pour ce qui est de la méthode de remplissage de ton tableau de byte, libre à toi de faire de l'allocation mémoire dynamique.
Par exemple si ta taille maximum est de 10000K, plutôt que d'allouer que 10000K directement, tu peux allouer par tranche de 100K. Ainsi, le dernier "paquet" envoyé sera minimiser (selon la taille globale des fichiers à transférer bien sur), c'est toujours ça de gagner.

Avoir une linked list, je ne vois pas en quoi c'est utile. Une linked list te permet essentiellement de chainer des informations entre elle. Or dans ton cas, tu sais que tu lis par paquet ton fichier, puis tu envoi. L'ordre ne change pas, le serveur recompose dans le même ordre ton fichier à la réception. Enfin, c'est mon avis et je suis preneur d'arguments opposés :)

Autre petite remarque : si tu tiens tant à simplifier la vie des futurs utilisateurs, je te conseilles de ne pas faire ton programme en RMI, mais directement avec les Socket. Tu vas certainement avoir un peu plus de mal puisque que c'est un poil plus technique, mais au final, tu obtiendra plus de satisfaction coté utilisateur. Socket sera à mon avis bien plus rapide que RMI qui de base est un procédé relativement lourd quand il s'agit de faire une telle application (transfert de (gros) fichiers)) et qui d'autre part, t'impose tout un algorithme pour pouvoir découper / envoyer / recomposer tes fichiers. (ps: chose que tu devrais quand même faire avec les sockets, mais la bufferisation sera géré automatiquement par les sockets (et certainement mieux géré que nous nous pouvons le faire))
1
kij_82 Messages postés 4088 Date d'inscription jeudi 7 avril 2005 Statut Contributeur Dernière intervention 30 septembre 2013 857
22 sept. 2008 à 13:44
Bonjour,

List / ArrayList c'est pas mal. En sachant que ArrayList implémente List.
0
vignemail1 Messages postés 1246 Date d'inscription vendredi 8 octobre 2004 Statut Contributeur Dernière intervention 13 septembre 2019 259
22 sept. 2008 à 13:55
Tu as aussi LinkedList, cela dépend du type d'accès que tu veux.
0
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
22 sept. 2008 à 13:57
Rere,

Merci il me semblait bien que c'était ça mais je n'étais point sûr.

Mon appli est basée sur RMI parce que je n'avais pas envie de m'embêter sur la couche réseau.

Le problème c'est que pour envoyer mon objet fichier il m'aurait fallu d'abord le bufferiser en mémoire sauf que j'ai opté pour le multi upload par thread. Donc chargé plusieurs fichiers de plusieurs méga en mémoire je suis pas sur que ça aurait été terrible.

Donc j'ai du créer un "système" de bufferisation via un Vector à 150 000 de size max.
Dans celui-ci j'envoie donc au serveur une demande d'ouverture de fichier. Puis ensuite je lis mon fichier local et je remplis mon Vector au maximum de 150 000.
Au delà j'envoie les données qu'il contient au serveur, puis je le vide et charge des nouvelles données à envoyer.
Et enfin j'envoie au serveur une demande de fermeture de fichier.

Mais je trouve pas çà top en fin de compte, j'ai l'impression que c'est super lent. Ou alors je me fais des idées. Ou alors mon Vector est lent.
Et en plus mon code n'est pas encore nettoyé. Il y a du debug de partout :)
0
kij_82 Messages postés 4088 Date d'inscription jeudi 7 avril 2005 Statut Contributeur Dernière intervention 30 septembre 2013 857
22 sept. 2008 à 14:03
Le mieux est de choisir une classe qui s'auto alloue toute seul (fait par le moteur Java), plutôt que d'allouer tout moi un tableau super grand qui ne sera pas forcément utiliser à 100%.

LinkedList, pour du multi-upload je pense que tu peux oublier (?)
Reste les autres, personnellement je choisirais ArrayList parce que j'ai l'habitude de l'utiliser (ce qui n'est pas forcément un point positif a retenir car je l'utilise à toute les sauces :D)

Comme dis, ca dépends ensuite de l'utilisation que tu veux en faire, List de base est pas mal, ensuite tu peux vouloir manager ta list avec des méthodes qui n'existe pas dans la classe List, mais qui sont implémentées dans la classe ArrayList ou une autre. Donc à toi de voir.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
22 sept. 2008 à 14:12
Ah non non mon vector a un buffer différent selon la taille du fichier, il est pas défini à 150 000.

Je te mets mon code : :D

<code>

for(long i=0;i<l;i++)
{
if(i==(l-1))
{
buffer.addElement(bis.read());
result = server.writeMapFile(new Auth(login,password),file.getName(),srv,buffer);
}

else if(buffer.size() == 150000)
{
System.out.println("Buffer plein");
result = server.writeMapFile(new Auth(login,password),file.getName(),srv,buffer);
buffer.clear();
buffer.addElement(bis.read());
}
else
{
buffer.addElement(bis.read());
}
}

bis est un BufferedInputStream
buffer c'est mon Vector
server c'est mon connecteur au serveur
result est un objet de Type Result qui contient le résultat de l'action par le serveur, soit c'est bon soit pas bon
srv c'est juste une String que je récupère d'un Choice
Auth c'est pour vérifier l'authentification par le serveur
file c'est un objet de type File
0
Marco la baraque Messages postés 996 Date d'inscription vendredi 9 mai 2008 Statut Contributeur Dernière intervention 5 novembre 2009 328
22 sept. 2008 à 21:57
Salut Arth,
J'ai lu ton post, et j'ai plusieurs questions.

Tout d'abord, effectivement, on en avait parlé un jour, et en général il est préférable d'utiliser la classe LinkedList plutôt que Vector, car Vector est synchronized (à moins que ton objet soit utilisé dans un environnement multi-threadé bien sûr, comme c'est peut-être ton cas). D'ailleurs je me demande en quoi est-ce plus efficace d'utiliser un Vector qu'une LinkedList synchronized, mais là n'est pas la question (n'hésitez pas à me MP si vous avez des idées, ou connaissez la réponse :).

En fait je ne comprends pas très bien à quoi servent ton vecteur et ton buffer ici. Que cherches tu à faire exactement? Tu veux uploader une liste de fichiers, ou simplement découper ton fichier de taille imposante en paquets de la taille de ton buffer? C'est ta partie client ou ta partie serveur que tu affiches ici?

Cordialement,
0
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
22 sept. 2008 à 23:01
En fait le problème de RMI c'est que je peux très bien passer des objets en mode distant ou en récupérer en local ceci fonctionne très bien puisque c'est le principe de RMI.

Mon application servirait pour ma team de jeu en réseau puisque on a un serveur dédié linux, pour ajouter des nouvelles cartes des sons etc, puisque en FTP c'est un peu plus fastidieux. ET comme tout le monde ne sait pas trop utiliser un ordinateur j'ai souhaité faire cette appli là qui en doublé avec des scripts permettrait de faire cela super facilement.

Comme je ne voulais pas m'emmerder avec la couche réseau, j'ai donc pensé à RMI, mais comme écrit plus haut on ne peut donc qu'envoyer des objets persistants.

Mettons que j'ai un objet de type File à envoyer sur mon serveur, vu que RMI ne gère pas la bufferisation, et donc l'envoi continu de données, il m'aurait fallu pour chaque fichier à envoyer le charger en mémoire dans une List ou un Vector puis ensuite l'envoyer d'un seul bloc. Et si tu souhaites charger comme j'ai pensé à faire plusieurs fichiers via des thread en même temps, côté mémoire ça n'aurait pas été terrible.

Donc je me suis penché sur comment faire un petit buffer.

Le code que j'ai affiché c'est celui de mon client, et plus précisément du fonctionnement de mon buffer.

Donc la première boucle sert à parcourir tout mon fichier que je souhaites envoyer.
Ensuite pour chaque données lue je vérifie que :
- si la données lue est la dernière donnée, on ajoute l'objet au buffer, puis on envoie les données du buffer sur le réseau
- si la taille définie mais non inéchangeable du buffer est atteinte, alors on écrit le contenu du buffer sur la socket, puis on vide le Vector et enfin on ajoute à celui-ci la donnée.
- et puis en dernier si on n'est pas à la fin du fichier et si le buffer n'a pas atteint la taille fixée alors on ajoute la données lue au buffer.

Pourquoi 150 Ko en taille de buffer ? aléatoirement et surtout car mon débit en upload est de 16 Ko mais j'ai pensé à mettre plus grand.

Parce qu'au départ j'envoyais octet par octet chaque donnée lue dans un seul paquet au serveur.
Or si on calcul que chaque paquet envoyé contient un seul octet, avec un ping de 60 ms, cela fait un débit mettons dire de 8 à 10 octet / seconde, ce qui est pas top du tout, surtout pour charger des fichiers de plusieurs Méga. J'ai donc pensé à faire un buffer via un Vector.

Mais j'ai testé mon chargement avec cette méthode cet après-midi et c'est très lent. J'ai pensé que ça venait du Vector et de sa consommation ressources mais faut dire que mon débit n'est pas terrible non plus.
Alors je me disais pourquoi ne pas essayé avec un autre objet que le Vector et merde je retrouvais plus le nom :) et j'en ai appris d'autres du coup.

Voilà.

Loup.
0
Marco la baraque Messages postés 996 Date d'inscription vendredi 9 mai 2008 Statut Contributeur Dernière intervention 5 novembre 2009 328
22 sept. 2008 à 23:31
Ok, je comprends un peu mieux ton problème.
J'ai toutefois certains doutes, et encore des questions :)

La première chose, c'est : pourquoi t'embêtes-tu (enfin, je dis ça mais je n'y connais absolument rien) ? En principe tous ces problèmes de bufferisation sont gérées par les protocoles que tu utilises. Par exemple quand tu uploades un fichier via un formulaire, le protocole http se charge de découper ton fichier en trames (de 1518o je crois) qu'il va envoyer au serveur, et ton fichier va être reconstitué par le serveur.
Je ne sais pas trop comment fonctionne RMI, mais ne peux-tu pas instancier un objet de type File sur ton client et le passer directement au serveur sans utiliser de Vector. A mon avis la couche transport du protocole RMI s'occupe naturellement de bufferiser le flux.
De plus, je ne vois toujours pas à quoi te sert ton vector. C'est un vector dans lequel tu stockes quoi exactement? Des bytes ? Si tu peux passer directement un File via RMI, c'est une perte de temps d'utiliser un vector selon moi.

Si j'étais toi, j'essaierais de tester ta méthode en utilisant un logiciel qui examine les paquets sortants (genre Wireshark) afin de voir si effectivement les paquets que tu envoies au serveur font bien 150 Ko (donc si ton système de bufferisation fonctionne bien, ou si ce que tu construis est encore découpé par la couche transport).

En tous cas c'est intéressant, donc tiens nous au courant (en tout cas moi ça m'intéresse).

Cordialement,
0
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
22 sept. 2008 à 23:44
J'ai cherché figure toi :)

Mais je n'ai trouvé que ce que j'ai énoncé et donc que RMI ne gère pas cela.

Pour te dire en exemple puisque même si on me disait le contraire pas têtu j'ai essayé d'envoyer un fichier directement.

Alors tout content je récupère mon nom de fichier, je crée une nouvelle instance de File avec le nom, boom je l'envoie sur le serveur via la fonction qui va bien et ...
java.IOException => fichier C:/Documents and Settings/gna gna gn/gna gna gna.txt" non trouvé.

Et oui !! sur le serveur il a tenté de m'ouvrir mon fichier Windows pour le lire. Comme je le lui demandais tu me diras mais non non c'est pas possible ça.

Ou alors j'ai sauté une grand épisode de RMI. Mais je suis persuadé qu'il ne fait pas de buffering.

M'enfin je désespère pas.

Pour répondre pour le Vector => il stocke des entiers de type Integer. Parce que mes fichiers sont des fichiers zippés, et donc cela nécessite une copie parfaite des données de chaque fichier envoyé.
Il sert juste à stocker plusieurs données à la suite, mais comme je n'ai pas de taille précise vu que chaque fichier a une taille différente je l'utilise donc pour faire de la taille dynamique.
Et pour comme j'ai dit plus haut, si tu envoie un seul paquet à la fois, le débit est d'environ 600 Octets / minutes, alors que si tu charges un nombre X de données dans ton Vector, cela sera beaucoup plus rapide puisque tu n'a plus la contrainte du ping, du réseau, et du temps d'acheminement des paquets. Et surtout parce que au lieu d'envoyer dans chaque paquet un seul octet utile, tu envoie un paquet avec le nombre max d'octets utiles. Et donc un gain de temps considérable.
0
Marco la baraque Messages postés 996 Date d'inscription vendredi 9 mai 2008 Statut Contributeur Dernière intervention 5 novembre 2009 328
23 sept. 2008 à 00:08
Ok, je comprends beaucoup mieux maintenant.
Tu as raison pour ton vector (utilise donc une LinkedList dans ce cas, tu gagneras sans doute un peu de temps).
C'est quand même dommage de réinventer la roue, parce que je pense que c'est carrément possible de se débrouiller avec l'API java.
Tu ne peux pas non plus envoyer de FileInputStream ou de ZipInputStream via RMI (j'imagine que tu as essayé avec ton BufferedInputStream) ?
0
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
23 sept. 2008 à 00:14
J'ai même pas tenté à vrai dire. Je me suis dit que ca allait être pire qu'avec le coup du Vector. ET je pense que ça ne marchera pas puisque on ne fait que récupérer un objet et je suis pas sûr que si je passe au serveur mon BIS il va me gérer une ouverture d'un ficher ouvert en local sur le serveur.

M'enfin on peut toujours tenter l'impossible :)
0
Marco la baraque Messages postés 996 Date d'inscription vendredi 9 mai 2008 Statut Contributeur Dernière intervention 5 novembre 2009 328
23 sept. 2008 à 00:22
Ouai, ça risque de faire pareil qu'avec le File. M'enfin si ça fonctionne, je pense que ce sera beaucoup plus performant.
0
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
23 sept. 2008 à 00:23
Ah pour le coup sans doute.
0
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
23 sept. 2008 à 12:10
Certes mais avec les Socket ça va être plus long et plus chiant à faire, parce qu'il faudrait mettre des contrôles de données partout créer des mots à chercher type <datamap> pour savoir que va envoyer une donnée concernant une map etc.

M'enfin ...
0
kij_82 Messages postés 4088 Date d'inscription jeudi 7 avril 2005 Statut Contributeur Dernière intervention 30 septembre 2013 857
23 sept. 2008 à 14:56
Le format XML est ton ami si tu veux transférer tes données selon un schéma / squelette type imposé.
Un parseur coté serveur pour interpréter / récupérer tes données c'est vite fais.

Après à toi de voir quelle solution te correspond le plus.
0
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
23 sept. 2008 à 21:51
Ah ça par contre j'ai jamais vu.

Je vais chercher voir de quoi il s'agit.
0
sandul Messages postés 3924 Date d'inscription jeudi 22 mai 2008 Statut Membre Dernière intervention 8 octobre 2010 723
23 sept. 2008 à 23:15
Salut,

My two cents dans cette affaire :-)

Si tu veux utiliser RMI pour transmettre un fichier, tu peux sûrement utiliser un tableau de bytes ou un String (les deux objets étant sérialisables et donc transmis sans problème par rmi). Maintenant, à mon avis, si tu ne peux pas tout envoyer d'un coup (car fichier trop gros par rapport à la mémoire dispo), il faut découper le fichier et là il y aurait 2 scénarios:
1 - appels rmi synchro (==> pas de souci, mais bloquant); toutefois, tu peux très bien faire tous les appels concernant l'envoi d'un même fichier dans un seul thread ==> et ceci serait ok
2- appels asychro avec un pool de threads pour optimiser ==> un peu plus compliqué, car l'ordre de réception n'est pas garantie de l'autre côté. Tu pourrais, par contre, rajouter facilement un 2ème paramètre pour indiquer le numéro de la séquence dans le découpage et utilier ce numéro pour la reconstitution.

Je ne suis pas sûr que (2) serait à préférer à (1) si (1) fait l'envoi dans un thread dédié par fichier à envoyer. M'enfin, cela dépend de la situation concrète, un peu difficile à imaginer.

++
0
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
24 sept. 2008 à 00:35
Je me demanderais presque si je devrais pas me mettre aux architectures 3 tiers et aux application servers pour le coup.

Mais bon je suis pas sûr d'y arriver.
0
sandul Messages postés 3924 Date d'inscription jeudi 22 mai 2008 Statut Membre Dernière intervention 8 octobre 2010 723
24 sept. 2008 à 00:36
Si c'est uniquement pour le souci de transfert de fichier, le rmi peut très bien faire l'affaire, à mon avis...
0
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
24 sept. 2008 à 00:39
Faut que je trouve la faille de cette merde :)
0
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
24 sept. 2008 à 00:40
Sinon c'est clair que je vais créer mon protocole de transfert sans doute en xml vu que tu le suggérais, et me concentrer sur des socket en mode Thread.
0
sandul Messages postés 3924 Date d'inscription jeudi 22 mai 2008 Statut Membre Dernière intervention 8 octobre 2010 723
24 sept. 2008 à 00:43
Effectivement, j'ai vu une suggestion de xml dans un post above (qui ne m'appartient pas), mais je n'ai pas tout suivi (quel serait le besoin du xml pour transférer un fichier? mais sûrement j'ai lu un peu trop vite...)

Tu peux faire des threads sans socket (je veux dire uniquement avec ce que tu as implémenté, à savoir des appels rmi).
0
arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
24 sept. 2008 à 00:46
Oui mais cela me semble vachement lent que même que même.

Ou alors je ne pige plus rien au réseau.
0