[libcxx] [PATCH] unordered_map: Avoid unnecessary mallocs when no insert occurs

Duncan P. N. Exon Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 16 14:42:06 PST 2015


This is a follow-up to r239666: "Fix PR12999 - unordered_set::insert
calls operator new when no insert occurs".  That fix didn't apply to
`unordered_map` because unordered_map::value_type gets packed inside:
--
union __value_type {
  pair<key_type, mapped_type> __nc;       // Only C++11 or higher.
  pair<const key_type, mapped_type> __cc; // Always.
  // Constructors...
};
--
and the underlying __hash_table only knows about __value_type.

I added __hash_table::__insert_unique_dispatch(), which accepts an extra
argument of either true_type or false_type.  Since __hash_table doesn't
know anything about __value_type vs. value_type, unordered_map needs to
check whether the type passed to `insert()` is recognized -- i.e.,
either value_type or __nc_value_type -- and can avoid the allocation.
Doing a type check in __hash_table seems like a layering violation.

Besides this, I augmented __unordered_map_hasher and
__unordered_map_equal to understand both value_type and __nc_value_type,
and broke an ambiguity in callers of __hash_table::__construct_node() by
renaming the versions that take a hash to __construct_node_hash().

The main work is still done by __hash_table::__insert_unique_value()
from r239666.

This is one of my first patches for libc++, and I'm not sure of a few
things:
  - Did I successfully match the coding style?  (I'm kind of lost
    without clang-format TBH.)
  - Should I separate the change to __construct_node_hash() into a
    separate prep commit?  (I would if this were LLVM, but I'm not sure
    if the common practice is different for libc++.)
  - Most of the overloads I added to __unordered_map_hasher and
    __unordered_map_equal aren't actually used by
    __hash_table::__insert_unique_value().  Should I omit the unused
    ones?  (Again, for LLVM I would have omitted them.)

After this I'll fix the same performance issue in std::map (and I
assume std::set?).

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-unordered_map-Avoid-unnecessary-mallocs-when-no-inse.patch
Type: application/octet-stream
Size: 15366 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20151216/85e22f23/attachment-0001.obj>


More information about the cfe-commits mailing list