Skip to content

Commit

Permalink
Merge pull request #14 from rafaelkallis/preview
Browse files Browse the repository at this point in the history
5.0
  • Loading branch information
rafaelkallis authored Jun 9, 2022
2 parents ee08802 + 80b66ae commit 1023b84
Show file tree
Hide file tree
Showing 24 changed files with 375 additions and 203 deletions.
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@ compression reduces the tree height and horizontal compression decreases a node
using namespace art;

int main() {
art<int> m;
art<std::shared_ptr<MyResource>> m;

int v = 2;
// set k to v
m.set("k", &v);
// set k
m.set("k", std::make_shared(new MyResource()));

// get value of k
int * v_ptr = m.get("k");
// get k
std::shared_ptr<MyResource> ptr = m.get("k");

// delete k
m.del("k");
Expand Down Expand Up @@ -100,6 +99,9 @@ query sparse zipf:
===============================================================================
```

You can replicate using `make release && make bench`


## References

* [The Adaptive Radix Tree: ARTful Indexing for Main-Memory Databases](http://www-db.in.tum.de/~leis/papers/ART.pdf)
Expand Down
2 changes: 1 addition & 1 deletion bench/delete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ using picobench::state;
PICOBENCH_SUITE("delete");

static void art_delete_sparse(state &s) {
art::art<int> m;
art::art<int*> m;
int v = 1;
std::mt19937_64 g1(0);
for (auto i __attribute__((unused)) : s) {
Expand Down
2 changes: 1 addition & 1 deletion bench/insert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ using picobench::state;
PICOBENCH_SUITE("insert");

static void art_insert_sparse(state &s) {
art::art<int> m;
art::art<int*> m;
int v = 1;
std::mt19937_64 rng(0);
for (auto i __attribute__((unused)) : s) {
Expand Down
2 changes: 1 addition & 1 deletion bench/mixed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ using std::unordered_map;
PICOBENCH_SUITE("mixed");

static void art_mixed_sparse(state &s) {
art::art<int> m;
art::art<int*> m;
fast_zipf rng(10000000);
hash<uint32_t> h;
string k;
Expand Down
2 changes: 1 addition & 1 deletion bench/mixed_dense.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ static void art_mixed(state &s) {
int v = 1;
fast_zipf rng(n);

art::art<int> m;
art::art<int*> m;
string k;
for (auto i __attribute__((unused)) : s) {
k = dataset[rng()];
Expand Down
8 changes: 4 additions & 4 deletions bench/query_iteration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ using std::unordered_map;
PICOBENCH_SUITE("query iteration");

static void full_scan_zipf(state &s) {
art::art<int> m;
art::art<int*> m;
hash<uint32_t> h;
int v = 1;
int *v_ptr = &v;
art::tree_it<int> it, it_end;
art::tree_it<int*> it, it_end;
fast_zipf rng(1000000);
for (int i = 0; i < 100000; ++i) {
m.set(to_string(h(rng())).c_str(), v_ptr);
Expand All @@ -38,11 +38,11 @@ static void full_scan_zipf(state &s) {
PICOBENCH(full_scan_zipf).iterations({1000});

static void full_scan_uniform(state &s) {
art::art<int> m;
art::art<int*> m;
hash<uint32_t> h;
int v = 1;
int *v_ptr = &v;
art::tree_it<int> it, it_end;
art::tree_it<int*> it, it_end;
mt19937_64 rng(0);
for (int i = 0; i < 100000; ++i) {
m.set(to_string(h(rng())).c_str(), v_ptr);
Expand Down
2 changes: 1 addition & 1 deletion bench/query_sparse_uniform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ using std::unordered_map;
PICOBENCH_SUITE("query sparse uniform");

static void art_q_s_u(state &s) {
art::art<int> m;
art::art<int*> m;
hash<uint32_t> h;
int v = 1;
int *v_ptr = &v;
Expand Down
2 changes: 1 addition & 1 deletion bench/query_sparse_uniform_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ PICOBENCH_SUITE("query sparse uniform base 64 keys");
std::string to_base64(const std::string& string_);

static void art_q_s_u(state &s) {
art::art<int> m;
art::art<int*> m;
hash<uint32_t> h;
int v = 1;
int *v_ptr = &v;
Expand Down
2 changes: 1 addition & 1 deletion bench/query_sparse_zipf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ using std::unordered_map;
PICOBENCH_SUITE("query sparse zipf");

static void art_q_s_z(state &s) {
art::art<int> m;
art::art<int*> m;
hash<uint32_t> h;
int v = 1;
int *v_ptr = &v;
Expand Down
43 changes: 24 additions & 19 deletions include/art/art.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ template <class T> class art {
* Finds the value associated with the given key.
*
* @param key - The key to find.
* @return the value associated with the key or a nullptr.
* @return the value associated with the key or a default constructed value.
*/
T *get(const char *key) const;
T get(const char *key) const;

/**
* Associates the given key with the given value.
Expand All @@ -39,7 +39,7 @@ template <class T> class art {
* @return a nullptr if no other value is associated with they or the
* previously associated value.
*/
T *set(const char *key, T *value);
T set(const char *key, T value);

/**
* Deletes the given key and returns it's associated value.
Expand All @@ -50,7 +50,7 @@ template <class T> class art {
* @param key - The key to delete.
* @return the values assciated with they key or a nullptr otherwise.
*/
T *del(const char *key);
T del(const char *key);

/**
* Forward iterator that traverses the tree in lexicographic order.
Expand Down Expand Up @@ -97,33 +97,35 @@ template <class T> art<T>::~art() {
}
}

template <class T> T *art<T>::get(const char *key) const {
template <class T>
T art<T>::get(const char *key) const {
node<T> *cur = root_, **child;
int depth = 0, key_len = std::strlen(key) + 1;
while (cur != nullptr) {
if (cur->prefix_len_ != cur->check_prefix(key + depth, key_len - depth)) {
/* prefix mismatch */
return nullptr;
return T{};
}
if (cur->prefix_len_ == key_len - depth) {
/* exact match */
return cur->is_leaf() ? static_cast<leaf_node<T>*>(cur)->value_ : nullptr;
return cur->is_leaf() ? static_cast<leaf_node<T>*>(cur)->value_ : T{};
}
child = static_cast<inner_node<T>*>(cur)->find_child(key[depth + cur->prefix_len_]);
depth += (cur->prefix_len_ + 1);
cur = child != nullptr ? *child : nullptr;
}
return nullptr;
return T{};
}

template <class T> T *art<T>::set(const char *key, T *value) {
template <class T>
T art<T>::set(const char *key, T value) {
int key_len = std::strlen(key) + 1, depth = 0, prefix_match_len;
if (root_ == nullptr) {
root_ = new leaf_node<T>(value);
root_->prefix_ = new char[key_len];
std::copy(key, key + key_len + 1, root_->prefix_);
root_->prefix_len_ = key_len;
return nullptr;
return T{};
}

node<T> **cur = &root_, **child;
Expand Down Expand Up @@ -155,7 +157,7 @@ template <class T> T *art<T>::set(const char *key, T *value) {

/* cur must be a leaf */
auto cur_leaf = static_cast<leaf_node<T>*>(*cur);
T *old_value = cur_leaf->value_;
T old_value = cur_leaf->value_;
cur_leaf->value_ = value;
return old_value;
}
Expand Down Expand Up @@ -205,7 +207,7 @@ template <class T> T *art<T>::set(const char *key, T *value) {
new_parent->set_child(key[depth + prefix_match_len], new_node);

*cur = new_parent;
return nullptr;
return T{};
}

/* must be inner node */
Expand Down Expand Up @@ -235,7 +237,7 @@ template <class T> T *art<T>::set(const char *key, T *value) {
new_node->prefix_);
new_node->prefix_len_ = key_len - depth - (**cur).prefix_len_ - 1;
(**cur_inner).set_child(child_partial_key, new_node);
return nullptr;
return T{};
}

/* propagate down and repeat:
Expand All @@ -251,11 +253,12 @@ template <class T> T *art<T>::set(const char *key, T *value) {
}
}

template <class T> T *art<T>::del(const char *key) {
template <class T>
T art<T>::del(const char *key) {
int depth = 0, key_len = std::strlen(key) + 1;

if (root_ == nullptr) {
return nullptr;
return T{};
}

/* pointer to parent, current and child node */
Expand All @@ -270,13 +273,13 @@ template <class T> T *art<T>::del(const char *key) {
(**cur).check_prefix(key + depth, key_len - depth)) {
/* prefix mismatch => key doesn't exist */

return nullptr;
return T{};
}

if (key_len == depth + (**cur).prefix_len_) {
/* exact match */
if (!(**cur).is_leaf()) {
return nullptr;
return T{};
}
auto value = static_cast<leaf_node<T>*>(*cur)->value_;
auto n_siblings = par != nullptr ? (**par).n_children() - 1 : 0;
Expand Down Expand Up @@ -374,7 +377,7 @@ template <class T> T *art<T>::del(const char *key) {
par = reinterpret_cast<inner_node<T>**>(cur);
cur = (**par).find_child(cur_partial_key);
}
return nullptr;
return T{};
}

template <class T> tree_it<T> art<T>::begin() {
Expand All @@ -385,7 +388,9 @@ template <class T> tree_it<T> art<T>::begin(const char *key) {
return tree_it<T>::greater_equal(this->root_, key);
}

template <class T> tree_it<T> art<T>::end() { return tree_it<T>(); }
template <class T> tree_it<T> art<T>::end() {
return tree_it<T>();
}

} // namespace art

Expand Down
4 changes: 2 additions & 2 deletions include/art/child_it.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ template <class T> class inner_node;
template <class T> class child_it {
public:
child_it() = default;
explicit child_it(inner_node<T> *n);
child_it(inner_node<T> *n, int relative_index);
child_it(const child_it<T> &other) = default;
child_it(child_it<T> &&other) noexcept = default;
child_it<T> &operator=(const child_it<T> &other) = default;
child_it<T> &operator=(child_it<T> &&other) noexcept = default;

explicit child_it(inner_node<T> *n);
child_it(inner_node<T> *n, int relative_index);

using iterator_category = std::bidirectional_iterator_tag;
using value_type = const char;
Expand Down
3 changes: 1 addition & 2 deletions include/art/inner_node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@ namespace art {

template <class T> class inner_node : public node<T> {
public:
virtual ~inner_node() = default;

inner_node() = default;
inner_node(const inner_node<T> &other) = default;
inner_node(inner_node<T> &&other) noexcept = default;
inner_node<T> &operator=(const inner_node<T> &other) = default;
inner_node<T> &operator=(inner_node<T> &&other) noexcept = default;
virtual ~inner_node() = default;

bool is_leaf() const override;

Expand Down
6 changes: 3 additions & 3 deletions include/art/leaf_node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ template <class T> class art;

template <class T> class leaf_node : public node<T> {
public:
explicit leaf_node(T *value);
explicit leaf_node(T value);
bool is_leaf() const override;

T *value_;
T value_;
};

template <class T>
leaf_node<T>::leaf_node(T *value): value_(value) {}
leaf_node<T>::leaf_node(T value): value_(value) {}

template <class T>
bool leaf_node<T>::is_leaf() const { return true; }
Expand Down
1 change: 1 addition & 0 deletions include/art/node_16.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ template <class T> inner_node<T> *node_16<T>::grow() {
auto new_node = new node_48<T>();
new_node->prefix_ = this->prefix_;
new_node->prefix_len_ = this->prefix_len_;
new_node->n_children_ = this->n_children_;
std::copy(this->children_, this->children_ + this->n_children_, new_node->children_);
for (int i = 0; i < n_children_; ++i) {
new_node->indexes_[(uint8_t) this->keys_[i]] = i;
Expand Down
Loading

0 comments on commit 1023b84

Please sign in to comment.