>From Michael Blow <mb...@apache.org>:

Michael Blow has uploaded this change for review. ( 
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20376?usp=email )


Change subject: [NO ISSUE][HYR][STO] FileMapManager performance improvements
......................................................................

[NO ISSUE][HYR][STO] FileMapManager performance improvements

Ext-ref: MB-68501
Change-Id: I6f3a79b3b3e42abd39bc50b149b943a62349c1f8
---
M 
hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/VirtualBufferCache.java
M hyracks-fullstack/hyracks/hyracks-storage-common/pom.xml
M 
hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/FileMapManager.java
M 
hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/IFileMapManager.java
A 
hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/SynchronizedFileMapManager.java
5 files changed, 166 insertions(+), 30 deletions(-)



  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/76/20376/1

diff --git 
a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/VirtualBufferCache.java
 
b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/VirtualBufferCache.java
index c388ba2..73e6429 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/VirtualBufferCache.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/impls/VirtualBufferCache.java
@@ -42,6 +42,7 @@
 import org.apache.hyracks.storage.common.file.BufferedFileHandle;
 import org.apache.hyracks.storage.common.file.FileMapManager;
 import org.apache.hyracks.storage.common.file.IFileMapManager;
+import org.apache.hyracks.storage.common.file.SynchronizedFileMapManager;
 import org.apache.hyracks.util.JSONUtil;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -68,7 +69,7 @@

     public VirtualBufferCache(ICacheMemoryAllocator allocator, int pageSize, 
int pageBudget) {
         this.allocator = allocator;
-        this.fileMapManager = new FileMapManager();
+        this.fileMapManager = new SynchronizedFileMapManager(new 
FileMapManager());
         this.pageSize = pageSize;
         if (pageBudget == 0) {
             throw new IllegalArgumentException("Page Budget Cannot be 0");
@@ -122,20 +123,13 @@

     @Override
     public int createFile(FileReference fileRef) throws HyracksDataException {
-        synchronized (fileMapManager) {
-            return fileMapManager.registerFile(fileRef);
-        }
+        return fileMapManager.registerFile(fileRef);
     }

     @Override
     public int openFile(FileReference fileRef) throws HyracksDataException {
         try {
-            synchronized (fileMapManager) {
-                if (fileMapManager.isMapped(fileRef)) {
-                    return fileMapManager.lookupFileId(fileRef);
-                }
-                return fileMapManager.registerFile(fileRef);
-            }
+            return fileMapManager.registerFileIfAbsent(fileRef);
         } finally {
             logStats();
         }
@@ -159,17 +153,17 @@

     @Override
     public void deleteFile(FileReference fileRef) throws HyracksDataException {
-        synchronized (fileMapManager) {
-            int fileId = fileMapManager.lookupFileId(fileRef);
-            deleteFile(fileId);
-        }
+        int fileId = fileMapManager.unregisterFile(fileRef);
+        reclaimPagesFromDeletedFile(fileId);
     }

     @Override
     public void deleteFile(int fileId) throws HyracksDataException {
-        synchronized (fileMapManager) {
-            fileMapManager.unregisterFile(fileId);
-        }
+        fileMapManager.unregisterFile(fileId);
+        reclaimPagesFromDeletedFile(fileId);
+    }
+
+    private void reclaimPagesFromDeletedFile(int fileId) {
         int reclaimedPages = 0;
         for (int i = 0; i < buckets.length; i++) {
             final CacheBucket bucket = buckets[i];
@@ -243,10 +237,7 @@
             }
             if (!newPage) {
                 int fileId = BufferedFileHandle.getFileId(dpid);
-                FileReference fileRef;
-                synchronized (fileMapManager) {
-                    fileRef = fileMapManager.lookupFileName(fileId);
-                }
+                FileReference fileRef = fileMapManager.lookupFileName(fileId);
                 throw 
HyracksDataException.create(ErrorCode.PAGE_DOES_NOT_EXIST_IN_FILE,
                         BufferedFileHandle.getPageId(dpid), fileRef);
             }
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-common/pom.xml 
b/hyracks-fullstack/hyracks/hyracks-storage-common/pom.xml
index 33ec4d6..d84ef1e 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-common/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-storage-common/pom.xml
@@ -74,5 +74,9 @@
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
     </dependency>
+    <dependency>
+      <groupId>it.unimi.dsi</groupId>
+      <artifactId>fastutil-core</artifactId>
+    </dependency>
   </dependencies>
 </project>
\ No newline at end of file
diff --git 
a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/FileMapManager.java
 
b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/FileMapManager.java
index 0f2703b..5fa1e9c 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/FileMapManager.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/FileMapManager.java
@@ -18,23 +18,35 @@
  */
 package org.apache.hyracks.storage.common.file;

+import java.io.Serial;
 import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;

 import org.apache.hyracks.api.exceptions.ErrorCode;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.io.FileReference;
 import org.apache.hyracks.util.annotations.NotThreadSafe;

+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.objects.Object2IntMap;
+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
+
 @NotThreadSafe
 public class FileMapManager implements IFileMapManager {
+    @Serial
     private static final long serialVersionUID = 1L;
+    private static final int NOT_FOUND = -1;

-    private Map<Integer, FileReference> id2nameMap = new HashMap<>();
-    private Map<FileReference, Integer> name2IdMap = new HashMap<>();
+    private final Int2ObjectMap<FileReference> id2nameMap;
+    private final Object2IntMap<FileReference> name2IdMap;
     private int idCounter = 0;

+    public FileMapManager() {
+        id2nameMap = new Int2ObjectOpenHashMap<>();
+        name2IdMap = new Object2IntOpenHashMap<>();
+        name2IdMap.defaultReturnValue(NOT_FOUND);
+    }
+
     @Override
     public FileReference lookupFileName(int fileId) throws 
HyracksDataException {
         FileReference fRef = id2nameMap.get(fileId);
@@ -46,8 +58,8 @@

     @Override
     public int lookupFileId(FileReference fileRef) throws HyracksDataException 
{
-        Integer fileId = name2IdMap.get(fileRef);
-        if (fileId == null) {
+        int fileId = name2IdMap.getInt(fileRef);
+        if (fileId == NOT_FOUND) {
             throw 
HyracksDataException.create(ErrorCode.NO_MAPPING_FOR_FILENAME, fileRef);
         }
         return fileId;
@@ -69,24 +81,48 @@
         if (fileRef == null) {
             throw 
HyracksDataException.create(ErrorCode.NO_MAPPING_FOR_FILE_ID, fileId);
         }
-        name2IdMap.remove(fileRef);
+        name2IdMap.removeInt(fileRef);
         fileRef.unregister();
         return fileRef;
     }

     @Override
+    public int unregisterFile(FileReference fileRef) throws 
HyracksDataException {
+        int fileId = name2IdMap.removeInt(fileRef);
+        if (fileId == NOT_FOUND) {
+            throw 
HyracksDataException.create(ErrorCode.NO_MAPPING_FOR_FILENAME, fileRef);
+        }
+        id2nameMap.remove(fileId);
+        fileRef.unregister();
+        return fileId;
+    }
+
+    @Override
     public int registerFile(FileReference fileRef) throws HyracksDataException 
{
-        Integer existingKey = name2IdMap.get(fileRef);
-        if (existingKey != null) {
+        int existingKey = name2IdMap.getInt(fileRef);
+        if (existingKey != NOT_FOUND) {
             FileReference prevFile = id2nameMap.get(existingKey);
             throw HyracksDataException.create(ErrorCode.FILE_ALREADY_MAPPED, 
fileRef, prevFile,
                     new Date(prevFile.registrationTime()).toString());
         }
+        return registerFileSafe(fileRef);
+    }
+
+    private int registerFileSafe(FileReference fileRef) {
         int fileId = idCounter++;
+        if (idCounter == NOT_FOUND) {
+            idCounter++;
+        }
         fileRef.register();
         id2nameMap.put(fileId, fileRef);
         name2IdMap.put(fileRef, fileId);
         return fileId;
     }

+    @Override
+    public int registerFileIfAbsent(FileReference fileRef) {
+        int fileId = name2IdMap.getInt(fileRef);
+        return fileId != NOT_FOUND ? fileId : registerFileSafe(fileRef);
+    }
+
 }
diff --git 
a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/IFileMapManager.java
 
b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/IFileMapManager.java
index 9a633b3..2a098d2 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/IFileMapManager.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/IFileMapManager.java
@@ -49,4 +49,23 @@
      */
     FileReference unregisterFile(int fileId) throws HyracksDataException;

+    /**
+     * Unregister a file mapping
+     *
+     * @param fileRef
+     *            - The file reference whose mapping is to be unregistered.
+     * @throws HyracksDataException
+     *             - If the file reference is not mapped currently in this 
manager.
+     * @return the file id
+     */
+    int unregisterFile(FileReference fileRef) throws HyracksDataException;
+
+    /**
+     * Register a new file name if it is not already registered.
+     *
+     * @param fileRef
+     *            - file reference to register or lookup
+     * @return the file id
+     */
+    int registerFileIfAbsent(FileReference fileRef);
 }
diff --git 
a/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/SynchronizedFileMapManager.java
 
b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/SynchronizedFileMapManager.java
new file mode 100644
index 0000000..3d42b2a
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/file/SynchronizedFileMapManager.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.storage.common.file;
+
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.io.FileReference;
+
+public class SynchronizedFileMapManager implements IFileMapManager {
+    private final IFileMapManager delegate;
+
+    public SynchronizedFileMapManager(IFileMapManager fileMapManager) {
+        this.delegate = fileMapManager;
+    }
+
+    @Override
+    public int registerFile(FileReference fileRef) throws HyracksDataException 
{
+        synchronized (delegate) {
+            return delegate.registerFile(fileRef);
+        }
+    }
+
+    @Override
+    public int registerFileIfAbsent(FileReference fileRef) {
+        synchronized (delegate) {
+            return delegate.registerFileIfAbsent(fileRef);
+        }
+    }
+
+    @Override
+    public FileReference unregisterFile(int fileId) throws 
HyracksDataException {
+        synchronized (delegate) {
+            return delegate.unregisterFile(fileId);
+        }
+    }
+
+    @Override
+    public int unregisterFile(FileReference fileRef) throws 
HyracksDataException {
+        synchronized (delegate) {
+            return delegate.unregisterFile(fileRef);
+        }
+    }
+
+    @Override
+    public boolean isMapped(int fileId) {
+        synchronized (delegate) {
+            return delegate.isMapped(fileId);
+        }
+    }
+
+    @Override
+    public boolean isMapped(FileReference fileRef) {
+        synchronized (delegate) {
+            return delegate.isMapped(fileRef);
+        }
+    }
+
+    @Override
+    public int lookupFileId(FileReference fileRef) throws HyracksDataException 
{
+        synchronized (delegate) {
+            return delegate.lookupFileId(fileRef);
+        }
+    }
+
+    @Override
+    public FileReference lookupFileName(int fileId) throws 
HyracksDataException {
+        synchronized (delegate) {
+            return delegate.lookupFileName(fileId);
+        }
+    }
+}

--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20376?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://asterix-gerrit.ics.uci.edu/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: asterixdb
Gerrit-Branch: trinity
Gerrit-Change-Id: I6f3a79b3b3e42abd39bc50b149b943a62349c1f8
Gerrit-Change-Number: 20376
Gerrit-PatchSet: 1
Gerrit-Owner: Michael Blow <mb...@apache.org>

Reply via email to