Copilot commented on code in PR #13893:
URL: https://github.com/apache/trafficserver/pull/13893#discussion_r4366151916


##########
src/iocore/cache/unit_tests/test_RamCacheCLFUS.cc:
##########
@@ -398,3 +456,295 @@ TEST_CASE("CLFUS value metric is a floating-point 
density", "[cache][ramcache][c
   static_assert(v_hot > v_one, "CLFUS value metric does not increase with 
hits");
   static_assert(v_small > v_large, "CLFUS value metric does not decrease with 
size");
 }
+
+namespace
+{
+
+CryptoHash
+make_key(uint64_t id)
+{
+  CryptoHash key;
+  key.u32[0] = static_cast<uint32_t>(0xc0ffee00 + id);
+  key.u32[2] = static_cast<uint32_t>(0xdeadbeef + id);
+  key.u32[3] = static_cast<uint32_t>(0x12345678 + id);
+  return key;
+}
+
+} // namespace
+
+TEST_CASE("CLFUS decays hit count when sparing victims during eviction", 
"[cache][ramcache][clfus]")
+{
+  CacheDisk disk;
+  init_disk(disk);
+  StripeSM stripe{&disk, 10, 0};
+  CacheVol cache_vol;
+  wire_stripe(stripe, cache_vol);
+
+  cache_config_ram_cache_compress        = CACHE_COMPRESSION_NONE;
+  cache_config_ram_cache_use_seen_filter = 0;
+
+  RamCacheCLFUS rc;
+  rc.init(32 * 1024, &stripe);
+
+  auto buf  = make_buffer(compressible_bytes(8 * 1024));
+  auto key1 = make_key(1);
+  auto key2 = make_key(2);
+  auto key3 = make_key(3);
+
+  REQUIRE(rc.put(&key1, buf.get(), 8 * 1024) == 1);
+  REQUIRE(rc.put(&key2, buf.get(), 8 * 1024) == 1);
+  REQUIRE(rc.put(&key3, buf.get(), 8 * 1024) == 1);
+
+  RamCacheCLFUSEntry *e1 = RamCacheCLFUSTestAccess::find_entry(rc, key1);
+  REQUIRE(e1 != nullptr);
+  e1->hits = 16; // Give key1 high hits so it exceeds average value
+
+  // key4 triggers an eviction pass
+  auto key4 = make_key(4);
+  rc.put(&key4, buf.get(), 8 * 1024);
+
+  // e1 was spared on its first pass as a victim (16 -> 8), then taken on the
+  // second pass once the requeue budget ran out and put back by
+  // _requeue_victims() (8 -> 7). Without the spared-victim decay it would be 
15.
+  CHECK(e1->hits == 7);
+}
+
+TEST_CASE("CLFUS unconditionally promotes resident entries to the tail on 
hits", "[cache][ramcache][clfus]")
+{
+  CacheDisk disk;
+  init_disk(disk);
+  StripeSM stripe{&disk, 10, 0};
+  CacheVol cache_vol;
+  wire_stripe(stripe, cache_vol);
+
+  cache_config_ram_cache_compress        = CACHE_COMPRESSION_NONE;
+  cache_config_ram_cache_use_seen_filter = 0;
+
+  RamCacheCLFUS rc;
+  rc.init(64 * 1024, &stripe);
+
+  auto buf  = make_buffer(compressible_bytes(4 * 1024));
+  auto key1 = make_key(1);
+  auto key2 = make_key(2);
+  auto key3 = make_key(3);
+
+  REQUIRE(rc.put(&key1, buf.get(), 4 * 1024) == 1);
+  REQUIRE(rc.put(&key2, buf.get(), 4 * 1024) == 1);
+  REQUIRE(rc.put(&key3, buf.get(), 4 * 1024) == 1);
+
+  RamCacheCLFUSEntry *e1 = RamCacheCLFUSTestAccess::find_entry(rc, key1);
+  REQUIRE(e1 != nullptr);
+  // Initial order in _lru[0] has e1 at the head
+  CHECK(RamCacheCLFUSTestAccess::lru_head(rc) == e1);
+
+  // Inflate _average_value so e1's value is lower than average
+  RamCacheCLFUSTestAccess::set_average_value(rc, 1000.0);
+
+  // get() on key1 must unconditionally promote e1 to the tail of _lru[0]
+  Ptr<IOBufferData> got;
+  CHECK(rc.get(&key1, &got) == 1);
+  CHECK(RamCacheCLFUSTestAccess::lru_tail(rc) == e1);
+  CHECK(RamCacheCLFUSTestAccess::lru_head(rc) != e1);
+}
+
+TEST_CASE("CLFUS history entry is refreshed on get() hit", 
"[cache][ramcache][clfus]")
+{
+  CacheDisk disk;
+  init_disk(disk);
+  StripeSM stripe{&disk, 10, 0};
+  CacheVol cache_vol;
+  wire_stripe(stripe, cache_vol);
+
+  cache_config_ram_cache_compress        = CACHE_COMPRESSION_NONE;
+  cache_config_ram_cache_use_seen_filter = 0;
+
+  RamCacheCLFUS rc;
+  rc.init(12 * 1024, &stripe);
+
+  auto buf  = make_buffer(compressible_bytes(8 * 1024));
+  auto key1 = make_key(1);
+  auto key2 = make_key(2);
+
+  REQUIRE(rc.put(&key1, buf.get(), 8 * 1024) == 1);
+  // key2 cannot fit in 12KB (8KB + 8KB > 12KB), routed to history (_lru[1])
+  CHECK(rc.put(&key2, buf.get(), 8 * 1024) == 0);
+
+  RamCacheCLFUSEntry *e2 = RamCacheCLFUSTestAccess::find_entry(rc, key2);
+  REQUIRE(e2 != nullptr);
+  REQUIRE(e2->flag_bits.lru == 1); // in history
+
+  uint64_t          hits_before = e2->hits;
+  Ptr<IOBufferData> got;

Review Comment:
   The history-recency assertion cannot detect a regression: `e2` is the only 
history entry, so it is already the tail before `get()`, and the check still 
passes if the new remove/enqueue operations are deleted. Add another history 
entry and require `e2` not to be the tail before the lookup, then verify that 
the lookup moves it there.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to