@@ -48,25 +48,22 @@ namespace SPTAG
4848 struct CachedChunk {
4949 SizeType chunkId;
5050 std::string data;
51- std::chrono::steady_clock::time_point fetchTime;
5251 };
5352 using LruList = std::list<CachedChunk>;
5453 mutable std::shared_mutex m_cacheMutex;
5554 mutable LruList m_lruList;
5655 mutable std::unordered_map<SizeType, LruList::iterator> m_cacheMap;
57- int m_cacheTTLMs{0 }; // TTL in ms, 0 = cache disabled
58- int m_cacheMaxChunks{10000 }; // max cached chunks (~40MB at 4096 chunk size)
56+ int m_cacheMaxChunks{10000 }; // max cached chunks; <= 0 disables caching
5957
6058 // Insert or update a chunk in the LRU cache. Caller must hold exclusive m_cacheMutex.
61- void CachePut (SizeType chunkId, const std::string& data, std::chrono::steady_clock::time_point now ) const
59+ void CachePut (SizeType chunkId, const std::string& data) const
6260 {
6361 if (m_cacheMaxChunks <= 0 ) return ; // cache disabled
6462
6563 auto it = m_cacheMap.find (chunkId);
6664 if (it != m_cacheMap.end ()) {
6765 // Update existing: move to front
6866 it->second ->data = data;
69- it->second ->fetchTime = now;
7067 m_lruList.splice (m_lruList.begin (), m_lruList, it->second );
7168 } else {
7269 // Evict LRU entries if at capacity
@@ -75,7 +72,7 @@ namespace SPTAG
7572 m_cacheMap.erase (back.chunkId );
7673 m_lruList.pop_back ();
7774 }
78- m_lruList.push_front ({chunkId, data, now });
75+ m_lruList.push_front ({chunkId, data});
7976 m_cacheMap[chunkId] = m_lruList.begin ();
8077 }
8178 }
@@ -112,7 +109,7 @@ namespace SPTAG
112109 auto ret = m_db->Put (ChunkKey (chunkId), data, MaxTimeout, nullptr );
113110 if (ret == ErrorCode::Success) {
114111 std::unique_lock<std::shared_mutex> lock (m_cacheMutex);
115- CachePut (chunkId, data, std::chrono::steady_clock::now () );
112+ CachePut (chunkId, data);
116113 }
117114 return ret;
118115 }
@@ -136,16 +133,17 @@ namespace SPTAG
136133 std::string data = ReadChunk (chunkId);
137134 if (!data.empty ()) {
138135 std::unique_lock<std::shared_mutex> lock (m_cacheMutex);
139- CachePut (chunkId, data, std::chrono::steady_clock::now () );
136+ CachePut (chunkId, data);
140137 }
141138 return data;
142139 }
143140
144- // Read a single byte for a VID using cache . Returns 0xfe on error/miss.
145- uint8_t ReadVersionByte (SizeType vid) const
141+ // Read a single byte for a VID. Returns 0xfe on error/miss.
142+ uint8_t ReadVersionByte (SizeType vid, VersionReadPolicy policy = VersionReadPolicy::UseCache ) const
146143 {
147144 SizeType cid = ChunkId (vid);
148- std::string chunk = ReadChunkCached (cid);
145+ std::string chunk = (policy == VersionReadPolicy::BypassCacheNoFill) ?
146+ ReadChunk (cid) : ReadChunkCached (cid);
149147 if (chunk.empty () || (int )chunk.size () <= ChunkOffset (vid)) {
150148 return 0xfe ;
151149 }
@@ -190,7 +188,6 @@ namespace SPTAG
190188 void SetDB (std::shared_ptr<Helper::KeyValueIO> db) { m_db = db; }
191189 void SetLayer (int layer) { m_layer = layer; }
192190 void SetChunkSize (int chunkSize) { m_chunkSize = chunkSize; }
193- void SetCacheTTL (int ttlMs) { m_cacheTTLMs = ttlMs; }
194191 void SetCacheMaxChunks (int maxChunks) { m_cacheMaxChunks = maxChunks; }
195192
196193 std::shared_ptr<Helper::KeyValueIO> GetDB () const { return m_db; }
@@ -293,12 +290,17 @@ namespace SPTAG
293290 std::uint64_t BufferSize () const override { return static_cast <std::uint64_t >(m_count.load ()) + sizeof (SizeType); }
294291
295292 bool Deleted (const SizeType& key) const override
293+ {
294+ return Deleted (key, VersionReadPolicy::UseCache);
295+ }
296+
297+ bool Deleted (const SizeType& key, VersionReadPolicy policy) const override
296298 {
297299 if (key < 0 || key >= m_count.load ()) {
298300 SPTAGLIB_LOG (Helper::LogLevel::LL_Error, " TiKVVersionMap::Deleted: invalid key %d (max %d)\n " , key, m_count.load ());
299301 return true ;
300302 }
301- return ReadVersionByte (key) == 0xfe ;
303+ return ReadVersionByte (key, policy ) == 0xfe ;
302304 }
303305
304306 bool Delete (const SizeType& key) override
@@ -323,12 +325,17 @@ namespace SPTAG
323325 }
324326
325327 uint8_t GetVersion (const SizeType& key) override
328+ {
329+ return GetVersion (key, VersionReadPolicy::UseCache);
330+ }
331+
332+ uint8_t GetVersion (const SizeType& key, VersionReadPolicy policy) override
326333 {
327334 if (key < 0 || key >= m_count.load ()) {
328335 SPTAGLIB_LOG (Helper::LogLevel::LL_Error, " TiKVVersionMap::GetVersion: invalid key %d (max %d)\n " , key, m_count.load ());
329336 return 0xfe ;
330337 }
331- return ReadVersionByte (key);
338+ return ReadVersionByte (key, policy );
332339 }
333340
334341 void SetVersion (const SizeType& key, const uint8_t & version) override
@@ -451,13 +458,18 @@ namespace SPTAG
451458 // / Batch version lookup with local cache support.
452459 // / Checks cache first, only fetches misses from TiKV via BatchGet.
453460 void BatchGetVersions (const std::vector<SizeType>& vids, std::vector<uint8_t >& versions) override
461+ {
462+ BatchGetVersions (vids, versions, VersionReadPolicy::UseCache);
463+ }
464+
465+ void BatchGetVersions (const std::vector<SizeType>& vids, std::vector<uint8_t >& versions, VersionReadPolicy policy) override
454466 {
455467 versions.resize (vids.size ());
456468 if (vids.empty ()) return ;
457469
458470 SizeType count = m_count.load ();
459- auto now = std::chrono::steady_clock::now ( );
460- bool cacheEnabled = (m_cacheTTLMs > 0 );
471+ bool bypassCache = (policy == VersionReadPolicy::BypassCacheNoFill );
472+ bool cacheEnabled = (m_cacheMaxChunks > 0 && !bypassCache );
461473
462474 // Group VIDs by chunk
463475 std::unordered_map<SizeType, std::vector<size_t >> chunkToIndices;
@@ -479,11 +491,8 @@ namespace SPTAG
479491 for (auto & [cid, indices] : chunkToIndices) {
480492 auto it = m_cacheMap.find (cid);
481493 if (it != m_cacheMap.end ()) {
482- auto ageMs = std::chrono::duration_cast<std::chrono::milliseconds>(now - it->second ->fetchTime ).count ();
483- if (ageMs < m_cacheTTLMs) {
484- resolvedChunks[cid] = it->second ->data ; // copy
485- continue ;
486- }
494+ resolvedChunks[cid] = it->second ->data ; // copy
495+ continue ;
487496 }
488497 missChunkIds.push_back (cid);
489498 }
@@ -522,11 +531,11 @@ namespace SPTAG
522531 m_layer, missingChunks, static_cast <int >(missChunkIds.size ()), missChunkIds[0 ]);
523532 }
524533
525- // Update LRU cache with fetched chunks (exclusive lock)
534+ // Update LRU cache with fetched chunks (exclusive lock). Bypass reads never fill cache.
526535 if (cacheEnabled && !fetchedChunks.empty ()) {
527536 std::unique_lock<std::shared_mutex> lock (m_cacheMutex);
528537 for (auto & [cid, data] : fetchedChunks) {
529- CachePut (cid, data, now );
538+ CachePut (cid, data);
530539 }
531540 }
532541 }
0 commit comments