Разбор саксофона в GoLang - медленная скорость - PullRequest
0 голосов
/ 30 ноября 2018

Учитывая следующий код в C # / .NET Core 2.1

class Program
{
    static void Main(string[] args)
    {
        var totalAmountSeconds = 0;

        using (var reader = XmlReader.Create(@"C:\Users\kevin\Desktop\temp\XML.xml"))
        {
            var stopWatch = new Stopwatch();
            var elementCounter = 0;

            stopWatch.Start();

            foreach (var element in XmlReaderUtils.EnumerateAxis(reader, new[] { "Node" }))
            {
                elementCounter += 1;
            }

            stopWatch.Stop();
            totalAmountSeconds += stopWatch.Elapsed.Seconds;

            Console.WriteLine("Total '<Node />' elements: " + elementCounter);
        }

        using (var reader = XmlReader.Create(@"XML.xml"))
        {
            var stopWatch = new Stopwatch();
            var elementCounter = 0;

            stopWatch.Start();

            foreach (var element in XmlReaderUtils.EnumerateAxis(reader, new[] { "ArticleGroup" }))
            {
                elementCounter += 1;
            }

            stopWatch.Stop();
            totalAmountSeconds += stopWatch.Elapsed.Seconds;

            Console.WriteLine("Total '<ArticleGroup />' elements: " + elementCounter);
        }

        Console.WriteLine("Total amount of required seconds: " + totalAmountSeconds);
    }
}

public static class XmlReaderUtils
{
    public static IEnumerable<XElement> EnumerateAxis(XmlReader reader,
        string[] elements)
    {
        reader.MoveToContent();

        while (reader.Read())
        {
            switch (reader.NodeType)
            {
                case XmlNodeType.Element:
                    if (!elements.Contains(reader.Name)) continue;

                    yield return XNode.ReadFrom(reader) as XElement;

                    break;
            }
        }
    }
}

Я считаю, что точная копия этого кода в GoLang должна быть следующей:

package main

import (
    "encoding/xml"
    "fmt"
    "os"
    "time"
)

func main() {
    start := time.Now()

    xmlFile, _ := os.Open("XML.xml")
    defer xmlFile.Close()

    decoder := xml.NewDecoder(xmlFile)

    amountOfElements := 0
    for {
        t, _ := decoder.Token()
        if t == nil {
            break
        }

        // Inspect the type of the token just read.
        switch se := t.(type) {
        case xml.StartElement:
            if se.Name.Local == "Node" {
                amountOfElements++
            }
        }
    }

    fmt.Printf("Total '<Node />' elements: %v\n", amountOfElements)

    xmlFile, _ = os.Open("XML.xml")
    defer xmlFile.Close()

    decoder = xml.NewDecoder(xmlFile)

    amountOfElements = 0
    for {
        t, _ := decoder.Token()
        if t == nil {
            break
        }

        // Inspect the type of the token just read.
        switch se := t.(type) {
        case xml.StartElement:
            if se.Name.Local == "ArticleGroup" {
                amountOfElements++
            }
        }
    }

    fmt.Printf("Total '<ArticleGroup />' elements: %v\n", amountOfElements)

    fmt.Printf("Total elapsed time: %v", time.Since(start))
}

Выполнение кода в .NET занимает 1 минуту, а в GoLang - 2 минуты.Версия .NET создается с использованием конфигурации выпуска, go GoLang * go build выполняется.

Я ожидал, что GoLang будет быстрее, но действительно он оказался медленнее?Это нормально или я что-то упустил?

1 Ответ

0 голосов
/ 30 ноября 2018

xml.NewDecoder содержит два метода для чтения XML-токена из файла - Token () и RawToken () .

Tocken() содержит некоторые дополнительные проверки дляStartElement и EndElement сопоставляют и переводят префиксы пространства имен в соответствующие им URL-адреса.

Попробуйте RawToken(), если вы заметили эти функции.

PS В C # вы читаете 2 разных файла, в GO вы читаете один и тот же файл дважды.Может быть, второй файл меньше / проще в примере C #?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...