diff --git a/include/caliper/common/Node.h b/include/caliper/common/Node.h index d5c62c35..07e8e166 100644 --- a/include/caliper/common/Node.h +++ b/include/caliper/common/Node.h @@ -49,6 +49,13 @@ class Node : public util::LockfreeIntrusiveTree Variant data() const { return m_data; } cali_id_t id() const { return m_id; } + + Node* find_child_node(cali_id_t attr, const Variant& v) { + Node* n = first_child(); + while (n && !n->equals(attr, v)) + n = n->next_sibling(); + return n; + } }; } // namespace cali diff --git a/src/caliper/MetadataTree.cpp b/src/caliper/MetadataTree.cpp index e9939ef1..4cdaa2c2 100644 --- a/src/caliper/MetadataTree.cpp +++ b/src/caliper/MetadataTree.cpp @@ -224,9 +224,7 @@ Node* MetadataTree::get_path(const Attribute& attr, size_t n, const Variant* dat for (size_t i = 0; i < n; ++i) { parent = node; - - for (node = parent->first_child(); node && !node->equals(attr.id(), data[i]); node = node->next_sibling()) - ; + node = parent->find_child_node(attr.id(), data[i]); if (!node) break; @@ -258,11 +256,7 @@ Node* MetadataTree::get_or_copy_node(const Node* from, Node* parent) if (!parent) parent = root(); - Node* node = nullptr; - - for (node = parent->first_child(); node && !node->equals(from->attribute(), from->data()); - node = node->next_sibling()) - ; + Node* node = parent->find_child_node(from->attribute(), from->data()); if (!node) { if (!have_free_nodeblock(1)) diff --git a/src/common/Attribute.cpp b/src/common/Attribute.cpp index 0b5a073c..3f9fd1ab 100644 --- a/src/common/Attribute.cpp +++ b/src/common/Attribute.cpp @@ -7,6 +7,8 @@ #include "caliper/common/Node.h" +#include + using namespace cali; Attribute Attribute::make_attribute(Node* node) @@ -45,7 +47,7 @@ int Attribute::properties() const { for (const Node* node = m_node; node; node = node->parent()) if (node->attribute() == PROP_ATTR_ID) - return node->data().to_int(); + return static_cast(node->data().c_variant().value.v_int); return CALI_ATTR_DEFAULT; } diff --git a/src/reader/Aggregator.cpp b/src/reader/Aggregator.cpp index ce12e323..1824eb96 100644 --- a/src/reader/Aggregator.cpp +++ b/src/reader/Aggregator.cpp @@ -26,7 +26,7 @@ using namespace cali; namespace { -std::size_t hash_key(const std::vector& key) +std::size_t compute_key_hash(const std::vector& key) { std::size_t hash = 0; for (const Entry& e : key) { @@ -914,6 +914,7 @@ struct Aggregator::AggregatorImpl { struct AggregateEntry { std::vector key; + std::vector hash_key; std::vector> kernels; std::size_t next_entry_idx; }; @@ -999,14 +1000,9 @@ struct Aggregator::AggregatorImpl { inline bool is_key( const CaliperMetadataAccessInterface& db, const std::vector& key_attrs, - cali_id_t attr_id + Attribute attr ) { - Attribute attr = db.get_attribute(attr_id); - - if (m_select_nested && attr.is_nested()) - return true; - for (const Attribute& key_attr : key_attrs) { if (key_attr == attr) return true; @@ -1018,35 +1014,43 @@ struct Aggregator::AggregatorImpl { } std::shared_ptr get_aggregation_entry( - std::vector::const_iterator nodes_begin, - std::vector::const_iterator nodes_end, - const std::vector& immediates, - CaliperMetadataAccessInterface& db + std::vector::const_iterator nodes_begin, + std::vector::const_iterator nodes_end, + const std::vector& immediates, + CaliperMetadataAccessInterface& db ) { - // --- make key + // --- make hash key from key nodes and immediates - std::vector key; - key.reserve(immediates.size() + 1); + std::vector hash_key; + hash_key.reserve((nodes_end - nodes_begin) + immediates.size()); + hash_key.resize((nodes_end - nodes_begin)); - if (nodes_begin != nodes_end) { - std::vector rv_nodes(nodes_end - nodes_begin); - std::reverse_copy(nodes_begin, nodes_end, rv_nodes.begin()); - key.push_back(Entry(db.make_tree_entry(rv_nodes.size(), rv_nodes.data()))); - } - - std::copy(immediates.begin(), immediates.end(), std::back_inserter(key)); + std::transform(nodes_begin, nodes_end, hash_key.begin(), [](Node* n){ return Entry(n); }); + hash_key.insert(hash_key.end(), immediates.begin(), immediates.end()); // --- lookup key - std::size_t hash = hash_key(key) % m_hashmap.size(); + std::size_t hash = compute_key_hash(hash_key) % m_hashmap.size(); for (size_t i = m_hashmap[hash]; i; i = m_entries[i]->next_entry_idx) { auto e = m_entries[i]; - if (key == e->key) + if (hash_key == e->hash_key) return e; } - // --- key not found: create entry + // --- hash key not found: create a new entry + + // -- merge key nodes into new tree entry to create compact key + + std::vector key; + key.reserve(immediates.size() + 1); + key.insert(key.end(), immediates.begin(), immediates.end()); + + if (nodes_begin != nodes_end) { + std::vector rv_nodes(nodes_end - nodes_begin); + std::reverse_copy(nodes_begin, nodes_end, rv_nodes.begin()); + key.push_back(Entry(db.make_tree_entry(rv_nodes.size(), rv_nodes.data()))); + } std::vector> kernels; kernels.reserve(m_kernel_configs.size()); @@ -1057,6 +1061,7 @@ struct Aggregator::AggregatorImpl { auto e = std::make_shared(); e->key = std::move(key); + e->hash_key = std::move(hash_key); e->kernels = std::move(kernels); e->next_entry_idx = m_hashmap[hash]; @@ -1073,39 +1078,43 @@ struct Aggregator::AggregatorImpl { // --- Unravel nodes, filter for key attributes - std::vector nodes; - std::vector immediates; + std::vector nodes; + std::vector non_path_nodes; + std::vector immediates; nodes.reserve(80); + non_path_nodes.reserve(20); immediates.reserve(key_attrs.size()); - bool select_all = m_select_all; - for (const Entry& e : rec) { if (e.is_reference()) { - for (const Node* node = e.node(); node && node->attribute() != CALI_INV_ID; node = node->parent()) - if (select_all || is_key(db, key_attrs, node->attribute())) - nodes.push_back(node); - } else if (e.is_immediate() && is_key(db, key_attrs, e.attribute())) { + for (Node* node = e.node(); node && node->attribute() != CALI_INV_ID; node = node->parent()) { + Attribute attr = db.get_attribute(node->attribute()); + bool is_nested = attr.is_nested(); + if (m_select_all || (m_select_nested && is_nested) || is_key(db, key_attrs, attr)) { + if (is_nested) + nodes.push_back(node); + else + non_path_nodes.push_back(node); + } + } + } else if (e.is_immediate() && is_key(db, key_attrs, db.get_attribute(e.attribute()))) { // Only include explicitly selected immediate entries in the key. immediates.push_back(e); } } - // --- Group by attribute, reverse nodes (restores original order) and get/create tree node. - // Keeps nested attributes separate. + // --- Canonicalize key by sorting by attribute ids - auto nonnested_begin = std::stable_partition(nodes.begin(), nodes.end(), [&db](const Node* node) { - return db.get_attribute(node->attribute()).is_nested(); - }); - - std::stable_sort(nonnested_begin, nodes.end(), [](const Node* a, const Node* b) { + std::stable_sort(non_path_nodes.begin(), non_path_nodes.end(), [](const Node* a, const Node* b) { return a->attribute() < b->attribute(); }); std::sort(immediates.begin(), immediates.end(), [](const Entry& a, const Entry& b) { return a.attribute() < b.attribute(); }); + auto nonnested_begin = nodes.insert(nodes.end(), non_path_nodes.begin(), non_path_nodes.end()); + std::lock_guard g(m_entries_lock); auto entry = get_aggregation_entry(nodes.begin(), nodes.end(), immediates, db); diff --git a/src/reader/CaliperMetadataDB.cpp b/src/reader/CaliperMetadataDB.cpp index 1cd3eb97..f64e46e2 100644 --- a/src/reader/CaliperMetadataDB.cpp +++ b/src/reader/CaliperMetadataDB.cpp @@ -206,8 +206,7 @@ struct CaliperMetadataDB::CaliperMetadataDBImpl { { std::lock_guard g(m_node_lock); - for (node = parent->first_child(); node && !node->equals(attr_id, v_data); node = node->next_sibling()) - ; + node = parent->find_child_node(attr_id, v_data); if (!node) { node = create_node(attr_id, v_data, parent); @@ -336,6 +335,8 @@ struct CaliperMetadataDB::CaliperMetadataDBImpl { if (!parent) parent = &m_root; + std::lock_guard g(m_node_lock); + for (size_t i = 0; i < n; ++i) { if (attr[i].store_as_value()) continue; @@ -345,10 +346,7 @@ struct CaliperMetadataDB::CaliperMetadataDBImpl { if (v_data.type() == CALI_TYPE_STRING) v_data = make_string_variant(static_cast(data[i].data()), data[i].size()); - std::lock_guard g(m_node_lock); - - for (node = parent->first_child(); node && !node->equals(attr[i].id(), v_data); node = node->next_sibling()) - ; + node = parent->find_child_node(attr[i].id(), v_data); if (!node) node = create_node(attr[i].id(), v_data, parent); @@ -366,12 +364,10 @@ struct CaliperMetadataDB::CaliperMetadataDBImpl { if (!parent) parent = &m_root; - for (size_t i = 0; i < n; ++i) { - std::lock_guard g(m_node_lock); + std::lock_guard g(m_node_lock); - for (node = parent->first_child(); node && !node->equals(nodelist[i]->attribute(), nodelist[i]->data()); - node = node->next_sibling()) - ; + for (size_t i = 0; i < n; ++i) { + node = parent->find_child_node(nodelist[i]->attribute(), nodelist[i]->data()); if (!node) node = create_node(nodelist[i]->attribute(), nodelist[i]->data(), parent); @@ -495,6 +491,7 @@ struct CaliperMetadataDB::CaliperMetadataDBImpl { CaliperMetadataDBImpl() : m_root { CALI_INV_ID, CALI_INV_ID, {} } { + m_nodes.reserve(1000); setup_bootstrap_nodes(); m_alias_attr =