Skip to content

Commit

Permalink
Improved performance
Browse files Browse the repository at this point in the history
  • Loading branch information
ankane committed Oct 7, 2024
1 parent 654f650 commit 508d04c
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 28 deletions.
50 changes: 36 additions & 14 deletions include/rice/rice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,7 @@ namespace Rice::detail

#include <unordered_map>
#include <any>
#include <tuple>


namespace Rice::detail
Expand All @@ -1093,8 +1094,8 @@ namespace Rice::detail
Return_T lookup(VALUE klass, ID method_id);

private:
std::pair<VALUE, ID> key(VALUE klass, ID method_id);
std::map<std::pair<VALUE, ID>, std::any> natives_ = {};
size_t key(VALUE klass, ID method_id);
std::unordered_multimap<size_t, std::tuple<VALUE, ID, std::any>> natives_ = {};
};
}

Expand All @@ -1112,20 +1113,32 @@ namespace Rice::detail
{
// Effective Java (2nd edition)
// https://stackoverflow.com/a/2634715
inline std::pair<VALUE, ID> NativeRegistry::key(VALUE klass, ID id)
inline size_t NativeRegistry::key(VALUE klass, ID id)
{
uint32_t prime = 53;
return (prime + klass) * prime + id;
}

inline void NativeRegistry::add(VALUE klass, ID method_id, std::any callable)
{
if (rb_type(klass) == T_ICLASS)
{
klass = detail::protect(rb_class_of, klass);
}

return std::make_pair(klass, id);
}
auto range = this->natives_.equal_range(key(klass, method_id));
for (auto it = range.first; it != range.second; ++it)
{
const auto [k, m, d] = it->second;

inline void NativeRegistry::add(VALUE klass, ID method_id, std::any callable)
{
// Now store data about it
this->natives_[key(klass, method_id)] = callable;
if (k == klass && m == method_id)
{
std::get<2>(it->second) = callable;
return;
}
}

this->natives_.emplace(std::make_pair(key(klass, method_id), std::make_tuple(klass, method_id, callable)));
}

template <typename Return_T>
Expand All @@ -1144,14 +1157,23 @@ namespace Rice::detail
template <typename Return_T>
inline Return_T NativeRegistry::lookup(VALUE klass, ID method_id)
{
auto iter = this->natives_.find(key(klass, method_id));
if (iter == this->natives_.end())
if (rb_type(klass) == T_ICLASS)
{
klass = detail::protect(rb_class_of, klass);
}

auto range = this->natives_.equal_range(key(klass, method_id));
for (auto it = range.first; it != range.second; ++it)
{
rb_raise(rb_eRuntimeError, "Could not find data for klass and method id");
const auto [k, m, d] = it->second;

if (k == klass && m == method_id)
{
return std::any_cast<Return_T>(d);
}
}

std::any data = iter->second;
return std::any_cast<Return_T>(data);
rb_raise(rb_eRuntimeError, "Could not find data for klass and method id");
}
}

Expand Down
5 changes: 3 additions & 2 deletions rice/detail/NativeRegistry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <unordered_map>
#include <any>
#include <tuple>

#include "ruby.hpp"

Expand All @@ -22,8 +23,8 @@ namespace Rice::detail
Return_T lookup(VALUE klass, ID method_id);

private:
std::pair<VALUE, ID> key(VALUE klass, ID method_id);
std::map<std::pair<VALUE, ID>, std::any> natives_ = {};
size_t key(VALUE klass, ID method_id);
std::unordered_multimap<size_t, std::tuple<VALUE, ID, std::any>> natives_ = {};
};
}
#include "NativeRegistry.ipp"
Expand Down
45 changes: 33 additions & 12 deletions rice/detail/NativeRegistry.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,32 @@ namespace Rice::detail
{
// Effective Java (2nd edition)
// https://stackoverflow.com/a/2634715
inline std::pair<VALUE, ID> NativeRegistry::key(VALUE klass, ID id)
inline size_t NativeRegistry::key(VALUE klass, ID id)
{
uint32_t prime = 53;
return (prime + klass) * prime + id;
}

inline void NativeRegistry::add(VALUE klass, ID method_id, std::any callable)
{
if (rb_type(klass) == T_ICLASS)
{
klass = detail::protect(rb_class_of, klass);
}

return std::make_pair(klass, id);
}
auto range = this->natives_.equal_range(key(klass, method_id));
for (auto it = range.first; it != range.second; ++it)
{
const auto [k, m, d] = it->second;

inline void NativeRegistry::add(VALUE klass, ID method_id, std::any callable)
{
// Now store data about it
this->natives_[key(klass, method_id)] = callable;
if (k == klass && m == method_id)
{
std::get<2>(it->second) = callable;
return;
}
}

this->natives_.emplace(std::make_pair(key(klass, method_id), std::make_tuple(klass, method_id, callable)));
}

template <typename Return_T>
Expand All @@ -44,13 +56,22 @@ namespace Rice::detail
template <typename Return_T>
inline Return_T NativeRegistry::lookup(VALUE klass, ID method_id)
{
auto iter = this->natives_.find(key(klass, method_id));
if (iter == this->natives_.end())
if (rb_type(klass) == T_ICLASS)
{
klass = detail::protect(rb_class_of, klass);
}

auto range = this->natives_.equal_range(key(klass, method_id));
for (auto it = range.first; it != range.second; ++it)
{
rb_raise(rb_eRuntimeError, "Could not find data for klass and method id");
const auto [k, m, d] = it->second;

if (k == klass && m == method_id)
{
return std::any_cast<Return_T>(d);
}
}

std::any data = iter->second;
return std::any_cast<Return_T>(data);
rb_raise(rb_eRuntimeError, "Could not find data for klass and method id");
}
}

0 comments on commit 508d04c

Please sign in to comment.