0

I'm writing an own class to parse some xml documents. Therefore I use libxml. I created a XMLDocument class and a XMLNode class. I wrote some functions like "elementsForName" and so on. In the end the whole project running on the iPad 3 was extremely slow, when I parse huge xml documents. I tried to find out with the 'Time Profiler' of 'Instruments', where the problem is.

The problem is the way, how Swift works with Arrays. I have a function called func elementsForName(name: String) -> [MyXMLNode]? {. In this method I loop through all children nodes of the given node. I compare the node type and the node name. If it's the same as the 'name'-String, I create a new instance of my MyXMLNode-class and append it to an array. The problem is, that appending to an array will resize the array, so Swift will copy the whole array. This needs a lot of time in the end. (I found this useful thread: Swift vs Java - speed at filling big array)

Here my method:

func elementsForName(name: String) -> [MyXMLNode]? {
    var children = [MyXMLNode]()
    var currentNode = nodePointer!.memory.children
    while currentNode != nil {
        let tag = String.fromCString(CString(UnsafePointer<xmlChar>(currentNode.memory.name)))
        if currentNode.memory.type.value == 1 && tag == name {
            children.append(MyXMLNode(xmlNodePointer: currentNode))
        }

        currentNode = currentNode.memory.next
    }

    if children.count == 0 {
        return nil
    }

    return children
}

I thought about creating an array with a given capacity, but before ending the loop, I cannot know, how much elements of the given name will be found.

Any ideas?

Community
  • 1
  • 1
Lupurus
  • 3,618
  • 2
  • 29
  • 59
  • 1
    Why not use linked list data structure? Simple, powerful and exactly what you need. – AndrewShmig Jul 20 '14 at 18:18
  • linked lists are not exactly known for their speed when it comes to inserting elements... – Atomix Jul 20 '14 at 18:22
  • @JoJoe, inserting new element at the end of linked list is O(1). Whats the problem? – AndrewShmig Jul 20 '14 at 18:24
  • Silly me, I was thinking about generally acessing elements, which is O(n). You're right. – Atomix Jul 20 '14 at 18:26
  • Do you have an example for a linked list? (Especially one where I can access with [i]) – Lupurus Jul 20 '14 at 20:24
  • Ok thanks for the idea. I found something, but I had to add a subscript method to access the childs. The problem is, that looping through needs as well very long. The idea was great, but in the end I went now back to use Objective-C for the complete xml parsing. I think working with a c api is faster with Obj-C (for camparison: 17 seconds with swift, 2-3 seconds with obj-c) :( – Lupurus Jul 21 '14 at 06:10

1 Answers1

0

You can prevent using Array.append() by using other existing Swift Array methods like Array.filter() and Array.map(). Something like:

nodes.filter { 
    let tag = ...
    return $0.memory.type.value == 1 && tag == name
  }.map { (cn:Node) in MyXMLNode(xmlNodePointer:  cn) }}
GoZoner
  • 67,920
  • 20
  • 95
  • 145
  • Thanks for your answer. I just did not really understand, what filter() and map() do (I will read about that). But what is 'Node' in your example? – Lupurus Jul 22 '14 at 06:27
  • `Node` is the type of `currentNode`, perhaps it is `MyXMLNode`? Functions like `filter()` and `map()` are important given _closures_ in Swift. – GoZoner Jul 23 '14 at 01:25