Age | Commit message (Collapse) | Author |
|
Fixes #43.
|
|
All other sanitizers are still unavailable so only enable them on non-OSX
systems.
|
|
Apparently Clang 3.7 implements C++ DR 1748 that makes placement new with null
pointer undefined behavior. Which renders all C++ programs that rely on this
invalid. Which includes pugixml.
This is not very likely to happen in the wild because the allocations that are
subject to this in pugixml are relatively small, but tests break because of
this.
Fix the issue by adding null pointer checks (that are completely redundant in
all current compilers except Clang 3.7 but it's not like there is another
option).
|
|
|
|
Work around a name lookup bug by pulling auto_deleter name in the local
scope. We could also move auto_deleter to pugi:: namespace, but that
pollutes it unnecessarily for other compilers.
|
|
|
|
This makes get_value_* simpler and also works around DMC compilation issue.
|
|
This makes code more consistent between wchar/utf8 mode.
|
|
|
|
Extra argument 'hint' is used to start the attribute lookup; if the attribute
is not found the lookup is restarted from the beginning of the attriubte list.
This allows to optimize attribute lookups if you need to get many attributes
from the node and can make assumptions about the likely ordering. The code is
correct regardless of the order, but it is faster than using vanilla lookups
if the order matches the calling order.
Fixes #30.
|
|
|
|
|
|
|
|
Address sanitizer can detect underflows so we don't really need the custom
allocator.
Additionally, custom allocator can return memory that is not pointer-aligned;
this causes undefined behavior sanitizer to complain.
|
|
Work around -Wself-move using ref-deref.
|
|
|
|
|
|
|
|
auto_deleter is now used in all modes so we can't exclude it from compilation.
|
|
Apply the usual workaround for for scoping issues. Also fix integer conversion
warning for BorlandC.
|
|
Implement compact mode.
This introduces a new storage mode that dramatically reduces node size at some performance cost.
The mode is enabled by defining PUGIXML_COMPACT. This does not change API/ABI - all existing functionality still works.
The pointers are stored using delta encoding and bytes, with some additional tricks to make encoding more optimal for e.g. parent pointer and string pointers. Since the node is fixed size, we have to fall back to a hash table if the pointer does not fit. Thus all DOM operations still have amortized complexity - constant number of operations if you don't need the hash table and amortized constant if you do.
Aside from some performance loss (which is inevitable since decoding takes time), the only other caveat is that we can't remove entries from the hash table - so in some edge cases with a lot of node removals the peak memory consumption can grow indefinitely. In theory we can implement this later; it's unclear that this is useful at this point.
The resulting node/attribute sizes are as follows:
non-compact node: 28b 32-bit, 56b 64-bit
compact node: 12b 32/64-bit
non-compact attribute: 20b 32-bit, 40b 64-bit
compact attribute: 8b 32/64-bit
|
|
|
|
|
|
|
|
Now compact_string matches compact_pointer_parent.
Turns out PUGI__UNLIKELY is good at reordering conditions but usually does not
really affect performance. Since MSVC should treat "if" branches as taken and
does not support branch probabilities, don't use them if we don't need to.
|
|
|
|
Instead of checking if the object being removed allocated a marker, mark the
marker block as deleted immediately upon allocation. This simplifies the logic
and prevents extra markers from being inserted if we allocate/deallocate the
same node indefinitely.
Also change marker pointer type to uint32_t*.
|
|
First assignment uses a fast path; second assignment uses a specialized
path as well.
|
|
|
|
When we deallocate nodes/attributes that allocated the marker we have to
adjust the size accordingly, and dismiss the marker in case it gets
overwritten with something else...
|
|
Header is now just 2 bytes, with optional additonal 4 bytes that are only
allocated for every 85 nodes / 128 attributes.
|
|
|
|
|
|
This temporarily increases the node size to 16 bytes - we'll bring it back.
It allows us to remove the horrible node_pi hack and to reduce the amount of
changes against master. This comes at the price of not decreasing basline
xml_node_struct size.
The compact xml_node_struct is also increased by this change but a followup
change will reduce *both* xml_attribute_struct and xml_node_struct (to 8/12
bytes).
|
|
The memory_large_allocations test sometimes classified hash allocations
as page allocations since hash table could reach 512 entries.
|
|
Split a long line into multiple statements.
|
|
Also remove useless comments.
|
|
|
|
|
|
We used this in two cases - to get the page pointer and to test flags.
We now use PUGI__GETPAGE for getting the page pointer and operator& to test
flags - this makes getting node type significantly faster since it does not
require page pointer reconstruction.
|
|
|
|
|
|
Clarify the offset applied when encoding the pointer difference.
Make decoding diff slightly more clear - no effect on performance.
Adjust branch weighting in compact_string encoding - 0.5% faster.
Use uint16_t in compact_pointer_parent - 2% faster.
|
|
Make sure compact_hash_table::rehash() is not inlined - that way reserve() is
inlined so the fast path has no extra function calls.
Also use subtraction instead of multiplication when checking capacity.
|
|
|
|
|
|
|
|
|
|
|
|
Also test ranged for and copying big xpath_variable_set objects (to make
sure we actually handle hash collisions properly)
|