IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les r�ponses en temps r�el, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

TMemoryStream : incompr�hension


Sujet :

C++Builder

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre tr�s actif Avatar de Argol_Medusa
    Homme Profil pro
    Ing�nieur Radiofr�quences
    Inscrit en
    Ao�t 2005
    Messages
    208
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : Ing�nieur Radiofr�quences
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 208
    Par d�faut TMemoryStream : incompr�hension
    Bonjour � tous,

    je suis en train de me poser de s�rieuses questions sur les TMemoryStream.

    Je souhaite mettre une grosse quantit� de donn�es en m�moire, afin de les traiter de mani�re rapide en __int64 , en utilisant la pleine puissante de mon processeur 64 bits.

    Pour se faire j'utilise la m�thode LoadFromFile pour charger des fichiers, et celle-ci :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    __int64 __fastcall CopyFrom(TStream* Source, __int64 Count);
    Ok, pas de souci, sauf que :

    void __fastcall WriteBuffer(const void *Buffer, int Count);
    ne permet d'�crire que 32K de donn�es ??? ( int et pas __int64 )

    J'essaye tout de m�me, la limitation de 32K ne semble pas �tre effective, car j'arrive � traiter de grosses quantit�es de donn�es qui d�passent largement les 32K, premi�re surprise, je ne trouve pas l'overload de la fonction en __int64

    Seconde surprise, je charge progressivement des fichiers, jusqu'� 230Mo :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
     
                    // copier ce fichier à la suite dans le bigbuffer
    		TMemoryStream *a;
    		a = new TMemoryStream();
    		a->LoadFromFile(Nom_Fichier);
    		char *buffer;
    		buffer = (char*) a->Memory;
    		this->BigBuffer->WriteBuffer(buffer,a->Size);
    et l� BIM :

    Le projet ifs.exe a d�clanch� la classe d'exception EOutOfMemory avec le message "m�moire insuffisante'


    What the ... ???

    Je teste vite fait pour v�rifier que ce n'est pas un probl�me de limitation windows ou quelque chose dans le genre :


    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
     
    unsigned __int64 taille = 1024*1024*550;
    MegaBuffer = new char[taille];
    for (unsigned __int64 i = 0; i < taille; i++)
    {
    	MegaBuffer[i]=0x66;
    }
    Ce dernier code fonctionne tr�s bien, en CTRL ALT SUPR je vois bien la m�moire de l'ex�cutable qui monte � plus de 550Mo


    Un habitu� des TMemoryStream pourrait-il m'�clairer? je dois rater un truc l�
    (La doc embarqu�e sur le C++ Builder ne me donne aucune indication int�ressante ).

  2. #2
    Expert �minent
    Avatar de ShaiLeTroll
    Homme Profil pro
    D�veloppeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 44
    Localisation : France, Seine Saint Denis (�le de France)

    Informations professionnelles :
    Activit� : D�veloppeur C++\Delphi
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par d�faut
    Citation Envoy� par Argol_Medusa Voir le message
    Je teste vite fait pour v�rifier que ce n'est pas un probl�me de limitation windows ou quelque chose dans le genre :
    ton test est-il dans la m�me appli, m�me contexte, une fuite m�moire dans le projet r�el ?

    Citation Envoy� par Argol_Medusa Voir le message
    Je souhaite mettre une grosse quantit� de donn�es en m�moire, afin de les traiter de mani�re rapide en __int64 , en utilisant la pleine puissante de mon processeur 64 bits.
    Quand tu �voques une grosse quantit� sur un processeur 64 bits,
    550Mo cela reste possible en 32bits, �trange d'avoir une erreur, je pense � une fuite m�moire !
    Pense au SWAP aussi, si tu n'as pas la RAM physique, il va finalement �crire dans le fichier d'�change !
    Ton traitement sera au final plus lent !

    En plus, tu parle de 64Bits, mais c'est l'adresse d'un pointeur ou la taille d'un fichier, ce n'est qu'une valeur, cela n'am�liore pas les performances d'�tre en 32 ou 64 bits, cela permet d'adresse plus de m�moire certe mais cela ne change pas les calculs surtout pour un TStream

    J'ai l'impression que tu confonds la taille des registres dont d�coulent les possibilit�s d'adressage avec la puissance de calcul ?!

    Dans le cas du TFileStream, en Win32 ou Win64,
    ReadBuffer\Read utilise toujours la fonction RTL FileRead qui encapsulent l'API ReadFile qui est toujours une version 32 bit,
    Seek (m�me la 64Bits) utile la fonction RTL FileSeek qui encaspulent l'API SetFilePointer qui utilise deux DWORD s�par� pour reconstituer un __int64 donc au final, tu n'utilises m�me pas un registre 64 mais deux registre 32

    Dans le cas du TMemoryStream, allocation maximale � 2Gio

    Tu semble connaitre d�j� la limite 2Go pour un process, j'ignore les limitation en 64, avec Delphi historiquement le compilateur refuse des variables de plus de 2Go (par exemple un tableau de 2^29 integer)
    Win32 lui-m�me refuse aussi plus de 2Go (que l'on peut passer � 3Go) par processus
    Qu'en est-il de Win64 et Delphi 64 ?
    C++ Builder est-il en 64 Bits, je ne crois pas, j'ignore les limites du langage � ce sujet mais le MemoryManager Delphi utilis� par TStream et ses descendants doivent limiter aussi la taille de variable � 2Go

    Un sujet � lire Probl�me de m�moire avec Delphi-5 sous 64 bits
    Autre �l�ment qui pourrait t'int�resser :
    GetHeapStatus
    Delphi 2006+ : GetMemoryManagerState

    Windows : GetProcessMemoryInfo ou GlobalMemoryStatus

    Sujet connexe : RAM non utilis�e

    voir Prise en charge de m�moire volumineuse disponible dans Windows Server 2003 et Windows 2000, article expliquant le commutateur /PAE et le commutateur /3GB
    Il doit y en avoir d'autres pour Vista\Seven, en plus WOW64 doit jouer lorsqu'un processus 32bits est utilis� sur un 64bits


    Citation Envoy� par Argol_Medusa Voir le message
    Pour se faire j'utilise la m�thode LoadFromFile pour charger des fichiers, et celle-ci :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    __int64 __fastcall CopyFrom(TStream* Source, __int64 Count);
    Pour LoadFromStream, tu peux effectivement copier un TFileStream vers un TMemoryStream, cela utilise CopyFrom en interne
    Pour LoadFromFile, c'est ni plus ni moins qu'un wrapper de TFileStream\LoadFromStream
    CopyFrom utilise un tampon de 60Kio pour la m�thode abstraite Read() et boucle jusqu'� ce que la quantit�e de donn�e restant � copier atteignent z�ro
    Si tu veux copier plusieurs Gio cela fera via quelques milliers d'it�rations de 60Kio

    Citation Envoy� par Argol_Medusa Voir le message
    WriteBuffer ne permet d'�crire que 32K de donn�es ??? ( int et pas __int64 )
    32K ??? D'o� te viens c'est limite ???
    32bit donne une limite de 2^31 = 2Gio !
    Tu devrais lire le code du ReadBuffer ou WriteBuffer, il utilise Read ou Write, en g�n�ral, cela lit le buffer d'un seul coup !
    Mais ils ont pr�vu pour des Stream que nous pourrions d�velopper qui forcerait une limitation de buffer, d'o� la boucle sur Stream en utilisant Read ou Write jusqu'� ce que la quantit� de donn�es souhait�e soit lues ou �crites

    Ensuite Read ou Write n'existe qu'en version 32Bit car Delphi Win32 est historiquement limit� � 2Go de donn�es pour un buffer (le param�tre de ces fonctions ne peut pas d�passer 2Go donc un Longint suffit), c'est surement li� au Win32 qui en g�re que 2Go pour un processus, � l'�poque, en 1998 (Delphi 3), on une grosse machine c'�tait 256Mo ! Il �tait inconsevable de charger plus de 64Mo dans un programme, le SWAP �tant tellement utilis� que les performances �taient plus mauvaises qu'avec une lecteur s�quentiel de fichier !

    Idem pour ReadBuffer ou WriteBuffer, il y a la m�me limite, j'ignore si le compilateur 64Bits permet de d�passer une variable de 2Go mais C++Builder est encore 32 bits !? XE3 n'apporte pas encore le 64 Bits en C++ ? Je croyais que c'est pour la prochaine version ?!

    Pour CopyFrom, cela supporte le 64bits parce que le receveur est un stream,
    pour un TFileStream, on peut atteindre plus de 2Go sans probl�me
    pour un TMemoryStream, c'est impossible la Capacity reste en Longint malgr� que Position ou Size soit en NativeInt (int ou __int64 selon compilateur, ce qui donne 2Gio ou 8Eio)
    A savoir que Capacity grossi 8Ko par allocation pour �viter des r�allocations par WriteBuffer

    Citation Envoy� par Argol_Medusa Voir le message
    J'essaye tout de m�me, la limitation de 32K ne semble pas �tre effective, car j'arrive � traiter de grosses quantit�es de donn�es qui d�passent largement les 32K, premi�re surprise, je ne trouve pas l'overload de la fonction en __int64
    Evidemment puisque cette limite de 32Kio n'existe pas !
    Et pas d'overload, tu confonds les fonctions utilisant un buffer et celle utilisant un TStream

    Citation Envoy� par Argol_Medusa Voir le message
    Le projet ifs.exe a d�clanch� la classe d'exception EOutOfMemory avec le message "m�moire insuffisante'
    Pense que ton processus �tant limit� � 2Go, si tu a plusieurs TStream en m�me temps, ils occuppent tous de la m�moire, donc c'est le cumul des buffers qui te limitera !
    On a d�j� parl�, pour ma part, je n'arrives pas � allouer plus de 1980Mio dans un programme, on est m�me pas � 2 Gio = 2048 Mio par ce qu'il doit y avoir la VCL qui bouffe la m�moire aussi

    Donc pense � lib�rer tes objets entre deux lectures !

    tu peux aussi lire le fichier manuellement avec le TFileStream par paquet de 60Kio au lieu de le charger le compl�tement puis de le recopier compl�tement,
    Aide via F1 - FAQ - Guide du d�veloppeur Delphi devant un probl�me - Pensez-y !
    Attention Troll M�chant !
    "Quand un homme a faim, mieux vaut lui apprendre � p�cher que de lui donner un poisson" Confucius
    Mieux vaut se taire et para�tre idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la m�diocrit� !

    L'exp�rience, c'est le nom que chacun donne � ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre tr�s actif Avatar de Argol_Medusa
    Homme Profil pro
    Ing�nieur Radiofr�quences
    Inscrit en
    Ao�t 2005
    Messages
    208
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : Ing�nieur Radiofr�quences
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 208
    Par d�faut
    Bonjour Shai, et merci pour ton aide.


    Citation Envoy� par ShaiLeTroll Voir le message
    ton test est-il dans la m�me appli, m�me contexte, une fuite m�moire dans le projet r�el ?
    Oui effectivement mon test sorti du contexte (ds autre appli s�par�e) c'est pas tr�s pertinent en effet, j'ai refais le test dans le m�me programme :

    - quand j'ajoute en TMemoryStream je peux monter � 200Mo environ de m�moire vive (apr�s �a crash), et si j'essaye de cr�er mon char de 400Mo, �a me jette aussi.
    - quand j'essaye d'abord le tableau de char, je monte � 400 Mo sans probl�me, je commence � ajouter des donn�es dans le memorystream et �a me jette au bout de 200Mo de memorystream ( soit 600Mo au total dans la m�moire vive )

    Je vais suivre la piste de la fuite m�moire, l'hypoth�se me semble tr�s probable en effet !


    Citation Envoy� par ShaiLeTroll Voir le message
    En plus, tu parle de 64Bits, mais c'est l'adresse d'un pointeur ou la taille d'un fichier, ce n'est qu'une valeur, cela n'am�liore pas les performances d'�tre en 32 ou 64 bits, cela permet d'adresse plus de m�moire certe mais cela ne change pas les calculs surtout pour un TStream

    J'ai l'impression que tu confonds la taille des registres dont d�coulent les possibilit�s d'adressage avec la puissance de calcul ?!
    Alors, en fait je parle bien de 2 choses distinctes mais mon explication n'�tait pas tr�s clair

    l'id�e de base �tait :

    - de charger jusqu'� 5 Go de donn�es � partir du HDD,
    - de les traiter ensuite en __int64 (traitement en pointeurs cette fois-ci, rien � voir donc avec la taille HDD) pour que les traitements soient plus rapides

    Sauf qu'effectivement (bien vu j'avais oubli�) windows est incapable de g�rer plus de 2 ou 3 Go � priori donc je dois m'attendre soit � un refus d'allocation m�moire soit � un swap qui va me ralentir, dans tous les cas �a me met mon architecture dans l'eau.

    Il va falloir que je revois ma copie ( ou trouver autre version de windows ? )
    D'autant plus que d'apr�s ce que tu me dis le traitement de la biblioth�que du C++ Builder n'est pas vraiment du 64 bits mais du 2x32bits


    Citation Envoy� par ShaiLeTroll Voir le message
    32K ??? D'o� te viens c'est limite ???
    32bit donne une limite de 2^31 = 2Gio !
    La limite vient de mon cerveau qui �tait fatigu� hier apr�m
    Je voyais une limite du int count dans : void __fastcall WriteBuffer(const void *Buffer, int Count);

    mais c'est un int (=long int sur PC) et pas un short int autant pour moi (c'est �a de basculer entre du �Controleur 16bits et du PC � longueur de journ�e !!) la limite est donc bien de (2^32)/2 =2^31 = 2Go tu as parfaitement raison, et �a explique aussi pourquoi je pouvais charger sans probl�me des fichiers de plus de 32K (�videment).



    Citation Envoy� par ShaiLeTroll Voir le message
    Tu devrais lire le code du ReadBuffer ou WriteBuffer, il utilise Read ou Write, en g�n�ral, cela lit le buffer d'un seul coup !
    Mais ils ont pr�vu pour des Stream que nous pourrions d�velopper qui forcerait une limitation de buffer, d'o� la boucle sur Stream en utilisant Read ou Write jusqu'� ce que la quantit� de donn�es souhait�e soit lues ou �crites
    Tu veux dire dans le cas o� on voudrait cr�er notre propre classe d�riv�e d'un TStream?
    Je n'arrivais pas � voir le code associ� au classes.hpp (classes.cpp), le F7 m'emm�ne directement en assembleur, mais en fait apr�s recherche dans les r�pertoires c'est dans classes.PAS, c'est du delphi ceci explique cela.
    Je vais regarder un peu leur code.


    Citation Envoy� par ShaiLeTroll Voir le message
    Idem pour ReadBuffer ou WriteBuffer, il y a la m�me limite, j'ignore si le compilateur 64Bits permet de d�passer une variable de 2Go mais C++Builder est encore 32 bits !? XE3 n'apporte pas encore le 64 Bits en C++ ? Je croyais que c'est pour la prochaine version ?!
    J'avais pos� la question sur leur page Youtube, mais pas eu de r�ponse, c'�tait juste avant la sortie du XE3.

    J'avais lu � l'�poque qu'ils avaient fait machine arri�re sur le XE3 qui devait �tre un 64bits mais finalement ce n'est � priori pas le cas.
    A v�rifier.

    Citation Envoy� par ShaiLeTroll Voir le message
    Pour CopyFrom, cela supporte le 64bits parce que le receveur est un stream,
    pour un TFileStream, on peut atteindre plus de 2Go sans probl�me
    pour un TMemoryStream, c'est impossible la Capacity reste en Longint malgr� que Position ou Size soit en NativeInt (int ou __int64 selon compilateur, ce qui donne 2Gio ou 8Eio)
    A savoir que Capacity grossi 8Ko par allocation pour �viter des r�allocations par WriteBuffer
    ...
    Pense que ton processus �tant limit� � 2Go, si tu a plusieurs TStream en m�me temps, ils occuppent tous de la m�moire, donc c'est le cumul des buffers qui te limitera !
    Effectivement Capacity est en int sur le TMemoryStream

    Bref, tout cela doit nous am�ne � une limitation autour de 2Go au total effectivement, mais �a n'explique pas pourquoi ma limitation est autour de 200Mo en m�moire, ton hypoth�se de fuite m�moire me plait assez, je vais re-regarder mon code

    Sinon concernant l'architecture globale, je vais devoir d�couper pour faire du traitement par petit packets (genre 100Mo) je pense.

    En tout cas merci bien pour tes r�ponses d�taill�es qui m'ont bien �clair�es !!

  4. #4
    Membre tr�s actif Avatar de Argol_Medusa
    Homme Profil pro
    Ing�nieur Radiofr�quences
    Inscrit en
    Ao�t 2005
    Messages
    208
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : Ing�nieur Radiofr�quences
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 208
    Par d�faut
    D�sol� pour le double post, je rajoute juste le code d'un test tout simple � partir de z�ro : je clique sur le button1 pour ajouter des donn�es (fichier de 40Mo) �a me claque � 500Mo de donn�es cette fois-ci.

    Mais il me semble voir par moment des mont�es br�ves � 700Mo(dans le gestionnaire des taches) lors de l'ajout du m�me fichier.

    Est-ce que la commande CopyFrom (oui j'ai remplac� la lecture directe par un copyfrom du coup ) n'utiliserait pas un buffer temporaire ou quelque chose qui ferait monter la m�moire ??

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    //---------------------------------------------------------------------------
     
    #include <vcl.h>
    #pragma hdrstop
     
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
     
    TMemoryStream *BigBuffer;
     
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)	: TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    		// copier ce fichier à la suite dans le bigbuffer
    		TMemoryStream *a;
    		a = new TMemoryStream();
    		a->LoadFromFile("c:\\del\\Copier coller sous C++Builder.avi");
    		BigBuffer->CopyFrom(a,a->Size);
    		a->Clear();
    		delete a;
    		a=NULL;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
     BigBuffer = new TMemoryStream();
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
    {
    	delete BigBuffer;
    	BigBuffer=NULL;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
    this->Button2->Caption=BigBuffer->Size;
    }
    //---------------------------------------------------------------------------

Discussions similaires

  1. messages incompr�hensibles
    Par devalender dans le forum Outils
    R�ponses: 2
    Dernier message: 06/07/2004, 16h53
  2. incompr�hension avec ado
    Par Orgied dans le forum Bases de donn�es
    R�ponses: 3
    Dernier message: 19/05/2004, 18h24
  3. [WSAD5] probleme incompr�hensible
    Par capitaine_banane dans le forum Eclipse Java
    R�ponses: 5
    Dernier message: 07/04/2004, 11h56
  4. Probl�me avec TMemoryStream + jpeg
    Par zymoplex dans le forum Langage
    R�ponses: 2
    Dernier message: 01/02/2004, 19h46
  5. [JSP] Erreur incompr�hensible
    Par xxaragornxx dans le forum Servlets/JSP
    R�ponses: 6
    Dernier message: 09/09/2003, 16h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo