How to improve property_tree performance
Hi, I have a fairly easy record structure which I am writing to xml using property_tree. I am trying to figure out how to do it better, since the current time spend building the tree is too high. I do the following : wiptree pt; wiptree &tvars = pt.add(L"some.recordname",L""); for( int i = 0; i < somenumber /*say 60K*/; ++i ) { wiptree &curtree = tvars.add(L"someitem",L""); curtree.add(L"<xmlattr>.name",L"some_attribute"); ... } To me this seems reasonable. Is there a faster way to do this ? Since I just want to write it out and it's quite simple, I could avoid using property_tree and write the xml file manually. But since I read it in later with property_tree, then for maintainability I would like to read and write with the same method. Thanks Bo
On 13.10.2010 09:35, Bo Jensen wrote:
Hi, I have a fairly easy record structure which I am writing to xml using property_tree. I am trying to figure out how to do it better, since the current time spend building the tree is too high.
I do the following :
wiptree pt; wiptree&tvars = pt.add(L"some.recordname",L"");
for( int i = 0; i< somenumber /*say 60K*/; ++i ) { wiptree&curtree = tvars.add(L"someitem",L"");
curtree.add(L"<xmlattr>.name",L"some_attribute");
... }
To me this seems reasonable. Is there a faster way to do this ? Since I just want to write it out and it's quite simple, I could avoid using property_tree and write the xml file manually. But since I read it in later with property_tree, then for maintainability I would like to read and write with the same method.
I've never done a performance analysis of PTree (I hardly have time to get the docs up to date with the actual library), so I don't know what is fast and what is slow. PTree is definitely not a fast library. I have some ideas about how to make it faster, but that would take essentially a reimplementation of the ptree class. You might want to try to use only push_back() instead of add(), though. That incurs fewer lookups and might thus improve performance. Sebastian
On Wed, Oct 13, 2010 at 8:09 AM, Sebastian Redl
On 13.10.2010 09:35, Bo Jensen wrote:
Hi, I have a fairly easy record structure which I am writing to xml using property_tree. I am trying to figure out how to do it better, since the current time spend building the tree is too high.
I do the following :
wiptree pt; wiptree&tvars = pt.add(L"some.recordname",L"");
for( int i = 0; i< somenumber /*say 60K*/; ++i ) { wiptree&curtree = tvars.add(L"someitem",L"");
curtree.add(L"<xmlattr>.name",L"some_attribute");
... }
To me this seems reasonable. Is there a faster way to do this ? Since I just want to write it out and it's quite simple, I could avoid using property_tree and write the xml file manually. But since I read it in later with property_tree, then for maintainability I would like to read and write with the same method.
I've never done a performance analysis of PTree (I hardly have time to get the docs up to date with the actual library), so I don't know what is fast and what is slow. PTree is definitely not a fast library. I have some ideas about how to make it faster, but that would take essentially a reimplementation of the ptree class.
I completely understand, I just wanted to eliminate me doing something stupid.
You might want to try to use only push_back() instead of add(), though. That incurs fewer lookups and might thus improve performance.
I tried that, it was only slightly faster. I also tried to do a bunch of independent trees and then merge them later, but still same speed. Is it correct, that you can not choose the underlying storage method or preallocate some space ? In my case I know exactly the sizes of each tree and number of items. Thanks for your time.
Sebastian _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
On 13.10.2010 10:15, Bo Jensen wrote:
I tried that, it was only slightly faster. I also tried to do a bunch of independent trees and then merge them later, but still same speed. Is it correct, that you can not choose the underlying storage method or preallocate some space ? In my case I know exactly the sizes of each tree and number of items.
No, because of the way PTree is structured at the high level (nesting trees where each branch can be treated as an independent tree), providing generic allocator support is impractical. Internally, a tree node consists of its local value and a node-based container of children, so preallocation through an interface would only be able to provide storage for that particular node, and would also require a special allocator. However, if you want to try the performance effect of using a stateless Boost Pool allocator, I believe all you have to do is add it to the base_container typedef in boost/property_tree/detail/ptree_implementation.hpp, near the top. See that big multi_index_container? That's the storage for child nodes. If you give it an alternative (stateless!) allocator, it will be used. Sebastian
On Wed, Oct 13, 2010 at 8:33 AM, Sebastian Redl
On 13.10.2010 10:15, Bo Jensen wrote:
I tried that, it was only slightly faster. I also tried to do a bunch of independent trees and then merge them later, but still same speed. Is it correct, that you can not choose the underlying storage method or preallocate some space ? In my case I know exactly the sizes of each tree and number of items.
No, because of the way PTree is structured at the high level (nesting trees where each branch can be treated as an independent tree), providing generic allocator support is impractical. Internally, a tree node consists of its local value and a node-based container of children, so preallocation through an interface would only be able to provide storage for that particular node, and would also require a special allocator. However, if you want to try the performance effect of using a stateless Boost Pool allocator, I believe all you have to do is add it to the base_container typedef in boost/property_tree/detail/ptree_implementation.hpp, near the top. See that big multi_index_container? That's the storage for child nodes. If you give it an alternative (stateless!) allocator, it will be used.
Sebastian _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Thanks for the input, I will try it out. Otherwise I might use the serialization with xml, since my usage is so simple.
On Wed, Oct 13, 2010 at 2:47 AM, Bo Jensen
On Wed, Oct 13, 2010 at 8:33 AM, Sebastian Redl
wrote: On 13.10.2010 10:15, Bo Jensen wrote:
I tried that, it was only slightly faster. I also tried to do a bunch of independent trees and then merge them later, but still same speed. Is it correct, that you can not choose the underlying storage method or preallocate some space ? In my case I know exactly the sizes of each tree and number of items.
No, because of the way PTree is structured at the high level (nesting trees where each branch can be treated as an independent tree), providing generic allocator support is impractical. Internally, a tree node consists of its local value and a node-based container of children, so preallocation through an interface would only be able to provide storage for that particular node, and would also require a special allocator. However, if you want to try the performance effect of using a stateless Boost Pool allocator, I believe all you have to do is add it to the base_container typedef in boost/property_tree/detail/ptree_implementation.hpp, near the top. See that big multi_index_container? That's the storage for child nodes. If you give it an alternative (stateless!) allocator, it will be used.
Sebastian _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Thanks for the input, I will try it out. Otherwise I might use the serialization with xml, since my usage is so simple.
You could just try using Spirit/Karma for that, there is about nothing faster then those for input/output streaming. You will have to define your own format (xml is *easy* to emulate it in, see its examples, already done), but it would certainly be faster then any other method if you have a real need for speed.
On Wed, Oct 13, 2010 at 6:54 PM, OvermindDL1
On Wed, Oct 13, 2010 at 2:47 AM, Bo Jensen
wrote: On Wed, Oct 13, 2010 at 8:33 AM, Sebastian Redl
wrote: On 13.10.2010 10:15, Bo Jensen wrote:
I tried that, it was only slightly faster. I also tried to do a bunch of independent trees and then merge them later, but still same speed. Is it correct, that you can not choose the underlying storage method or preallocate some space ? In my case I know exactly the sizes of each tree and number of items.
No, because of the way PTree is structured at the high level (nesting trees where each branch can be treated as an independent tree), providing generic allocator support is impractical. Internally, a tree node consists of its local value and a node-based container of children, so preallocation through an interface would only be able to provide storage for that particular node, and would also require a special allocator. However, if you want to try the performance effect of using a stateless Boost Pool allocator, I believe all you have to do is add it to the base_container typedef in boost/property_tree/detail/ptree_implementation.hpp, near the top. See that big multi_index_container? That's the storage for child nodes. If you give it an alternative (stateless!) allocator, it will be used.
Sebastian _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Thanks for the input, I will try it out. Otherwise I might use the serialization with xml, since my usage is so simple.
You could just try using Spirit/Karma for that, there is about nothing faster then those for input/output streaming. You will have to define your own format (xml is *easy* to emulate it in, see its examples, already done), but it would certainly be faster then any other method if you have a real need for speed. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Thanks for the replies, I ended up using pugixml instead for the speed crucial part.
On Fri, Oct 15, 2010 at 2:31 AM, Bo Jensen
On Wed, Oct 13, 2010 at 6:54 PM, OvermindDL1
wrote: On Wed, Oct 13, 2010 at 2:47 AM, Bo Jensen
wrote: On Wed, Oct 13, 2010 at 8:33 AM, Sebastian Redl
wrote: On 13.10.2010 10:15, Bo Jensen wrote:
I tried that, it was only slightly faster. I also tried to do a bunch of independent trees and then merge them later, but still same speed. Is it correct, that you can not choose the underlying storage method or preallocate some space ? In my case I know exactly the sizes of each tree and number of items.
No, because of the way PTree is structured at the high level (nesting trees where each branch can be treated as an independent tree), providing generic allocator support is impractical. Internally, a tree node consists of its local value and a node-based container of children, so preallocation through an interface would only be able to provide storage for that particular node, and would also require a special allocator. However, if you want to try the performance effect of using a stateless Boost Pool allocator, I believe all you have to do is add it to the base_container typedef in boost/property_tree/detail/ptree_implementation.hpp, near the top. See that big multi_index_container? That's the storage for child nodes. If you give it an alternative (stateless!) allocator, it will be used.
Sebastian _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Thanks for the input, I will try it out. Otherwise I might use the serialization with xml, since my usage is so simple.
You could just try using Spirit/Karma for that, there is about nothing faster then those for input/output streaming. You will have to define your own format (xml is *easy* to emulate it in, see its examples, already done), but it would certainly be faster then any other method if you have a real need for speed. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Thanks for the replies, I ended up using pugixml instead for the speed crucial part.
As stated Spirit/Karma will still outperform that if you do not mind writing it out yourself. :)
I've never done a performance analysis of PTree (I hardly have time to get the docs up to date with the actual library), so I don't know what is fast and what is slow. PTree is definitely not a fast library. I have some ideas about how to make it faster, but that would take essentially a reimplementation of the ptree class.
ptree uses std::list internally, right? I think it would be worth to use e.g. boost::ptr_deque or boost::ptr_vector (or a similar scheme) to reduce the number of heap allocations somewhat. -Thorsten
On 18.10.2010, at 14:38, Thorsten Ottosen wrote:
I've never done a performance analysis of PTree (I hardly have time to get the docs up to date with the actual library), so I don't know what is fast and what is slow. PTree is definitely not a fast library. I have some ideas about how to make it faster, but that would take essentially a reimplementation of the ptree class.
ptree uses std::list internally, right? I think it would be worth to use e.g. boost::ptr_deque or boost::ptr_vector (or a similar scheme) to reduce the number of heap allocations somewhat.
No. It used to do that, but when I took the library over, I realized that the documentation made complexity guarantees for find() that it couldn't keep (and also that it created a std::list of an undefined type, which is technically undefined), so I reimplemented it using a multi-index container and some seriously ugly data hiding to delay the container definition to where the ptree type is complete. I've played with the idea of creating the index-by-name lazily, and indeed use a ptr_vector to hold the sequence of elements. I think it would improve performance, but as I said, that would be essentially another reimplementation. Also, last time I looked, intrusive containers (for the index) didn't like incomplete member types, which is a real pity. Also, the library currently makes iterator validity guarantees that would be rather tricky, if not impossible, to keep for containers other than list and multi_index. I still might do it, if I ever find the time. But don't count on it. Sebastian
participants (4)
-
Bo Jensen
-
OvermindDL1
-
Sebastian Redl
-
Thorsten Ottosen