Я работаю над проверкой концепции для исследования времени, необходимого для анализа XML-документа с определенным количеством объектов.
Прежде всего, у меня есть структура, содержащая записи в моемXML-документ:
type Node struct {
ID int `xml:"id,attr"`
Position int `xml:"position,attr"`
Depth int `xml:"depth,attr"`
Parent string `xml:"parent,attr"`
Name string `xml:"Name"`
Description string `xml:"Description"`
OwnInformation struct {
Title string `xml:"Title"`
Description string `xml:"Description"`
} `xml:"OwnInformation"`
Assets []struct {
ID string `xml:"id,attr"`
Position int `xml:"position,attr"`
Type string `xml:"type,attr"`
Category int `xml:"category,attr"`
OriginalFile string `xml:"OriginalFile"`
Description string `xml:"Description"`
URI string `xml:"Uri"`
} `xml:"Assets>Asset"`
Synonyms []string `xml:"Synonyms>Synonym"`
}
Далее у меня есть фабрика, которая может генерировать любое заданное количество элементов:
func CreateNodeXMLDocumentBytes(
nodeElementCount int) []byte {
xmlContents := new(bytes.Buffer)
xmlContents.WriteString("<ROOT>\n")
for iterationCounter := 0; iterationCounter < nodeElementCount; iterationCounter++ {
appendNodeXMLElement(iterationCounter, xmlContents)
}
xmlContents.WriteString("</ROOT>")
return xmlContents.Bytes()
}
// PRIVATE: appendNodeXMLElement appends a '<Node />' elements to an existing bytes.Buffer instance.
func appendNodeXMLElement(
counter int,
xmlDocument *bytes.Buffer) {
xmlDocument.WriteString("<Node id=\"" + strconv.Itoa(counter) + "\" position=\"0\" depth=\"0\" parent=\"0\">\n")
xmlDocument.WriteString(" <Name>Name</Name>\n")
xmlDocument.WriteString(" <Description>Description</Description>\n")
xmlDocument.WriteString(" <OwnInformation>\n")
xmlDocument.WriteString(" <Title>Title</Title>\n")
xmlDocument.WriteString(" <Description>Description</Description>\n")
xmlDocument.WriteString(" </OwnInformation>\n")
xmlDocument.WriteString(" <Assets>\n")
xmlDocument.WriteString(" <Asset id=\"0\" position=\"0\" type=\"0\" category=\"0\">\n")
xmlDocument.WriteString(" <OriginalFile>OriginalFile</OriginalFile>\n")
xmlDocument.WriteString(" <Description>Description</Description>\n")
xmlDocument.WriteString(" <Uri>Uri</Uri>\n")
xmlDocument.WriteString(" </Asset>\n")
xmlDocument.WriteString(" <Asset id=\"1\" position=\"1\" type=\"1\" category=\"1\">\n")
xmlDocument.WriteString(" <OriginalFile>OriginalFile</OriginalFile>\n")
xmlDocument.WriteString(" <Description>Description</Description>\n")
xmlDocument.WriteString(" <Uri>Uri</Uri>\n")
xmlDocument.WriteString(" </Asset>\n")
xmlDocument.WriteString(" <Asset id=\"2\" position=\"2\" type=\"2\" category=\"2\">\n")
xmlDocument.WriteString(" <OriginalFile>OriginalFile</OriginalFile>\n")
xmlDocument.WriteString(" <Description>Description</Description>\n")
xmlDocument.WriteString(" <Uri>Uri</Uri>\n")
xmlDocument.WriteString(" </Asset>\n")
xmlDocument.WriteString(" <Asset id=\"3\" position=\"3\" type=\"3\" category=\"3\">\n")
xmlDocument.WriteString(" <OriginalFile>OriginalFile</OriginalFile>\n")
xmlDocument.WriteString(" <Description>Description</Description>\n")
xmlDocument.WriteString(" <Uri>Uri</Uri>\n")
xmlDocument.WriteString(" </Asset>\n")
xmlDocument.WriteString(" <Asset id=\"4\" position=\"4\" type=\"4\" category=\"4\">\n")
xmlDocument.WriteString(" <OriginalFile>OriginalFile</OriginalFile>\n")
xmlDocument.WriteString(" <Description>Description</Description>\n")
xmlDocument.WriteString(" <Uri>Uri</Uri>\n")
xmlDocument.WriteString(" </Asset>\n")
xmlDocument.WriteString(" </Assets>\n")
xmlDocument.WriteString(" <Synonyms>\n")
xmlDocument.WriteString(" <Synonym>Synonym 0</Synonym>\n")
xmlDocument.WriteString(" <Synonym>Synonym 1</Synonym>\n")
xmlDocument.WriteString(" <Synonym>Synonym 2</Synonym>\n")
xmlDocument.WriteString(" <Synonym>Synonym 3</Synonym>\n")
xmlDocument.WriteString(" <Synonym>Synonym 4</Synonym>\n")
xmlDocument.WriteString(" </Synonyms>\n")
xmlDocument.WriteString("</Node>\n")
}
Далее у меня есть приложение, которое создает образец документа и декодируеткаждый элемент '':
func main() {
nodeXMLDocumentBytes := factories.CreateNodeXMLDocumentBytes(100)
xmlDocReader := bytes.NewReader(nodeXMLDocumentBytes)
xmlDocDecoder := xml.NewDecoder(xmlDocReader)
xmlDocNodeElementCounter := 0
start := time.Now()
for {
token, _ := xmlDocDecoder.Token()
if token == nil {
break
}
switch element := token.(type) {
case xml.StartElement:
if element.Name.Local == "Node" {
xmlDocNodeElementCounter++
xmlDocDecoder.DecodeElement(new(entities.Node), &element)
}
}
}
fmt.Println("Total '<Node />' elements in the XML document: ", xmlDocNodeElementCounter)
fmt.Printf("Total elapsed time: %v\n", time.Since(start))
}
Это занимает около 11 мс на моем компьютере.
Далее я использовал goroutines для декодирования элементов XML:
func main() {
nodeXMLDocumentBytes := factories.CreateNodeXMLDocumentBytes(100)
xmlDocReader := bytes.NewReader(nodeXMLDocumentBytes)
xmlDocDecoder := xml.NewDecoder(xmlDocReader)
xmlDocNodeElementCounter := 0
start := time.Now()
for {
token, _ := xmlDocDecoder.Token()
if token == nil {
break
}
switch element := token.(type) {
case xml.StartElement:
if element.Name.Local == "Node" {
xmlDocNodeElementCounter++
go xmlDocDecoder.DecodeElement(new(entities.Node), &element)
}
}
}
time.Sleep(time.Second * 5)
fmt.Println("Total '<Node />' elements in the XML document: ", xmlDocNodeElementCounter)
fmt.Printf("Total elapsed time: %v\n", time.Since(start))
}
Я используюпростая команда «Сон», чтобы убедиться, что горутины закончены.Я знаю, что это должно быть реализовано с каналами и рабочей очередью.
Согласно выводу на моей консоли декодируются только 3 элемента.Так что же случилось с другими элементами?Может быть, что-то связано с тем, что я использую потоки?
Можно ли как-то сделать так, чтобы это было параллельным, чтобы уменьшить необходимое время для декодирования всех элементов?