Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make use of an (std::multi)map for object members, if #defined.
When RAPIDJSON_USE_MEMBERS_MAP is defined, an object Value will store its members in an (re)allocated array of Members like before, but also in an std::multimap<StringRef,SizeType> where the key and value reference the corresponding Member by its name and index in the array, respectively, and in a relocatable manner. The layout of the members map/array is now: {multimap}<>{capacity}<>{Member[capacity]}<>{multimap::iterator[capacity]} where <> stands for the RAPIDJSON_ALIGN-ment of each part, if needed. This layout needs to be reallocated when the current capacity is exhausted, which requires to take care of the multimap and its iterators explicitely; the former (likely not a POD) can simply be saved/restored by swapping (twice), and the old/alive iterators must be moved to their new offset (according to the new capacity). With this in place, it's immediate to get the multimap::iterator from a MemberIterator and vice versa, thus Find/Remove/EraseMember() working on a MemberIterator keep the same complexity (O(1) for find/remove, and still O(n-m) for EraseMember() due to the move/copy). For operations by name, the lookups complexity switches from O(n)/linear to the multimap's, usually rbtree's O(log n)/logarithmic, including for AddMember() which without RAPIDJSON_USE_MEMBERS_MAP is otherwise O(1). Consequently parsing will be slower, up to ~20% measured in perftests on my laptop (since it's mainly composed of insertions). But later work on the Document [usually the goal of parsing...] will be much faster; the new DocumentFind perftest included in this commit is 8 times faster with RAPIDJSON_USE_MEMBERS_MAP (still on my laptop). Overall the tests are 4% slower (mainly composed of parsing), and notably 15% slower for schemas parsing/validation (which supposedly comes from the larger JSON files parsing, still). As a side note, when RAPIDJSON_USE_MEMBERS_MAP is not defined, this commit does not change the perfs (same results for perftest with regard to previous version). Finally, the multimaps are allocated/constructed on/with the Value's Allocator (thanks to StdAllocator), so they are integrated into the memory model like the native classes, and thus will benefit from the same performance/safety/security/whatever provided by the user given Allocator.
- Loading branch information