This is an automated email from the ASF dual-hosted git repository.

JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new 881e924398 [core] Support off-heap lookup cache (#8867)
881e924398 is described below

commit 881e92439843fd5b627de1046dbca92e238831be
Author: Jingsong Lee <[email protected]>
AuthorDate: Tue Jul 28 08:17:37 2026 +0800

    [core] Support off-heap lookup cache (#8867)
---
 .../org/apache/paimon/io/cache/CacheManager.java   | 35 ++++++++++++++++++++--
 .../apache/paimon/io/cache/CacheManagerTest.java   | 17 +++++++++++
 2 files changed, 49 insertions(+), 3 deletions(-)

diff --git 
a/paimon-common/src/main/java/org/apache/paimon/io/cache/CacheManager.java 
b/paimon-common/src/main/java/org/apache/paimon/io/cache/CacheManager.java
index 073c3db6c3..e8cd314725 100644
--- a/paimon-common/src/main/java/org/apache/paimon/io/cache/CacheManager.java
+++ b/paimon-common/src/main/java/org/apache/paimon/io/cache/CacheManager.java
@@ -31,7 +31,7 @@ import java.io.IOException;
 import static org.apache.paimon.utils.Preconditions.checkNotNull;
 
 /** Cache manager to cache bytes to paged {@link MemorySegment}s. */
-public class CacheManager {
+public class CacheManager implements AutoCloseable {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(CacheManager.class);
 
@@ -43,8 +43,13 @@ public class CacheManager {
 
     private final Cache dataCache;
     private final Cache indexCache;
+    private final boolean offHeap;
 
     public CacheManager(MemorySize maxMemorySize, double 
highPriorityPoolRatio) {
+        this(maxMemorySize, highPriorityPoolRatio, false);
+    }
+
+    private CacheManager(MemorySize maxMemorySize, double 
highPriorityPoolRatio, boolean offHeap) {
         Preconditions.checkArgument(
                 highPriorityPoolRatio >= 0 && highPriorityPoolRatio < 1,
                 "The high priority pool ratio should in the range [0, 1).");
@@ -58,12 +63,19 @@ public class CacheManager {
         } else {
             this.indexCache = 
CacheBuilder.newBuilder().maximumWeight(indexCacheSize).build();
         }
+        this.offHeap = offHeap;
         LOG.info(
-                "Initialize cache manager with data cache of {} and index 
cache of {}.",
+                "Initialize {} cache manager with data cache of {} and index 
cache of {}.",
+                offHeap ? "off-heap" : "heap",
                 dataCacheSize,
                 indexCacheSize);
     }
 
+    public static CacheManager createOffHeap(
+            MemorySize maxMemorySize, double highPriorityPoolRatio) {
+        return new CacheManager(maxMemorySize, highPriorityPoolRatio, true);
+    }
+
     @VisibleForTesting
     public Cache dataCache() {
         return dataCache;
@@ -82,7 +94,7 @@ public class CacheManager {
                         k -> {
                             try {
                                 return new Cache.CacheValue(
-                                        MemorySegment.wrap(reader.read(key)), 
callback);
+                                        toMemorySegment(reader.read(key)), 
callback);
                             } catch (IOException e) {
                                 throw new RuntimeException(e);
                             }
@@ -98,6 +110,23 @@ public class CacheManager {
         }
     }
 
+    private MemorySegment toMemorySegment(byte[] bytes) {
+        if (!offHeap) {
+            return MemorySegment.wrap(bytes);
+        }
+        MemorySegment segment = 
MemorySegment.allocateOffHeapMemory(bytes.length);
+        segment.put(0, bytes);
+        return segment;
+    }
+
+    @Override
+    public void close() {
+        dataCache.invalidateAll();
+        if (indexCache != dataCache) {
+            indexCache.invalidateAll();
+        }
+    }
+
     /** The container for the segment. */
     public static class SegmentContainer {
 
diff --git 
a/paimon-common/src/test/java/org/apache/paimon/io/cache/CacheManagerTest.java 
b/paimon-common/src/test/java/org/apache/paimon/io/cache/CacheManagerTest.java
index 6045956a6d..e8ca35271e 100644
--- 
a/paimon-common/src/test/java/org/apache/paimon/io/cache/CacheManagerTest.java
+++ 
b/paimon-common/src/test/java/org/apache/paimon/io/cache/CacheManagerTest.java
@@ -66,4 +66,21 @@ public class CacheManagerTest {
             }
         }
     }
+
+    @Test
+    void testOffHeapCache() throws Exception {
+        File file = new File(tempDir.toFile(), "test.off-heap");
+        assertThat(file.createNewFile()).isTrue();
+        CacheKey key = CacheKey.forPageIndex(new RandomAccessFile(file, "r"), 
0, 0);
+
+        try (CacheManager cacheManager = 
CacheManager.createOffHeap(MemorySize.ofBytes(10), 0)) {
+            MemorySegment segment =
+                    cacheManager.getPage(key, ignored -> new byte[] {1, 2, 3}, 
ignored -> {});
+
+            assertThat(segment.isOffHeap()).isTrue();
+            byte[] bytes = new byte[3];
+            segment.get(0, bytes);
+            assertThat(bytes).containsExactly(1, 2, 3);
+        }
+    }
 }

Reply via email to