-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[core] Enable heterogeneous access for LRU cache #48954
Changes from all commits
32cabb6
d0265fd
bb8f7d8
29380a1
095e704
73e2fae
2e9b7a9
05b67f7
8ecbdf3
e1cc2c2
1ef094a
ad8ac27
357c3cd
1af2ff0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,19 @@ namespace ray::utils::container { | |
|
||
namespace { | ||
constexpr size_t kTestCacheSz = 1; | ||
|
||
class TestClassWithHashAndEq { | ||
public: | ||
TestClassWithHashAndEq(std::string data) : data_(std::move(data)) {} | ||
bool operator==(const TestClassWithHashAndEq &rhs) const { return data_ == rhs.data_; } | ||
template <typename H> | ||
friend H AbslHashValue(H h, const TestClassWithHashAndEq &obj) { | ||
return H::combine(std::move(h), obj.data_); | ||
} | ||
|
||
private: | ||
std::string data_; | ||
}; | ||
} // namespace | ||
|
||
TEST(SharedLruCache, PutAndGet) { | ||
|
@@ -34,22 +47,21 @@ TEST(SharedLruCache, PutAndGet) { | |
|
||
// Check put and get. | ||
cache.Put("1", std::make_shared<std::string>("1")); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. write a comment about the heterogeneous key is tested here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I don't use heterogeneous access for put operation, since the ownership is transferred anyway. |
||
val = cache.Get("1"); | ||
val = cache.Get(std::string_view{"1"}); | ||
EXPECT_NE(val, nullptr); | ||
EXPECT_EQ(*val, "1"); | ||
|
||
// Check key eviction. | ||
cache.Put("2", std::make_shared<std::string>("2")); | ||
val = cache.Get("1"); | ||
val = cache.Get(std::string_view{"1"}); | ||
EXPECT_EQ(val, nullptr); | ||
val = cache.Get("2"); | ||
val = cache.Get(std::string_view{"2"}); | ||
EXPECT_NE(val, nullptr); | ||
EXPECT_EQ(*val, "2"); | ||
|
||
// Check deletion. | ||
EXPECT_FALSE(cache.Delete("1")); | ||
EXPECT_TRUE(cache.Delete("2")); | ||
val = cache.Get("2"); | ||
EXPECT_FALSE(cache.Delete(std::string_view{"1"})); | ||
val = cache.Get(std::string_view{"1"}); | ||
EXPECT_EQ(val, nullptr); | ||
} | ||
|
||
|
@@ -73,4 +85,13 @@ TEST(SharedLruConstCache, TypeAliasAssertion) { | |
std::is_same_v<SharedLruConstCache<int, int>, SharedLruCache<int, const int>>); | ||
} | ||
|
||
TEST(SharedLruConstCache, CustomizedKey) { | ||
TestClassWithHashAndEq obj1{"hello"}; | ||
TestClassWithHashAndEq obj2{"hello"}; | ||
SharedLruCache<TestClassWithHashAndEq, std::string> cache{2}; | ||
cache.Put(obj1, std::make_shared<std::string>("val")); | ||
auto val = cache.Get(obj2); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess we want to test cache.Get(absl::string_view{"hello"}) here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, heterogeneous lookup is provided by flat hash map implementation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The intended use case for heterogeneous lookup here is C++ native string types, including std::string_view, std::string and const char*. For example, for a All of them have been implemented by hash map. Unfortunately not for STL unordered map implementation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right, can we have a test case that heterogeneous lookup is used? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I already did? |
||
EXPECT_EQ(*val, "val"); | ||
} | ||
|
||
} // namespace ray::utils::container |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need a move in Delete? It's possible user wants to delete then still use its key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also even if you want move semantics you want to pass in by value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's perfect forward with universal reference not move.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can forward instead of pass by value in headers, slightly more efficient, but only makes sense for Put where you can possibly forward rvalue in, underlying cache_ functions used for Get and Delete take const lvalue anyways so it doesn't matter...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put takes ownership of the key, so I take it by value;
Deletion and lookup only borrows reference, so perfect forwarding.