diff --git a/chrome/browser/ui/app_list/search/ranking/mrfu_cache.cc b/chrome/browser/ui/app_list/search/ranking/mrfu_cache.cc index cc94f119067a93..37ea1f14368827 100644 --- a/chrome/browser/ui/app_list/search/ranking/mrfu_cache.cc +++ b/chrome/browser/ui/app_list/search/ranking/mrfu_cache.cc @@ -138,6 +138,30 @@ float MrfuCache::GetNormalized(const std::string& item) { return Get(item) / proto_->total_score(); } +MrfuCache::Items MrfuCache::GetAll() { + if (!proto_.initialized()) + return {}; + + MrfuCache::Items results; + for (auto& item_score : *proto_->mutable_items()) { + Score& score = item_score.second; + Decay(&score); + results.emplace_back(item_score.first, score.score()); + } + return results; +} + +MrfuCache::Items MrfuCache::GetAllNormalized() { + if (!proto_.initialized() || proto_->total_score() == 0.0f) + return {}; + + auto results = GetAll(); + const float total = proto_->total_score(); + for (auto& pair : results) + pair.second /= total; + return results; +} + void MrfuCache::Decay(Score* score) { int64_t update_count = proto_->update_count(); int64_t count_delta = update_count - score->last_update_count(); diff --git a/chrome/browser/ui/app_list/search/ranking/mrfu_cache.h b/chrome/browser/ui/app_list/search/ranking/mrfu_cache.h index 59acb562cf7212..43f3957a539545 100644 --- a/chrome/browser/ui/app_list/search/ranking/mrfu_cache.h +++ b/chrome/browser/ui/app_list/search/ranking/mrfu_cache.h @@ -84,6 +84,9 @@ class MrfuCache { base::TimeDelta write_delay = base::Seconds(30); }; + // A vector of items and their scores. No guarantees of ordering. + using Items = std::vector>; + MrfuCache(const base::FilePath& path, const Params& params); ~MrfuCache(); @@ -99,6 +102,13 @@ class MrfuCache { // Returns the score of |item| divided by the sum of all scores. float GetNormalized(const std::string& item); + // Returns all items in the cache and their scores. + Items GetAll(); + + // Returns all items in the cache and their scores, normalized by the sum of + // all scores. + Items GetAllNormalized(); + private: friend class MrfuCacheTest; diff --git a/chrome/browser/ui/app_list/search/ranking/mrfu_cache_unittest.cc b/chrome/browser/ui/app_list/search/ranking/mrfu_cache_unittest.cc index d5acd28a2cd81b..507d1859ce5201 100644 --- a/chrome/browser/ui/app_list/search/ranking/mrfu_cache_unittest.cc +++ b/chrome/browser/ui/app_list/search/ranking/mrfu_cache_unittest.cc @@ -19,6 +19,10 @@ namespace app_list { namespace { +using testing::FloatNear; +using testing::Pair; +using testing::UnorderedElementsAre; + constexpr float kEps = 1e-3f; } // namespace @@ -29,10 +33,11 @@ class MrfuCacheTest : public testing::Test { base::FilePath GetPath() { return temp_dir_.GetPath().Append("proto"); } - MrfuCache::Params TestingParams() { + MrfuCache::Params TestingParams(float half_life = 10.0f, + float boost_factor = 5.0f) { MrfuCache::Params params; - params.half_life = 10.0f; - params.boost_factor = 5.0f; + params.half_life = half_life; + params.boost_factor = boost_factor; params.max_items = 3u; params.min_score = 0.01f; params.write_delay = base::Seconds(0); @@ -106,12 +111,9 @@ TEST_F(MrfuCacheTest, GetNormalized) { EXPECT_FLOAT_EQ(cache.GetNormalized("A"), 0.0f); - cache.Use("A"); - cache.Use("B"); - cache.Use("A"); - cache.Use("A"); - cache.Use("B"); - cache.Use("C"); + for (std::string item : {"A", "B", "A", "A", "B", "C"}) { + cache.Use(item); + } float a = cache.Get("A"); float b = cache.Get("B"); float c = cache.Get("C"); @@ -122,6 +124,43 @@ TEST_F(MrfuCacheTest, GetNormalized) { EXPECT_NEAR(cache.GetNormalized("C"), c / total, kEps); } +TEST_F(MrfuCacheTest, GetAll) { + MrfuCache cache(GetPath(), + TestingParams(/*half_life=*/1.0f, /*boost_factor=*/1.0f)); + EXPECT_TRUE(cache.GetAll().empty()); + Wait(); + EXPECT_TRUE(cache.GetAll().empty()); + + for (std::string item : {"A", "B", "C"}) { + cache.Use(item); + } + + // These are hand-calculated scores. + EXPECT_THAT(cache.GetAll(), + UnorderedElementsAre(Pair("A", FloatNear(0.166f, kEps)), + Pair("B", FloatNear(0.333f, kEps)), + Pair("C", FloatNear(0.666f, kEps)))); +} + +TEST_F(MrfuCacheTest, GetAllNormalized) { + MrfuCache cache(GetPath(), + TestingParams(/*half_life=*/1.0f, /*boost_factor=*/1.0f)); + EXPECT_TRUE(cache.GetAll().empty()); + Wait(); + EXPECT_TRUE(cache.GetAll().empty()); + + for (std::string item : {"A", "B", "C"}) { + cache.Use(item); + } + + // These are hand-calculate scores. + float total = 0.1666f + 0.333f + 0.666f; + EXPECT_THAT(cache.GetAllNormalized(), + UnorderedElementsAre(Pair("A", FloatNear(0.166f / total, kEps)), + Pair("B", FloatNear(0.333f / total, kEps)), + Pair("C", FloatNear(0.666f / total, kEps)))); +} + TEST_F(MrfuCacheTest, CorrectBoostCoeffApproximation) { // This is a hand-optimized solution to the boost coefficient equation // accurate to 3 dp. It uses a half-life of 10 (so decay coefficient of about