Avatar billede Slettet bruger
14. marts 2007 - 10:19 Der er 10 kommentarer

XML commands = memory leak, why?

Hey gutter

Jeg fik en ide om at bruge XML til at sende kommandoer mellem server og klient, og lavede derfor denne klasse for at teste hvad det var i stand til. Jeg har nogle gange brug for at sende store mængder data, så xml ville være en smart løsning.

Ved testen laver jeg (bare for at teste) en xml med 1 million linier. Lidt overdrevet, men så kunne jeg teste hvad det var i stand til. Det virker også overraskende godt, bortset fra at det bruger uhyre meget RAM. Måske gør jeg det forkert? Jeg er godt klar over at 1 million linier fylder en del i rammene, men ikke 200 mb, og efter jeg har sendt rydder den heller ikke op.

Jeg har vedlagt det meget lille test projekt, gør det lidt nemmere. Brug IsServer bool værdien til at skifte mellem server og klient når i builder.

Jeg ville blive super glad hvis nogen ville se hvorfor den bruger så meget RAM

filen kan hentes i bunden af siden, jeg har desværre ikke flere point at give af.

http://files-upload.com/129719/XMLTest.rar.html
Avatar billede Slettet bruger
14. marts 2007 - 11:15 #1
Okay, har fundet ud af at ved at køre GC.Collect(); så rydder den en hel del op. Men den bruger stadig en smule for meget syntes jeg
Avatar billede Slettet bruger
14. marts 2007 - 13:20 #2
Hmm, har læst lidt på det, og det ser ud til at kalde GC.Collect ikke er den bedste idé

Jeg har testet lidt, og ved at sende commands 10000 gange lige efter hinanden, stiger mit RAM forbrug ikke. Men sender man STORE commands, så bibeholder den det i RAM'en.. men det bliver vel ryddet selv automatisk med tiden
Avatar billede lateralus Nybegynder
14. marts 2007 - 14:45 #3
(Jeg har ikke kigget på din source-code)
Er de 1 million linier repræsenteret i en streng på både server og klient? Eller laver du noget parsing/indlæsning af det (eksempelvis DOM eller SAX) og har data repræsenteret i et eller flere objekter? En DOM parser kan godt bruge rigelige mængder af memory. Til så store data mængder bør du nok undgå DOM.
Avatar billede Slettet bruger
14. marts 2007 - 14:49 #4
Det jeg gør er, Opretter XMLDocument, smider alt data ind i det og sender

XMLDocument XMLDoc = new XMLDocument();

Stream.WriteLine(XMLDoc.OuterText);


og på modtager siden:


XMLDocument XMLDoc = new XMLDocument();
XMLDoc.Load("String data fra receive");
Avatar billede arne_v Ekspert
14. marts 2007 - 17:25 #5
XML er ikke specielt velegner til meget store data

DOM parsere (som XmlDocument) er absolut ikke velegnede til store data maengder - ofte
fylder objektet 3-8 gange saa meget som XML filen

saa store XML filer i XmlDocument betyder stort memory forbrug

det er korrekt at du ikke vinder noget som helst ved eksplicit at kalde GC - den
koerer selv naar det er noedvendigt
Avatar billede arne_v Ekspert
14. marts 2007 - 17:26 #6
jeg lavede engang dette her lille program til at illustrere mekanismerne:

using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

namespace E
{
    public class MainForm : Form
    {
        byte[] b1;
        byte[] b3;
        byte[] b9;
        byte[] b27;
        private Label dotnet2app;
        private Label win2dotnet;
        private Button alloc1;
        private Button free1;
        private Button alloc3;
        private Button free3;
        private Button alloc9;
        private Button free9;
        private Button alloc27;
        private Button free27;
        private Button rungc;
        public MainForm()
        {
            InitializeComponent();
        }
        private void InitializeComponent() {
            dotnet2app = new Label();
            win2dotnet = new Label();
            alloc1 = new Button();
            free1 = new Button();
            alloc3 = new Button();
            free3 = new Button();
            alloc9 = new Button();
            free9 = new Button();
            alloc27 = new Button();
            free27 = new Button();
            rungc = new Button();
            SuspendLayout();
            dotnet2app.Location = new Point(50, 50);
            dotnet2app.Size = new Size(200, 50);
            win2dotnet.Location = new Point(300, 50);
            win2dotnet.Size = new Size(200, 50);
            alloc1.Location = new Point(50, 150);
            alloc1.Size = new Size(100, 50);
            alloc1.Text = "Allocate 1 MB";
            alloc1.Click += new EventHandler(Alloc1Click);
            free1.Location = new Point(300, 150);
            free1.Size = new Size(100, 50);
            free1.Text = "Free 1 MB";
            free1.Click += new EventHandler(Free1Click);
            alloc3.Location = new Point(50, 250);
            alloc3.Size = new Size(100, 50);
            alloc3.Text = "Allocate 3 MB";
            alloc3.Click += new EventHandler(Alloc3Click);
            free3.Location = new Point(300, 250);
            free3.Size = new Size(100, 50);
            free3.Text = "Free 3 MB";
            free3.Click += new EventHandler(Free3Click);
            alloc9.Location = new Point(50, 350);
            alloc9.Size = new Size(100, 50);
            alloc9.Text = "Allocate 9 MB";
            alloc9.Click += new EventHandler(Alloc9Click);
            free9.Location = new Point(300, 350);
            free9.Size = new Size(100, 50);
            free9.Text = "Free 9 MB";
            free9.Click += new EventHandler(Free9Click);
            alloc27.Location = new Point(50, 450);
            alloc27.Size = new Size(100, 50);
            alloc27.Text = "Allocate 27 MB";
            alloc27.Click += new EventHandler(Alloc27Click);
            free27.Location = new Point(300, 450);
            free27.Size = new Size(100, 50);
            free27.Text = "Free 27 MB";
            free27.Click += new EventHandler(Free27Click);
            rungc.Location = new Point(175, 550);
            rungc.Size = new Size(100, 50);
            rungc.Text = "Run garbage collection";
            rungc.Click += new EventHandler(RungcClick);
            ClientSize = new Size(550, 650);
            Controls.Add(dotnet2app);
            Controls.Add(win2dotnet);
            Controls.Add(alloc1);
            Controls.Add(free1);
            Controls.Add(alloc3);
            Controls.Add(free3);
            Controls.Add(alloc9);
            Controls.Add(free9);
            Controls.Add(alloc27);
            Controls.Add(free27);
            Controls.Add(rungc);
            Text = "Memory allocation demo";
            UpdateStatus();
            ResumeLayout(false);
        }
       
        private void UpdateStatus()
        {
            dotnet2app.Text = "Application has allocated from .NET " + GC.GetTotalMemory(false)/1000000 + " MB";
            win2dotnet.Text = ".NET has allocated from Windows " + Process.GetCurrentProcess().PrivateMemorySize/1000000 + " MB";
        }
       
        private void Alloc1Click(object sender, EventArgs e)
        {
            b1 = new byte[1000000];
            UpdateStatus();
        }
        private void Free1Click(object sender, EventArgs e)
        {
            b1 = null;
            UpdateStatus();
        }
        private void Alloc3Click(object sender, EventArgs e)
        {
            b3 = new byte[3000000];
            UpdateStatus();
        }
        private void Free3Click(object sender, EventArgs e)
        {
            b3 = null;
            UpdateStatus();
        }
        private void Alloc9Click(object sender, EventArgs e)
        {
            b9 = new byte[9000000];
            UpdateStatus();
        }
        private void Free9Click(object sender, EventArgs e)
        {
            b9 = null;
            UpdateStatus();
        }
        private void Alloc27Click(object sender, EventArgs e)
        {
            b27 = new byte[27000000];
            UpdateStatus();
        }
        private void Free27Click(object sender, EventArgs e)
        {
            b27 = null;
            UpdateStatus();
        }
        private void RungcClick(object sender, EventArgs e)
        {
            GC.Collect();
            UpdateStatus();
        }

        [STAThread]
        public static void Main(string[] args)
        {
            Application.Run(new MainForm());
        }
    }
}
Avatar billede kalp Novice
15. marts 2007 - 11:29 #7
Hvem sender også et så stort XmlDocument uden at pakke det først?
Benyt dig da af GZipStream som du finder i System.IO.Compression.

Det pakker udmærket!
Har testet med en XML fil på 35MB (blandet tekst) og den kom ned på 588KB
men det har selvfølgelig også noget at gøre med at det blot er tekst..

har også testet med en fil 282MB fil som kom ned på 2.44MB
men da den smed en OutOfMemory exception pludselig kan det være det hele ikke kom med.. jeg tror det dog  (selv om det virker ret overdrevet med den forskel!!!)
da jeg trykkede f10 efter at have lukket nogle programmer og så kørte den videre.

under alle omstændigheder så kan det betale sig at pakke en xml fil da den kommer til at fylde meget meget mindre!
Avatar billede Slettet bruger
15. marts 2007 - 12:41 #8
Ja, jeg kiggede faktisk netop på GZipStream i dag. Mit problem er, at min server skal modtage disse kommandoer, store som små. Så jeg tænkte om jeg ikke bare kunne Zippe alle kommandoer inden jeg sender, og så unzippe hos serveren

Men hvordan er den bedste løsning. Skal jeg så sende kommandoerne som en fil eller hvordan?
Avatar billede Slettet bruger
16. marts 2007 - 14:12 #9
gawi kan du svare på det?
Avatar billede kalp Novice
16. marts 2007 - 14:18 #10
jeg er ikke med på hvad du helt præcist spørger om:)

men hvis jeg har forstået dig korrekt så jo det kan du godt:)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester