XML Daten Parallel parsen



  • Erstmal fehlen wie immer die interessanten Punkte 😉

    // hier werden diverse Sachen gefiltert und extrahiert, damit sie in die Datenbankfelder eingetragen werden können

    Gerade in dem Bereich dürfte es am ehesten Optimierungs-Potential geben:

    tDbCommand.Parameters.AddWithValue("?title", Encoding.UTF8.GetBytes(tTitle));
                tDbCommand.Parameters.AddWithValue("?description", Encoding.UTF8.GetBytes(tDescription));
                tDbCommand.Parameters.AddWithValue("?lat", Encoding.UTF8.GetBytes(Latitude.ToString()));
                tDbCommand.Parameters.AddWithValue("?long", Encoding.UTF8.GetBytes(Longitude.ToString()));
                tDbCommand.Parameters.AddWithValue("?population", Encoding.UTF8.GetBytes(Population.ToString()));
    

    Hier drängt sich direkt die Frage auf warum alles umständlich in Bytes konvertiert wird. Wichtig wäre hier die Tabellen-definition zu kennen. u.U. triggerst Du hier auto-konvertierungen die dann wieder von bytes in die richtigen Datentypen verwandeln -> teuer... Auch wäre es sinnvoller das SQL-Command nur einmal zu erzeugen anstatt jedesmal ein neues -> stressed nur die Speicherverwaltung und erfordert jedesmal ein neues Parsen des SQL auf der Datenbank...

    Ansonsten, wie vermutet ist der eigendliche XMlTextReader nicht das Bottleneck, sondern die Verarbeitung der Daten. Bei einem Test mit 10 Millionen PAges läuft der Reader in knapp 2 Minuten durch (ohne internes Parsing).

    Vielleicht hilft Dir folgender Ansatz:

    using System;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.Xml;
    using System.Text;
    using System.IO;
    using System.Threading;
    
    namespace XmlTestStuff
    {
        static class Program
        {
            public static Queue<String> NodeQueue = new Queue<string>();
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Thread thread = new Thread(new ThreadStart(Worker));
                thread.IsBackground = true;
                thread.Start();
    
                // of course you can start more than one worker here, i.e. one worker per core)
                // when using more than one worker thread it might be needed to add synchronization code,
                // but not sure...
    
                using (XmlReader reader = XmlTextReader.Create("E:\\xmltest.xml"))
                {
                    reader.ReadToDescendant("page"); // find the very first node and read it
    
                    NodeQueue.Enqueue(reader.ReadInnerXml());
    
                    while (reader.ReadToNextSibling("page") ) // now find all the sibling, aka nodes at the same depth like the first one.
                    {
                        NodeQueue.Enqueue(reader.ReadInnerXml());
                    }
                }
            }
    
            static void Worker()
            {
                while (true)
                {
                    while (NodeQueue.Count == 0)
                    {
                        Thread.Sleep(250);
                    }
    
                    StringReader stringreader = new StringReader(NodeQueue.Dequeue());
                    using (XmlReader reader = XmlReader.Create(stringreader))
                    {
    
                        // do ther parsing
                    }
                }
            }
        }
    }
    


  • also ich wuerd sagen
    -> profiler
    alles andere ist bisher nur spekulation - am ende liegt das problem ganz woanders - dann hat man am falschen ende zeit investiert

    ich selber benutz immer den build in profiler der beim vs team system dabei ist - n externen kenn ich grad nicht



  • @loks:
    man kann mit Sicherheit noch hier und da ein paar Sachen optimieren, da werden im code noch einige reguläre Ausdrücke verwendet etc. und bei den SQL-Parametern ging es glaube ich um Sonderzeichen und UTF-8 Kodierung. Ich kann ja mal schauen, ob ich es auch noch anders machen kann, ohne das Fehler auftreten.

    Aber Primär ging es mir ja um die Frage, wie ich die ungenutzten Kerne ausnutzen kann und die Rechenlast effizient darauf verteilen kann.

    Ansonsten gefällt mir der Ansatz, wie du die page-Nodes durchgehst ganz gut, ich denke, das werde ich mal für meine sache übernehmen. Vielleicht kann ich aber mit der vorgehensweise 8 Threads erzeugen, die dann gleichzeitig die Nodes bearbeiten können, wobei die Worker-Methode und der NodeQueue nicht statisch sein dürfen, oder man legt jeweils einen pro Thread an, was aber glaube ich dann wieder nicht so intelligent sein dürfte 😉

    @Mr. Evil:
    Nach nem Profiler werde ich auch mal schauen, ich benutze Visual Studio 2008 Express Edition bzw. auch die Beta von Visual Studion 2010.


Anmelden zum Antworten