PL_Andrev
PL_Andrev

Reputation: 21

Slow parsing of 23 kB XML file with more than half second

I'm trying to build objects based on xmlreader:

        List<Element> units = new List<Element>();

        string path = "D:\\Item\\Unit.xml";

        XElement xelement = XElement.Load(path);
        IEnumerable<XElement> elements = xelement.Elements();

        foreach (var c in elements)
        {
            Element stb = new Element();
            stb.Name = c.Element("Name").Value;
            stb.Picture = c.Element("Picture").Value;
            //and next 30 options included try / catch for int.Parse
         }

XML:

<?xml version="1.0" encoding="UTF-8"?>
<rows>
<row id="1">
    <Name>Freighter</Name>
    <Picture>Item\Freighter.gif</Picture>
    ... and 30 next rows with data for each "unit"
</row>
    ... and 30 next units...
<rows>

As I told, XML is 23kB file with 30 rows per each unit, with total 30 units in file. Not sure why this code is so slow: it took 670 miliseconds (i3 processor). The slowest part is obiect fillig, but not sure how to improve it.

The complete code looks exactly:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Diagnostics;

namespace element_reader
{
    class Program
    {
        static void Main(string[] args)
        {
            CustomStopwatch sw = new CustomStopwatch();
            sw.Start();

            List<Element> ships = new List<Element>();

            string path = "D:\\Ship_test.xml";

            XElement xelement = XElement.Load(path);
            IEnumerable<XElement> elements = xelement.Elements();

            sw.Stop();
            Console.WriteLine("Stopwatch elapsed: {0}, StartAt: {1}, EndAt: {2}", sw.ElapsedMilliseconds, sw.StartAt.Value, sw.EndAt.Value);
            sw.Start();

            foreach (var c in elements)
            {
                Element stb = new Element();
                stb.Name = c.Element("Name").Value;
                stb.Picture = c.Element("Picture").Value;

                try
                {
                    stb.Prt = int.Parse(c.Element("PRT").Value);
                }
                catch
                { stb.Prt = 0; }

                try
                {
                    stb.Lrt = int.Parse(c.Element("LRT").Value);
                }
                catch
                { stb.Lrt = 0; }

                stb.Special = c.Element("Special").Value;

                try
                {
                    stb.Wep = int.Parse(c.Element("Wep").Value);
                }
                catch
                { stb.Wep = 0; }

                try
                {
                    stb.Con = int.Parse(c.Element("Con").Value);
                }
                catch
                { stb.Con = 0; }

                try
                {
                    stb.Ene = int.Parse(c.Element("Ene").Value);
                }
                catch
                { stb.Ene = 0; }

                try
                {
                    stb.Ele = int.Parse(c.Element("Ele").Value);
                }
                catch
                { stb.Ele = 0; }

                try
                {
                    stb.Prp = int.Parse(c.Element("Prp").Value);
                }
                catch
                { stb.Prp = 0; }

                try
                {
                    stb.Bio = int.Parse(c.Element("Bio").Value);
                }
                catch
                { stb.Bio = 0; }


                try
                {
                    stb.Mass = int.Parse(c.Element("Mass").Value);
                }
                catch
                { stb.Mass = 0; }


                try
                {
                    stb.Iro = int.Parse(c.Element("Iro").Value);
                }
                catch
                { stb.Iro = 0; }

                try
                {
                    stb.Bor = int.Parse(c.Element("Bor").Value);
                }
                catch
                { stb.Bor = 0; }

                try
                {
                    stb.Ger = int.Parse(c.Element("Ger").Value);
                }
                catch
                { stb.Ger = 0; }

                try
                {
                    stb.Res = int.Parse(c.Element("Res").Value);
                }
                catch
                { stb.Res = 0; }


                ships.Add(stb);
            }

            sw.Stop();
            Console.WriteLine("Stopwatch elapsed: {0}, StartAt: {1}, EndAt: {2}", sw.ElapsedMilliseconds, sw.StartAt.Value, sw.EndAt.Value);
            Console.Read();
        }
    }

    public class Element
    {
        public string Name;
        public string Picture;

        public int Prt;
        public int Lrt;

        public string Special;

        public int Con;
        public int Wep;
        public int Ene;
        public int Ele;
        public int Prp;
        public int Bio;

        public int Mass;

        public int Iro;
        public int Bor;
        public int Ger;
        public int Res;
    }

    public class CustomStopwatch : Stopwatch
    {

        public DateTime? StartAt { get; private set; }
        public DateTime? EndAt { get; private set; }


        public void Start()
        {
            StartAt = DateTime.Now;

            base.Start();
        }

        public void Stop()
        {
            EndAt = DateTime.Now;

            base.Stop();
        }
    }
}

When the part of XML looks exactly:

<?xml version="1.0" encoding="UTF-8"?>
<rows>
<row id="1">
    <Name>Small Freighter</Name>
    <Picture>Item\Ship\Ship01_1.gif</Picture>
    <Description></Description>
    <PRT></PRT>
    <LRT></LRT>
    <Special></Special>

    <Ene>0</Ene>
    <Wep>0</Wep>
    <Prp>0</Prp>
    <Con>0</Con>
    <Ele>0</Ele>
    <Bio>0</Bio>

    <Slot1>-150, 0, Engine, 1, 1, 1</Slot1>
    <Slot2>-50, 0, Cargo, 70, 1, 1</Slot2>
    <Slot3>50, 0, DEF, 1, 1, 1</Slot3>
    <Slot4>150, 0, SEM, 1, 1, 1</Slot4>

    <Mass>25</Mass>

    <Res>20</Res>
    <Iro>12</Iro>
    <Res>0</Res>
    <Ger>17</Ger>

    <Fuel>130</Fuel>
    <Cargo>70</Cargo>
    <HPD_arm>25</HPD_arm>
    <Initiative>0</Initiative>
</row>
</rows>

Result is 70ms for 1kB file !!! If I have 20 files to load with 20-30 rows each this method is completely useless. Please notice that I do not use all data located in file.

Upvotes: 0

Views: 157

Answers (2)

apocalypse
apocalypse

Reputation: 5884

You didn't provide full xml file content, so I just only can suggest you one thing.
Use int.TryParse instead of int.Parse. I bet your code throws hundreds of exceptions which are very CPU expensive.

Upvotes: 1

jdweng
jdweng

Reputation: 34421

Usually the code should look like this :

            List<Element> elements = xelement.Descendants("TagName").Select(x => new Element() {
                Name = (string)x.Element("Name"),
                Picture = (string)x.Element("Picture")
            }).ToList();

Here is the comparison of the times Time 1 = '11.0082', Time 2 = '4.0032'

Here is code :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {

            Element newElement = new Element() {
                Name = "John",
                Picture = "Dorian Grey",
                Data1 = "1",
                Data2 = "1",
                Data3 = "1",
                Data4 = "1",
                Data5 = "1",
                Data6 = "1",
                Data7 = "1",
                Data8 = "1",
                Data9 = "1",
                Data10 = "1",
                Data11 = "1",
                Data12 = "1",
                Data13 = "1",
                Data14 = "1",
                Data15 = "1",
                Data16 = "1",
                Data17 = "1",
                Data18 = "1",
                Data19 = "1",
                Data20 = "1",
                Data21 = "1",
                Data22 = "1",
                Data23 = "1",
                Data24 = "1",
                Data25 = "1",
                Data26 = "1",
                Data27 = "1",
                Data28 = "1",
                Data29 = "1",
                Data30 = "1"
            };
            Root root = new Root();

            for (int i = 0; i < 29; i++)
            {
                root.elements.Add(newElement);
            }
            XmlWriterSettings setting = new XmlWriterSettings();
            setting.Indent = true;
            XmlWriter writer = XmlWriter.Create(FILENAME, setting);
            XmlSerializer serializer = new XmlSerializer(typeof(Root));
            serializer.Serialize(writer, root);
            writer.Flush();
            writer.Close();

            XDocument doc = XDocument.Load(FILENAME);

            DateTime start1 = DateTime.Now;

            List<Element> units = new List<Element>();
            List<XElement> elements = doc.Root.Elements().ToList();
            foreach (var c in elements)
            {
                Element stb = new Element();
                stb.Name = c.Element("Name").Value;
                stb.Picture = c.Element("Picture").Value;
                stb.Data1 = c.Element("Data1").Value;
                stb.Data2 = c.Element("Data2").Value;
                stb.Data3 = c.Element("Data3").Value;
                stb.Data4 = c.Element("Data4").Value;
                stb.Data5 = c.Element("Data5").Value;
                stb.Data6 = c.Element("Data6").Value;
                stb.Data7 = c.Element("Data7").Value;
                stb.Data8 = c.Element("Data8").Value;
                stb.Data9 = c.Element("Data9").Value;
                stb.Data10 = c.Element("Data10").Value;
                stb.Data11 = c.Element("Data11").Value;
                stb.Data12 = c.Element("Data12").Value;
                stb.Data13 = c.Element("Data13").Value;
                stb.Data14 = c.Element("Data14").Value;
                stb.Data15 = c.Element("Data15").Value;
                stb.Data16 = c.Element("Data16").Value;
                stb.Data17 = c.Element("Data17").Value;
                stb.Data18 = c.Element("Data18").Value;
                stb.Data19 = c.Element("Data19").Value;
                stb.Data20 = c.Element("Data20").Value;
                stb.Data21 = c.Element("Data21").Value;
                stb.Data22 = c.Element("Data22").Value;
                stb.Data23 = c.Element("Data23").Value;
                stb.Data24 = c.Element("Data24").Value;
                stb.Data25 = c.Element("Data25").Value;
                stb.Data26 = c.Element("Data26").Value;
                stb.Data27 = c.Element("Data27").Value;
                stb.Data28 = c.Element("Data28").Value;
                stb.Data29 = c.Element("Data29").Value;
                stb.Data30 = c.Element("Data30").Value;
                units.Add(stb);
            }
            DateTime end1 = DateTime.Now;

            DateTime start2 = DateTime.Now;
            List<Element> elements2 = doc.Descendants("elements").Select(x => new Element()
            {
                Name = (string)x.Element("Name"),
                Picture = (string)x.Element("Picture"),
                Data1 = (string)x.Element("Data1"),
                Data2 = (string)x.Element("Data2"),
                Data3 = (string)x.Element("Data3"),
                Data4 = (string)x.Element("Data4"),
                Data5 = (string)x.Element("Data5"),
                Data6 = (string)x.Element("Data6"),
                Data7 = (string)x.Element("Data7"),
                Data8 = (string)x.Element("Data8"),
                Data9 = (string)x.Element("Data9"),
                Data10 = (string)x.Element("Data10"),
                Data11 = (string)x.Element("Data11"),
                Data12 = (string)x.Element("Data12"),
                Data13 = (string)x.Element("Data13"),
                Data14 = (string)x.Element("Data14"),
                Data15 = (string)x.Element("Data15"),
                Data16 = (string)x.Element("Data16"),
                Data17 = (string)x.Element("Data17"),
                Data18 = (string)x.Element("Data18"),
                Data19 = (string)x.Element("Data19"),
                Data20 = (string)x.Element("Data20"),
                Data21 = (string)x.Element("Data21"),
                Data22 = (string)x.Element("Data22"),
                Data23 = (string)x.Element("Data23"),
                Data24 = (string)x.Element("Data24"),
                Data25 = (string)x.Element("Data25"),
                Data26 = (string)x.Element("Data26"),
                Data27 = (string)x.Element("Data27"),
                Data28 = (string)x.Element("Data28"),
                Data29 = (string)x.Element("Data29"),
                Data30 = (string)x.Element("Data30"),

            }).ToList();
            DateTime end2 = DateTime.Now;

            string results = string.Format("Time 1 = '{0}', Time 2 = '{1}'", (end1 - start1).TotalMilliseconds, (end2 - start2).TotalMilliseconds); 

            Console.ReadLine();
        }
    }

    public class Root
    {
        [XmlElement]
        public List<Element> elements = new List<Element>();
    }

    public class Element
    {
        public string Name { get; set; }
        public string Picture { get; set; }
        public string Data1 { get; set; }
        public string Data2 { get; set; }
        public string Data3 { get; set; }
        public string Data4 { get; set; }
        public string Data5 { get; set; }
        public string Data6 { get; set; }
        public string Data7 { get; set; }
        public string Data8 { get; set; }
        public string Data9 { get; set; }
        public string Data10 { get; set; }
        public string Data11 { get; set; }
        public string Data12 { get; set; }
        public string Data13 { get; set; }
        public string Data14 { get; set; }
        public string Data15 { get; set; }
        public string Data16 { get; set; }
        public string Data17 { get; set; }
        public string Data18 { get; set; }
        public string Data19 { get; set; }
        public string Data20 { get; set; }
        public string Data21 { get; set; }
        public string Data22 { get; set; }
        public string Data23 { get; set; }
        public string Data24 { get; set; }
        public string Data25 { get; set; }
        public string Data26 { get; set; }
        public string Data27 { get; set; }
        public string Data28 { get; set; }
        public string Data29 { get; set; }
        public string Data30 { get; set; }

    }
}

Upvotes: 0

Related Questions