Skip to content

Commit 7cb1079

Browse files
authored
Various performance optimizations (LLNL#457)
* Implement hash for variable length variant types * Refactor MetadataTree class * Optimize variant copy * Specialize variant constructor for string * Simplify Caliper::create_attribute() * More optimizations * More improvements and cleanup in Caliper.cpp
1 parent 1445da0 commit 7cb1079

File tree

9 files changed

+550
-742
lines changed

9 files changed

+550
-742
lines changed

include/caliper/common/Node.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class Node : public util::LockfreeIntrusiveTree<Node>
4949
/// \brief Check if the node's attribute and value are equal to
5050
/// \a attr and \a v
5151
bool equals(cali_id_t attr, const Variant& v) const {
52-
return m_attribute == attr ? m_data == v : false;
52+
return m_data == v && m_attribute == attr;
5353
}
5454

5555
/// \brief Return the node's attribute ID

include/caliper/common/Variant.h

+17-2
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ class Variant
4949

5050
template<typename U, typename std::enable_if< std::is_unsigned<U>::value, int >::type = 0>
5151
Variant(U val)
52-
: m_v(cali_make_variant_from_uint(val)) { }
52+
: m_v(cali_make_variant_from_uint(val)) { }
5353

5454
Variant(const char* val)
55-
: m_v(cali_make_variant_from_string(val)) { }
55+
: m_v(cali_make_variant_from_string(val)) { }
5656
Variant(cali_attr_type val)
5757
: m_v(cali_make_variant_from_type(val)) { }
5858

@@ -68,6 +68,11 @@ class Variant
6868
return !empty();
6969
}
7070

71+
bool has_unmanaged_data() const {
72+
cali_attr_type t = type();
73+
return (t == CALI_TYPE_STRING || t == CALI_TYPE_USR);
74+
}
75+
7176
cali_variant_t c_variant() const { return m_v; }
7277

7378
cali_attr_type type() const { return cali_variant_get_type(m_v); }
@@ -98,6 +103,16 @@ class Variant
98103

99104
std::string to_string() const;
100105

106+
Variant copy(void* ptr) const {
107+
Variant to(*this);
108+
109+
if (has_unmanaged_data())
110+
to.m_v.value.unmanaged_ptr =
111+
memcpy(ptr, m_v.value.unmanaged_const_ptr, size());
112+
113+
return to;
114+
}
115+
101116
Variant& operator += (const Variant& val);
102117

103118
size_t pack(unsigned char* buf) const {

include/caliper/common/cali_variant.h

+33-4
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ extern "C" {
2323
* Variable-length types (strings and blobs) are stored as unmanaged pointers.
2424
*/
2525
typedef struct {
26-
/** Least significant bytes encode the type.
27-
* Remaining bytes encode the size of variable-length types (strings and blobs (usr)).
26+
/** Least significant byte encode the type.
27+
* Top 4 bytes encode the size of variable-length types (strings and blobs).
28+
* Remainder encodes a small hash for variable-length types for faster comparisons.
2829
*/
2930
uint64_t type_and_size;
3031

@@ -42,6 +43,7 @@ typedef struct {
4243
} cali_variant_t;
4344

4445
#define CALI_VARIANT_TYPE_MASK 0xFF
46+
#define CALI_VARIANT_HASH_MASK 0xFFFFFF00
4547

4648
inline cali_variant_t
4749
cali_make_empty_variant()
@@ -130,7 +132,23 @@ cali_make_variant_from_double(double value)
130132
inline cali_variant_t
131133
cali_make_variant_from_string(const char* value)
132134
{
133-
return cali_make_variant(CALI_TYPE_STRING, value, strlen(value));
135+
size_t size = strlen(value);
136+
uint64_t hash = 0;
137+
138+
const unsigned char* p = (const unsigned char*) value;
139+
hash |= p[0];
140+
hash <<= 8;
141+
hash |= p[size/2];
142+
hash <<= 8;
143+
hash |= p[size-1];
144+
hash <<= 8;
145+
146+
cali_variant_t v;
147+
148+
v.type_and_size = (size << 32) | hash | (CALI_TYPE_STRING & CALI_VARIANT_TYPE_MASK);
149+
v.value.unmanaged_const_ptr = value;
150+
151+
return v;
134152
}
135153

136154
inline cali_variant_t
@@ -186,8 +204,19 @@ cali_variant_to_bool(cali_variant_t v, bool* okptr);
186204
int
187205
cali_variant_compare(cali_variant_t lhs, cali_variant_t rhs);
188206

207+
/** \brief Check if lhs and rhs' values are equal using a deep comparison.
208+
* Caller must make sure that lhs' and rhs' type and size are equal.
209+
*/
189210
bool
190-
cali_variant_eq(cali_variant_t lhs, cali_variant_t rhs);
211+
_cali_variant_value_eq(cali_variant_t lhs, cali_variant_t rhs);
212+
213+
/** \brief Check if lhs is equal to rhs
214+
*/
215+
inline bool
216+
cali_variant_eq(cali_variant_t lhs, cali_variant_t rhs)
217+
{
218+
return lhs.type_and_size == rhs.type_and_size ? _cali_variant_value_eq(lhs, rhs) : false;
219+
}
191220

192221
/** \brief Pack variant into byte buffer
193222
*/

src/caliper/Annotation.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ Annotation& Annotation::begin(double data)
284284

285285
Annotation& Annotation::begin(const char* data)
286286
{
287-
return begin(Variant(CALI_TYPE_STRING, data, strlen(data)));
287+
return begin(Variant(data));
288288
}
289289

290290
Annotation& Annotation::begin(cali_attr_type type, void* data, uint64_t size)

0 commit comments

Comments
 (0)