>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>