From 7a652bef69828f31d4ff6d203f5577b53ded5e35 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Sun, 25 Aug 2024 16:04:36 +0800 Subject: [PATCH 01/48] feat: framework for memoryManagement --- .../hugegraph/memory/MemoryManager.java | 11 +++ .../memory/allocator/AbstractAllocator.java | 14 +++ .../memory/allocator/IAllocator.java | 12 +++ .../memory/arbitrator/IMemoryArbitrator.java | 5 ++ .../memory/consumer/IMemoryConsumer.java | 5 ++ .../memory/pool/AbstractMemoryPool.java | 37 ++++++++ .../hugegraph/memory/pool/IMemoryPool.java | 26 ++++++ .../memory/pool/impl/MemoryPoolStats.java | 88 +++++++++++++++++++ .../memory/pool/impl/OperatorMemoryPool.java | 5 ++ .../memory/pool/impl/RootMemoryPool.java | 31 +++++++ .../memory/pool/impl/TaskMemoryPool.java | 5 ++ .../memory/reclaimer/IMemoryReclaimer.java | 5 ++ .../static/conf/graphs/hugegraph.properties | 2 +- 13 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IAllocator.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/IMemoryConsumer.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/RootMemoryPool.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/IMemoryReclaimer.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java new file mode 100644 index 0000000000..5feba1dddf --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -0,0 +1,11 @@ +package org.apache.hugegraph.memory; + +import org.apache.hugegraph.memory.pool.IMemoryPool; +import org.apache.hugegraph.memory.pool.impl.RootMemoryPool; + +public class MemoryManager { + + private static final String ROOT_POOL_NAME = "RootQueryMemoryPool"; + private static final IMemoryPool ROOT = new RootMemoryPool(null, ROOT_POOL_NAME); + +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java new file mode 100644 index 0000000000..5046d611a6 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java @@ -0,0 +1,14 @@ +package org.apache.hugegraph.memory.allocator; + +public abstract class AbstractAllocator implements IAllocator { + + @Override + public long tryToAllocateOnHeap(long size) { + return 0; + } + + @Override + public long forceAllocateOnHeap(long size) { + return 0; + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IAllocator.java new file mode 100644 index 0000000000..4b05c576cc --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IAllocator.java @@ -0,0 +1,12 @@ +package org.apache.hugegraph.memory.allocator; + +public interface IAllocator { + + long tryToAllocateOnHeap(long size); + + long forceAllocateOnHeap(long size); + + long tryToAllocateOffHeap(long size); + + long forceAllocateOffHeap(long size); +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java new file mode 100644 index 0000000000..28aa717eb1 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java @@ -0,0 +1,5 @@ +package org.apache.hugegraph.memory.arbitrator; + +public interface IMemoryArbitrator { + +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/IMemoryConsumer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/IMemoryConsumer.java new file mode 100644 index 0000000000..9e874e65c0 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/IMemoryConsumer.java @@ -0,0 +1,5 @@ +package org.apache.hugegraph.memory.consumer; + +public interface IMemoryConsumer { + +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java new file mode 100644 index 0000000000..21602d8e2e --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -0,0 +1,37 @@ +package org.apache.hugegraph.memory.pool; + +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; + +public abstract class AbstractMemoryPool implements IMemoryPool { + private final IMemoryPool parent; + private final Set children = new CopyOnWriteArraySet<>(); + private final MemoryPoolStats stats; + + public AbstractMemoryPool(IMemoryPool parent, String memoryPoolName) { + this.parent = parent; + this.stats = new MemoryPoolStats(memoryPoolName); + } + + @Override + public MemoryPoolStats getSnapShot() { + return stats; + } + + @Override + public IMemoryPool getParentPool() { + return parent; + } + + @Override + public String getName() { + return stats.getMemoryPoolName(); + } + + @Override + public Set getChildrenPools() { + return children; + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java new file mode 100644 index 0000000000..b3db732481 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java @@ -0,0 +1,26 @@ +package org.apache.hugegraph.memory.pool; + +import java.util.Set; + +import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; + +public interface IMemoryPool { + + MemoryPoolStats getSnapShot(); + + String getName(); + + IMemoryPool getParentPool(); + + Set getChildrenPools(); + + long allocate(long bytes); + + long free(long bytes); + + long requestMemory(long bytes); + + long reclaimMemory(long bytes, long maxWaitMs); + + // visitChildren,传递方法引用 +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java new file mode 100644 index 0000000000..42674f12cb --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java @@ -0,0 +1,88 @@ +package org.apache.hugegraph.memory.pool.impl; + +public class MemoryPoolStats { + + private final String memoryPoolName; + private long usedBytes; + private long reservedBytes; + private long cumulativeBytes; + private long allocatedBytes; + + private long numShrinks; + private long numExpands; + private long numAborts; + + public MemoryPoolStats(String MemoryPoolName) { + this.memoryPoolName = MemoryPoolName; + } + + @Override + public String toString() { + return String.format("IMemoryPool-%s: {usedBytes[%d], reservedBytes[%d], " + + "cumulativeBytes[%d], allocatedBytes[%d], numShrinks[%d], " + + "numExpands[%d], numAborts[%d]}.", memoryPoolName, usedBytes, + reservedBytes, + cumulativeBytes, allocatedBytes, numShrinks, numExpands, + numAborts); + } + + public String getMemoryPoolName() { + return memoryPoolName; + } + + public long getUsedBytes() { + return usedBytes; + } + + public void setUsedBytes(long usedBytes) { + this.usedBytes = usedBytes; + } + + public long getReservedBytes() { + return reservedBytes; + } + + public void setReservedBytes(long reservedBytes) { + this.reservedBytes = reservedBytes; + } + + public long getCumulativeBytes() { + return cumulativeBytes; + } + + public void setCumulativeBytes(long cumulativeBytes) { + this.cumulativeBytes = cumulativeBytes; + } + + public long getAllocatedBytes() { + return allocatedBytes; + } + + public void setAllocatedBytes(long allocatedBytes) { + this.allocatedBytes = allocatedBytes; + } + + public long getNumShrinks() { + return numShrinks; + } + + public void setNumShrinks(long numShrinks) { + this.numShrinks = numShrinks; + } + + public long getNumExpands() { + return numExpands; + } + + public void setNumExpands(long numExpands) { + this.numExpands = numExpands; + } + + public long getNumAborts() { + return numAborts; + } + + public void setNumAborts(long numAborts) { + this.numAborts = numAborts; + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java new file mode 100644 index 0000000000..74c6640f35 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -0,0 +1,5 @@ +package org.apache.hugegraph.memory.pool.impl; + +public class OperatorMemoryPool { + +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/RootMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/RootMemoryPool.java new file mode 100644 index 0000000000..ba939a362c --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/RootMemoryPool.java @@ -0,0 +1,31 @@ +package org.apache.hugegraph.memory.pool.impl; + +import org.apache.hugegraph.memory.pool.AbstractMemoryPool; +import org.apache.hugegraph.memory.pool.IMemoryPool; + +public class RootMemoryPool extends AbstractMemoryPool { + + public RootMemoryPool(IMemoryPool parent, String name) { + super(parent, name); + } + + @Override + public long reclaimMemory(long bytes, long maxWaitMs) { + return 0; + } + + @Override + public long requestMemory(long bytes) { + return 0; + } + + @Override + public long free(long bytes) { + return 0; + } + + @Override + public long allocate(long bytes) { + return 0; + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java new file mode 100644 index 0000000000..323d8e368e --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -0,0 +1,5 @@ +package org.apache.hugegraph.memory.pool.impl; + +public class TaskMemoryPool { + +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/IMemoryReclaimer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/IMemoryReclaimer.java new file mode 100644 index 0000000000..4900921736 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/IMemoryReclaimer.java @@ -0,0 +1,5 @@ +package org.apache.hugegraph.memory.reclaimer; + +public interface IMemoryReclaimer { + +} diff --git a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties index 1a3532914b..63c41d3563 100644 --- a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties +++ b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties @@ -19,7 +19,7 @@ edge.cache_type=l2 #vertex.default_label=vertex -backend=hstore +backend=rocksdb serializer=binary store=hugegraph From ccc918b6887d8be705d7c023ea4666546891428b Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Sun, 25 Aug 2024 17:31:33 +0800 Subject: [PATCH 02/48] wip: memory pool and manager framework --- .../hugegraph/memory/MemoryManager.java | 83 +++++++++++++++++- .../memory/allocator/AbstractAllocator.java | 19 ++++- .../memory/allocator/IAllocator.java | 12 --- .../memory/allocator/IMemoryAllocator.java | 30 +++++++ .../memory/arbitrator/IMemoryArbitrator.java | 17 ++++ .../memory/arbitrator/MemoryArbitrator.java | 22 +++++ .../memory/consumer/IMemoryConsumer.java | 18 ++++ .../memory/pool/AbstractMemoryPool.java | 85 ++++++++++++++++++- .../hugegraph/memory/pool/IMemoryPool.java | 39 +++++++-- .../memory/pool/impl/MemoryPoolStats.java | 31 ++++++- .../memory/pool/impl/OperatorMemoryPool.java | 17 ++++ .../memory/pool/impl/QueryMemoryPool.java | 51 +++++++++++ .../memory/pool/impl/RootMemoryPool.java | 31 ------- .../memory/pool/impl/TaskMemoryPool.java | 17 ++++ .../memory/reclaimer/IMemoryReclaimer.java | 19 ++++- 15 files changed, 431 insertions(+), 60 deletions(-) delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IAllocator.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IMemoryAllocator.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/RootMemoryPool.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index 5feba1dddf..2cbd40ceba 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -1,11 +1,88 @@ +/* + * 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.hugegraph.memory; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.atomic.AtomicLong; + +import org.apache.hugegraph.memory.allocator.AbstractAllocator; +import org.apache.hugegraph.memory.allocator.IMemoryAllocator; +import org.apache.hugegraph.memory.arbitrator.IMemoryArbitrator; +import org.apache.hugegraph.memory.arbitrator.MemoryArbitrator; import org.apache.hugegraph.memory.pool.IMemoryPool; -import org.apache.hugegraph.memory.pool.impl.RootMemoryPool; +import org.apache.hugegraph.memory.pool.impl.QueryMemoryPool; public class MemoryManager { - private static final String ROOT_POOL_NAME = "RootQueryMemoryPool"; - private static final IMemoryPool ROOT = new RootMemoryPool(null, ROOT_POOL_NAME); + private static final String QUERY_MEMORY_POOL_NAME_PREFIX = "QueryMemoryPool"; + private static final String DELIMINATOR = "_"; + // TODO: read it from conf, current 1G + private final AtomicLong currentMemoryCapacityInBytes = new AtomicLong(1000_000_000); + private final Set queryMemoryPools = new CopyOnWriteArraySet<>(); + private final IMemoryArbitrator memoryArbitrator; + // TODO: implement different allocate strategy. + private final IMemoryAllocator memoryAllocator; + // TODO: integrated with mingzhen's monitor thread + // private final Runnable queryGCThread; + + private MemoryManager() { + this.memoryArbitrator = new MemoryArbitrator(); + this.memoryAllocator = new AbstractAllocator() { + @Override + public long tryToAllocateOffHeap(long size) { + return 0; + } + + @Override + public long forceAllocateOffHeap(long size) { + return 0; + } + }; + } + + public IMemoryPool addQueryMemoryPool() { + int count = queryMemoryPools.size(); + String poolName = + QUERY_MEMORY_POOL_NAME_PREFIX + DELIMINATOR + count + DELIMINATOR + + System.currentTimeMillis(); + IMemoryPool queryPool = new QueryMemoryPool(poolName, this); + queryMemoryPools.add(queryPool); + return queryPool; + } + + public void gcQueryMemoryPool(IMemoryPool pool) { + queryMemoryPools.remove(pool); + long reclaimedMemory = pool.getAllocatedBytes(); + pool.releaseSelf(); + currentMemoryCapacityInBytes.addAndGet(reclaimedMemory); + } + + private static class MemoryManagerHolder { + + private static final MemoryManager INSTANCE = new MemoryManager(); + + private MemoryManagerHolder() { + // empty constructor + } + } + public static MemoryManager getInstance() { + return MemoryManagerHolder.INSTANCE; + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java index 5046d611a6..411ba2993b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java @@ -1,6 +1,23 @@ +/* + * 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.hugegraph.memory.allocator; -public abstract class AbstractAllocator implements IAllocator { +public abstract class AbstractAllocator implements IMemoryAllocator { @Override public long tryToAllocateOnHeap(long size) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IAllocator.java deleted file mode 100644 index 4b05c576cc..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IAllocator.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.apache.hugegraph.memory.allocator; - -public interface IAllocator { - - long tryToAllocateOnHeap(long size); - - long forceAllocateOnHeap(long size); - - long tryToAllocateOffHeap(long size); - - long forceAllocateOffHeap(long size); -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IMemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IMemoryAllocator.java new file mode 100644 index 0000000000..4b05a6ac38 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IMemoryAllocator.java @@ -0,0 +1,30 @@ +/* + * 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.hugegraph.memory.allocator; + +// TODO(pjz): implement different memory allocate strategy. +public interface IMemoryAllocator { + + long tryToAllocateOnHeap(long size); + + long forceAllocateOnHeap(long size); + + long tryToAllocateOffHeap(long size); + + long forceAllocateOffHeap(long size); +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java index 28aa717eb1..d963503c19 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java @@ -1,3 +1,20 @@ +/* + * 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.hugegraph.memory.arbitrator; public interface IMemoryArbitrator { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java new file mode 100644 index 0000000000..7a65e14a67 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java @@ -0,0 +1,22 @@ +/* + * 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.hugegraph.memory.arbitrator; + +public class MemoryArbitrator implements IMemoryArbitrator { + +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/IMemoryConsumer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/IMemoryConsumer.java index 9e874e65c0..2ce5d80497 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/IMemoryConsumer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/IMemoryConsumer.java @@ -1,5 +1,23 @@ +/* + * 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.hugegraph.memory.consumer; +// TODO(pjz): integrated it with HG objects such as edges and vertex. public interface IMemoryConsumer { } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 21602d8e2e..7550dede87 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -1,20 +1,97 @@ +/* + * 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.hugegraph.memory.pool; import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; +import java.util.TreeSet; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; public abstract class AbstractMemoryPool implements IMemoryPool { - private final IMemoryPool parent; - private final Set children = new CopyOnWriteArraySet<>(); - private final MemoryPoolStats stats; + + private final Set children = + new TreeSet<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); + private IMemoryPool parent; + private MemoryPoolStats stats; public AbstractMemoryPool(IMemoryPool parent, String memoryPoolName) { this.parent = parent; this.stats = new MemoryPoolStats(memoryPoolName); } + @Override + public long tryToReclaimLocalMemory(long neededBytes) { + long totalReclaimedBytes = 0; + long currentNeededBytes = neededBytes; + try { + for (IMemoryPool child : this.children) { + long reclaimedMemory = child.tryToReclaimLocalMemory(currentNeededBytes); + if (reclaimedMemory > 0) { + currentNeededBytes -= reclaimedMemory; + totalReclaimedBytes += reclaimedMemory; + // Reclaim enough memory. + if (currentNeededBytes <= 0) { + break; + } + } + } + return totalReclaimedBytes; + } finally { + this.stats.setNumShrinks(this.stats.getNumShrinks() + 1); + this.stats.setAllocatedBytes( + this.stats.getAllocatedBytes() - totalReclaimedBytes); + } + } + + @Override + public void releaseSelf() { + try { + for (IMemoryPool child : this.children) { + child.releaseSelf(); + } + } finally { + // Make these objs be GCed by JVM quickly. + this.stats = null; + this.parent = null; + this.children.clear(); + } + } + + @Override + public long getMaxCapacityBytes() { + return stats.getMaxCapacity(); + } + + @Override + public long getUsedBytes() { + return stats.getUsedBytes(); + } + + @Override + public long getFreeBytes() { + return stats.getAllocatedBytes() - stats.getUsedBytes(); + } + + @Override + public long getAllocatedBytes() { + return stats.getAllocatedBytes(); + } + @Override public MemoryPoolStats getSnapShot() { return stats; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java index b3db732481..bdb8800cac 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java @@ -1,3 +1,20 @@ +/* + * 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.hugegraph.memory.pool; import java.util.Set; @@ -8,19 +25,29 @@ public interface IMemoryPool { MemoryPoolStats getSnapShot(); + long tryToReclaimLocalMemory(long neededBytes); + + long tryToAcquireMemory(long bytes); + + void releaseSelf(); + + boolean tryToDiskSpill(); + + long getAllocatedBytes(); + + long getUsedBytes(); + + long getFreeBytes(); + + long getMaxCapacityBytes(); + String getName(); IMemoryPool getParentPool(); Set getChildrenPools(); - long allocate(long bytes); - - long free(long bytes); - long requestMemory(long bytes); long reclaimMemory(long bytes, long maxWaitMs); - - // visitChildren,传递方法引用 } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java index 42674f12cb..45fdcd5026 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java @@ -1,8 +1,26 @@ +/* + * 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.hugegraph.memory.pool.impl; public class MemoryPoolStats { private final String memoryPoolName; + private long maxCapacity; private long usedBytes; private long reservedBytes; private long cumulativeBytes; @@ -18,9 +36,10 @@ public MemoryPoolStats(String MemoryPoolName) { @Override public String toString() { - return String.format("IMemoryPool-%s: {usedBytes[%d], reservedBytes[%d], " + + return String.format("IMemoryPool-%s: {maxCapacity[%d], usedBytes[%d], reservedBytes[%d]," + "cumulativeBytes[%d], allocatedBytes[%d], numShrinks[%d], " + - "numExpands[%d], numAborts[%d]}.", memoryPoolName, usedBytes, + "numExpands[%d], numAborts[%d]}.", memoryPoolName, maxCapacity, + usedBytes, reservedBytes, cumulativeBytes, allocatedBytes, numShrinks, numExpands, numAborts); @@ -85,4 +104,12 @@ public long getNumAborts() { public void setNumAborts(long numAborts) { this.numAborts = numAborts; } + + public long getMaxCapacity() { + return maxCapacity; + } + + public void setMaxCapacity(long maxCapacity) { + this.maxCapacity = maxCapacity; + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index 74c6640f35..bc0c76171d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -1,3 +1,20 @@ +/* + * 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.hugegraph.memory.pool.impl; public class OperatorMemoryPool { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java new file mode 100644 index 0000000000..4038ac6ff9 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -0,0 +1,51 @@ +/* + * 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.hugegraph.memory.pool.impl; + +import org.apache.hugegraph.memory.MemoryManager; +import org.apache.hugegraph.memory.pool.AbstractMemoryPool; + +public class QueryMemoryPool extends AbstractMemoryPool { + + private final MemoryManager memoryManager; + + public QueryMemoryPool(String poolName, MemoryManager memoryManager) { + super(null, poolName); + this.memoryManager = memoryManager; + } + + @Override + public long tryToAcquireMemory(long bytes) { + return 0; + } + + @Override + public boolean tryToDiskSpill() { + return false; + } + + @Override + public long requestMemory(long bytes) { + return 0; + } + + @Override + public long reclaimMemory(long bytes, long maxWaitMs) { + return 0; + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/RootMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/RootMemoryPool.java deleted file mode 100644 index ba939a362c..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/RootMemoryPool.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.apache.hugegraph.memory.pool.impl; - -import org.apache.hugegraph.memory.pool.AbstractMemoryPool; -import org.apache.hugegraph.memory.pool.IMemoryPool; - -public class RootMemoryPool extends AbstractMemoryPool { - - public RootMemoryPool(IMemoryPool parent, String name) { - super(parent, name); - } - - @Override - public long reclaimMemory(long bytes, long maxWaitMs) { - return 0; - } - - @Override - public long requestMemory(long bytes) { - return 0; - } - - @Override - public long free(long bytes) { - return 0; - } - - @Override - public long allocate(long bytes) { - return 0; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index 323d8e368e..ff6d62b5bf 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -1,3 +1,20 @@ +/* + * 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.hugegraph.memory.pool.impl; public class TaskMemoryPool { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/IMemoryReclaimer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/IMemoryReclaimer.java index 4900921736..0a5e2eea6b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/IMemoryReclaimer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/IMemoryReclaimer.java @@ -1,5 +1,22 @@ +/* + * 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.hugegraph.memory.reclaimer; public interface IMemoryReclaimer { - + } From b26635806299924cfb659e91a9b5634d61f8ee23 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 8 Oct 2024 21:30:38 +0800 Subject: [PATCH 03/48] wip: memory allocation --- .../hugegraph/memory/MemoryManager.java | 15 --- .../memory/allocator/IMemoryAllocator.java | 6 +- .../memory/pool/AbstractMemoryPool.java | 11 ++- .../hugegraph/memory/pool/IMemoryPool.java | 3 +- .../memory/pool/impl/OperatorMemoryPool.java | 97 ++++++++++++++++++- .../memory/pool/impl/QueryMemoryPool.java | 7 +- .../memory/pool/impl/TaskMemoryPool.java | 23 ++++- 7 files changed, 136 insertions(+), 26 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index 2cbd40ceba..4d0132a928 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -21,8 +21,6 @@ import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicLong; -import org.apache.hugegraph.memory.allocator.AbstractAllocator; -import org.apache.hugegraph.memory.allocator.IMemoryAllocator; import org.apache.hugegraph.memory.arbitrator.IMemoryArbitrator; import org.apache.hugegraph.memory.arbitrator.MemoryArbitrator; import org.apache.hugegraph.memory.pool.IMemoryPool; @@ -36,24 +34,11 @@ public class MemoryManager { private final AtomicLong currentMemoryCapacityInBytes = new AtomicLong(1000_000_000); private final Set queryMemoryPools = new CopyOnWriteArraySet<>(); private final IMemoryArbitrator memoryArbitrator; - // TODO: implement different allocate strategy. - private final IMemoryAllocator memoryAllocator; // TODO: integrated with mingzhen's monitor thread // private final Runnable queryGCThread; private MemoryManager() { this.memoryArbitrator = new MemoryArbitrator(); - this.memoryAllocator = new AbstractAllocator() { - @Override - public long tryToAllocateOffHeap(long size) { - return 0; - } - - @Override - public long forceAllocateOffHeap(long size) { - return 0; - } - }; } public IMemoryPool addQueryMemoryPool() { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IMemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IMemoryAllocator.java index 4b05a6ac38..f7e5b41cb6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IMemoryAllocator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IMemoryAllocator.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.memory.allocator; +import java.nio.ByteBuffer; + // TODO(pjz): implement different memory allocate strategy. public interface IMemoryAllocator { @@ -24,7 +26,7 @@ public interface IMemoryAllocator { long forceAllocateOnHeap(long size); - long tryToAllocateOffHeap(long size); + ByteBuffer tryToAllocateOffHeap(long size); - long forceAllocateOffHeap(long size); + ByteBuffer forceAllocateOffHeap(long size); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 7550dede87..4649f26167 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -17,6 +17,7 @@ package org.apache.hugegraph.memory.pool; +import java.nio.ByteBuffer; import java.util.Set; import java.util.TreeSet; @@ -27,7 +28,7 @@ public abstract class AbstractMemoryPool implements IMemoryPool { private final Set children = new TreeSet<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); private IMemoryPool parent; - private MemoryPoolStats stats; + protected MemoryPoolStats stats; public AbstractMemoryPool(IMemoryPool parent, String memoryPoolName) { this.parent = parent; @@ -72,6 +73,14 @@ public void releaseSelf() { } } + @Override + public ByteBuffer tryToAcquireMemory(long bytes) { + // default implement + // just record how much memory is used(update stats) + + return null; + } + @Override public long getMaxCapacityBytes() { return stats.getMaxCapacity(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java index bdb8800cac..183a334493 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java @@ -17,6 +17,7 @@ package org.apache.hugegraph.memory.pool; +import java.nio.ByteBuffer; import java.util.Set; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; @@ -27,7 +28,7 @@ public interface IMemoryPool { long tryToReclaimLocalMemory(long neededBytes); - long tryToAcquireMemory(long bytes); + ByteBuffer tryToAcquireMemory(long bytes); void releaseSelf(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index bc0c76171d..f5f46f9b75 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -17,6 +17,101 @@ package org.apache.hugegraph.memory.pool.impl; -public class OperatorMemoryPool { +import java.nio.ByteBuffer; +import org.apache.hugegraph.memory.allocator.IMemoryAllocator; +import org.apache.hugegraph.memory.pool.AbstractMemoryPool; +import org.apache.hugegraph.memory.pool.IMemoryPool; + +public class OperatorMemoryPool extends AbstractMemoryPool { + + // TODO: configurable + private static final long ALIGNMENT = 8; + private static final long MB = 1 << 20; + // TODO: implement different allocate strategy & make it configurable. + private final IMemoryAllocator memoryAllocator; + + public OperatorMemoryPool(IMemoryPool parent, String poolName, + IMemoryAllocator memoryAllocator) { + super(parent, poolName); + this.memoryAllocator = memoryAllocator; + } + + /** + * Operator need `size` bytes, operator pool will try to reserve some memory for it + */ + @Override + public ByteBuffer tryToAcquireMemory(long size) { + // TODO: 1. update statistic + + // 2. allocate memory, currently use off-heap mode. + // if you use on-heap mode, we only track memory usage here. + return memoryAllocator.tryToAllocateOffHeap(size); + } + + @Override + public boolean tryToDiskSpill() { + return false; + } + + @Override + public long requestMemory(long size) { + // 1. align size + long alignedSize = sizeAlign(size); + // 2. reserve(round) + long neededMemorySize = calculateTrueRequestingMemory(alignedSize); + if (neededMemorySize <= 0) { + return 0; + } + // 3. call father + long fatherRes = getParentPool().requestMemory(neededMemorySize); + // if allocation failed. + if (fatherRes < 0) { + // TODO: new OOM exception + throw new OutOfMemoryError(); + } + return fatherRes; + } + + private long sizeAlign(long size) { + long reminder = size % ALIGNMENT; + return reminder == 0 ? size : size + ALIGNMENT - reminder; + } + + /** + * This method should be synchronized. + */ + private synchronized long calculateTrueRequestingMemory(long size) { + // 1. check whether you need to acquire memory or not + long neededSize = size - (getFreeBytes()); + // 2. if not needed, return 0 + if (neededSize <= 0) { + return 0; + } + // 3. if needed, calculate rounded size and return it + return roundDelta(stats.getReservedBytes(), neededSize); + } + + private long roundDelta(long reservedSize, long delta) { + return quantizedSize(reservedSize + delta) - reservedSize; + } + + private long quantizedSize(long size) { + if (size < 16 * MB) { + return roundUp(size, MB); + } + if (size < 64 * MB) { + return roundUp(size, 4 * MB); + } + return roundUp(size, 8 * MB); + } + + private long roundUp(long size, long factor) { + return (size + factor - 1) / factor * factor; + } + + @Override + public long reclaimMemory(long bytes, long maxWaitMs) { + return 0; + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 4038ac6ff9..3faf1afacd 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.memory.pool.impl; +import java.nio.ByteBuffer; + import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; @@ -29,11 +31,6 @@ public QueryMemoryPool(String poolName, MemoryManager memoryManager) { this.memoryManager = memoryManager; } - @Override - public long tryToAcquireMemory(long bytes) { - return 0; - } - @Override public boolean tryToDiskSpill() { return false; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index ff6d62b5bf..e1b262fa57 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -17,6 +17,27 @@ package org.apache.hugegraph.memory.pool.impl; -public class TaskMemoryPool { +import org.apache.hugegraph.memory.pool.AbstractMemoryPool; +import org.apache.hugegraph.memory.pool.IMemoryPool; +public class TaskMemoryPool extends AbstractMemoryPool { + + public TaskMemoryPool(IMemoryPool parent, String poolName) { + super(parent, poolName); + } + + @Override + public boolean tryToDiskSpill() { + return false; + } + + @Override + public long requestMemory(long bytes) { + return 0; + } + + @Override + public long reclaimMemory(long bytes, long maxWaitMs) { + return 0; + } } From ff10c3a30e39a58f9276b82eb25f7937a34d6135 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Wed, 9 Oct 2024 15:25:16 +0800 Subject: [PATCH 04/48] wip: memory reclaim --- .../hugegraph/memory/MemoryManager.java | 47 +++++++++++++++++++ .../memory/arbitrator/IMemoryArbitrator.java | 9 ++++ .../memory/arbitrator/MemoryArbitrator.java | 30 ++++++++++++ .../memory/pool/AbstractMemoryPool.java | 9 +++- .../hugegraph/memory/pool/IMemoryPool.java | 2 - .../memory/pool/impl/MemoryPoolStats.java | 2 +- .../memory/pool/impl/OperatorMemoryPool.java | 45 ++++++++++++------ .../memory/pool/impl/QueryMemoryPool.java | 41 +++++++++++++--- .../memory/pool/impl/TaskMemoryPool.java | 14 +++--- 9 files changed, 166 insertions(+), 33 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index 4d0132a928..cfb8ae3a5c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -19,26 +19,40 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicLong; import org.apache.hugegraph.memory.arbitrator.IMemoryArbitrator; import org.apache.hugegraph.memory.arbitrator.MemoryArbitrator; import org.apache.hugegraph.memory.pool.IMemoryPool; import org.apache.hugegraph.memory.pool.impl.QueryMemoryPool; +import org.apache.hugegraph.util.ExecutorUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class MemoryManager { + private static final Logger LOGGER = LoggerFactory.getLogger(MemoryManager.class); private static final String QUERY_MEMORY_POOL_NAME_PREFIX = "QueryMemoryPool"; + private static final String ARBITRATE_MEMORY_POOL_NAME = "ArbitrateMemoryPool"; private static final String DELIMINATOR = "_"; + private static final int ARBITRATE_MEMORY_THREAD_NUM = 12; // TODO: read it from conf, current 1G private final AtomicLong currentMemoryCapacityInBytes = new AtomicLong(1000_000_000); private final Set queryMemoryPools = new CopyOnWriteArraySet<>(); private final IMemoryArbitrator memoryArbitrator; + private final ExecutorService arbitrateExecutor; // TODO: integrated with mingzhen's monitor thread // private final Runnable queryGCThread; private MemoryManager() { this.memoryArbitrator = new MemoryArbitrator(); + this.arbitrateExecutor = ExecutorUtil.newFixedThreadPool(ARBITRATE_MEMORY_THREAD_NUM, + ARBITRATE_MEMORY_POOL_NAME); } public IMemoryPool addQueryMemoryPool() { @@ -58,6 +72,39 @@ public void gcQueryMemoryPool(IMemoryPool pool) { currentMemoryCapacityInBytes.addAndGet(reclaimedMemory); } + public long triggerLocalArbitration(IMemoryPool targetPool, long neededBytes) { + Future future = + arbitrateExecutor.submit( + () -> memoryArbitrator.reclaimLocally(targetPool, neededBytes)); + try { + return future.get(IMemoryArbitrator.MAX_WAIT_TIME_FOR_LOCAL_RECLAIM, + TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + LOGGER.warn("MemoryManager: arbitration locally for {} timed out", targetPool, e); + } catch (InterruptedException | ExecutionException e) { + LOGGER.error("MemoryManager: arbitration locally for {} interrupted or failed", + targetPool, + e); + } + return 0; + } + + public long triggerGlobalArbitration(IMemoryPool requestPool, long neededBytes) { + Future future = + arbitrateExecutor.submit( + () -> memoryArbitrator.reclaimGlobally(requestPool, neededBytes)); + try { + return future.get(IMemoryArbitrator.MAX_WAIT_TIME_FOR_GLOBAL_RECLAIM, + TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + LOGGER.warn("MemoryManager: arbitration globally for {} timed out", requestPool, e); + } catch (InterruptedException | ExecutionException e) { + LOGGER.error("MemoryManager: arbitration globally for {} interrupted or failed", + requestPool, e); + } + return 0; + } + private static class MemoryManagerHolder { private static final MemoryManager INSTANCE = new MemoryManager(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java index d963503c19..bc59b30962 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java @@ -17,6 +17,15 @@ package org.apache.hugegraph.memory.arbitrator; +import org.apache.hugegraph.memory.pool.IMemoryPool; + public interface IMemoryArbitrator { + long MAX_WAIT_TIME_FOR_LOCAL_RECLAIM = 1000; + + long MAX_WAIT_TIME_FOR_GLOBAL_RECLAIM = 5000; + + long reclaimLocally(IMemoryPool queryPool, long neededBytes); + + long reclaimGlobally(IMemoryPool queryPool, long neededBytes); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java index 7a65e14a67..17280d758c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java @@ -17,6 +17,36 @@ package org.apache.hugegraph.memory.arbitrator; +import org.apache.hugegraph.memory.pool.IMemoryPool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class MemoryArbitrator implements IMemoryArbitrator { + private static final Logger LOGGER = LoggerFactory.getLogger(MemoryArbitrator.class); + + @Override + public long reclaimLocally(IMemoryPool queryPool, long neededBytes) { + long startTime = System.currentTimeMillis(); + long res = queryPool.tryToReclaimLocalMemory(neededBytes); + LOGGER.info("[{}] reclaim local memory: {} bytes, took {} ms", + Thread.currentThread().getName(), + res, + System.currentTimeMillis() - startTime); + return res; + } + + @Override + public long reclaimGlobally(IMemoryPool queryPool, long neededBytes) { + long startTime = System.currentTimeMillis(); + // TODO + // 1. select the query task that uses the most memory + // 2. suspend that task + // 3. apply disk spill to that task + LOGGER.info("[{}] reclaim global memory: {} bytes, took {} ms", + Thread.currentThread().getName(), + 0, + System.currentTimeMillis() - startTime); + return 0; + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 4649f26167..c1513aff51 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -75,9 +75,9 @@ public void releaseSelf() { @Override public ByteBuffer tryToAcquireMemory(long bytes) { - // default implement // just record how much memory is used(update stats) - + stats.setUsedBytes(stats.getUsedBytes() + bytes); + stats.setCumulativeBytes(stats.getCumulativeBytes() + bytes); return null; } @@ -120,4 +120,9 @@ public String getName() { public Set getChildrenPools() { return children; } + + @Override + public String toString() { + return getSnapShot().toString(); + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java index 183a334493..aa9d94f610 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java @@ -49,6 +49,4 @@ public interface IMemoryPool { Set getChildrenPools(); long requestMemory(long bytes); - - long reclaimMemory(long bytes, long maxWaitMs); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java index 45fdcd5026..d7696e5942 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java @@ -36,7 +36,7 @@ public MemoryPoolStats(String MemoryPoolName) { @Override public String toString() { - return String.format("IMemoryPool-%s: {maxCapacity[%d], usedBytes[%d], reservedBytes[%d]," + + return String.format("MemoryPool-%s: {maxCapacity[%d], usedBytes[%d], reservedBytes[%d]," + "cumulativeBytes[%d], allocatedBytes[%d], numShrinks[%d], " + "numExpands[%d], numAborts[%d]}.", memoryPoolName, maxCapacity, usedBytes, diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index f5f46f9b75..e98abea754 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -35,6 +35,28 @@ public OperatorMemoryPool(IMemoryPool parent, String poolName, IMemoryAllocator memoryAllocator) { super(parent, poolName); this.memoryAllocator = memoryAllocator; + // TODO: this.stats.setMaxCapacity(); + } + + @Override + public boolean tryToDiskSpill() { + return false; + } + + @Override + public long tryToReclaimLocalMemory(long neededBytes) { + // 1. try to reclaim self free memory + long reclaimableBytes = getFreeBytes(); + // try its best to reclaim memory + if (reclaimableBytes <= neededBytes) { + // 2. update stats + stats.setAllocatedBytes(stats.getUsedBytes()); + stats.setReservedBytes(stats.getUsedBytes()); + return reclaimableBytes; + } + stats.setAllocatedBytes(stats.getAllocatedBytes() - neededBytes); + stats.setReservedBytes(stats.getReservedBytes() - neededBytes); + return neededBytes; } /** @@ -42,34 +64,32 @@ public OperatorMemoryPool(IMemoryPool parent, String poolName, */ @Override public ByteBuffer tryToAcquireMemory(long size) { - // TODO: 1. update statistic - + // 1. update statistic + super.tryToAcquireMemory(size); // 2. allocate memory, currently use off-heap mode. // if you use on-heap mode, we only track memory usage here. return memoryAllocator.tryToAllocateOffHeap(size); } - @Override - public boolean tryToDiskSpill() { - return false; - } - @Override public long requestMemory(long size) { + // TODO: check max capacity // 1. align size long alignedSize = sizeAlign(size); // 2. reserve(round) - long neededMemorySize = calculateTrueRequestingMemory(alignedSize); + long neededMemorySize = calculateReserveMemoryDelta(alignedSize); if (neededMemorySize <= 0) { return 0; } // 3. call father long fatherRes = getParentPool().requestMemory(neededMemorySize); - // if allocation failed. if (fatherRes < 0) { // TODO: new OOM exception throw new OutOfMemoryError(); } + // 4. update stats + stats.setReservedBytes(stats.getReservedBytes() + neededMemorySize); + stats.setAllocatedBytes(stats.getAllocatedBytes() + neededMemorySize); return fatherRes; } @@ -81,7 +101,7 @@ private long sizeAlign(long size) { /** * This method should be synchronized. */ - private synchronized long calculateTrueRequestingMemory(long size) { + private synchronized long calculateReserveMemoryDelta(long size) { // 1. check whether you need to acquire memory or not long neededSize = size - (getFreeBytes()); // 2. if not needed, return 0 @@ -109,9 +129,4 @@ private long quantizedSize(long size) { private long roundUp(long size, long factor) { return (size + factor - 1) / factor * factor; } - - @Override - public long reclaimMemory(long bytes, long maxWaitMs) { - return 0; - } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 3faf1afacd..428b59096b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -17,8 +17,6 @@ package org.apache.hugegraph.memory.pool.impl; -import java.nio.ByteBuffer; - import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; @@ -29,6 +27,7 @@ public class QueryMemoryPool extends AbstractMemoryPool { public QueryMemoryPool(String poolName, MemoryManager memoryManager) { super(null, poolName); this.memoryManager = memoryManager; + // TODO: this.stats.setMaxCapacity(); } @Override @@ -38,11 +37,39 @@ public boolean tryToDiskSpill() { @Override public long requestMemory(long bytes) { - return 0; + // 1. check whether self capacity is enough + if (getMaxCapacityBytes() - stats.getAllocatedBytes() < bytes) { + // 2. if not, call manager to invoke arbitrate locally + long reclaimedBytes = memoryManager.triggerLocalArbitration(this, bytes); + // 3. if arbitrate successes, update stats and return success + if (reclaimedBytes - bytes >= 0) { + // here we don't update capacity, because memory is reclaimed from queryPool itself. + stats.setReservedBytes(stats.getReservedBytes() + bytes); + stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); + return bytes; + } else { + // 4. if still not enough, try to reclaim globally + long globalReclaimedBytes = memoryManager.triggerGlobalArbitration(this, + bytes - + reclaimedBytes); + reclaimedBytes += globalReclaimedBytes; + // 5. if memory is enough, update stats and return success + if (reclaimedBytes - bytes >= 0) { + // add capacity + stats.setMaxCapacity(stats.getMaxCapacity() + globalReclaimedBytes); + stats.setReservedBytes(stats.getReservedBytes() + bytes); + stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); + return bytes; + } + } + // 6. if arbitrate fails, return -1, indicating that request failed. + return -1; + } else { + // 7. if capacity is enough, return success + stats.setReservedBytes(stats.getReservedBytes() + bytes); + stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); + return bytes; + } } - @Override - public long reclaimMemory(long bytes, long maxWaitMs) { - return 0; - } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index e1b262fa57..f32c2118c5 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -24,6 +24,7 @@ public class TaskMemoryPool extends AbstractMemoryPool { public TaskMemoryPool(IMemoryPool parent, String poolName) { super(parent, poolName); + // TODO: this.stats.setMaxCapacity(); } @Override @@ -33,11 +34,12 @@ public boolean tryToDiskSpill() { @Override public long requestMemory(long bytes) { - return 0; - } - - @Override - public long reclaimMemory(long bytes, long maxWaitMs) { - return 0; + // TODO: check max capacity + long parentRes = getParentPool().requestMemory(bytes); + if (parentRes > 0) { + stats.setReservedBytes(stats.getReservedBytes() + parentRes); + stats.setAllocatedBytes(stats.getAllocatedBytes() + parentRes); + } + return parentRes; } } From 26b0cfe08367c6bca4360a5f38c0905e98d9417d Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Wed, 9 Oct 2024 15:29:14 +0800 Subject: [PATCH 05/48] rename class --- .../hugegraph/memory/MemoryManager.java | 24 ++++----- .../memory/allocator/AbstractAllocator.java | 2 +- ...oryAllocator.java => MemoryAllocator.java} | 2 +- .../memory/arbitrator/IMemoryArbitrator.java | 31 ----------- .../memory/arbitrator/MemoryArbitrator.java | 35 +++---------- .../arbitrator/MemoryArbitratorImpl.java | 52 +++++++++++++++++++ ...emoryConsumer.java => MemoryConsumer.java} | 2 +- .../memory/pool/AbstractMemoryPool.java | 16 +++--- .../{IMemoryPool.java => MemoryPool.java} | 6 +-- .../memory/pool/impl/OperatorMemoryPool.java | 10 ++-- .../memory/pool/impl/TaskMemoryPool.java | 4 +- ...oryReclaimer.java => MemoryReclaimer.java} | 2 +- 12 files changed, 93 insertions(+), 93 deletions(-) rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/{IMemoryAllocator.java => MemoryAllocator.java} (96%) delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/{IMemoryConsumer.java => MemoryConsumer.java} (96%) rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/{IMemoryPool.java => MemoryPool.java} (92%) rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/{IMemoryReclaimer.java => MemoryReclaimer.java} (95%) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index cfb8ae3a5c..3ca1aecdfd 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -26,9 +26,9 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicLong; -import org.apache.hugegraph.memory.arbitrator.IMemoryArbitrator; import org.apache.hugegraph.memory.arbitrator.MemoryArbitrator; -import org.apache.hugegraph.memory.pool.IMemoryPool; +import org.apache.hugegraph.memory.arbitrator.MemoryArbitratorImpl; +import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.pool.impl.QueryMemoryPool; import org.apache.hugegraph.util.ExecutorUtil; import org.slf4j.Logger; @@ -43,41 +43,41 @@ public class MemoryManager { private static final int ARBITRATE_MEMORY_THREAD_NUM = 12; // TODO: read it from conf, current 1G private final AtomicLong currentMemoryCapacityInBytes = new AtomicLong(1000_000_000); - private final Set queryMemoryPools = new CopyOnWriteArraySet<>(); - private final IMemoryArbitrator memoryArbitrator; + private final Set queryMemoryPools = new CopyOnWriteArraySet<>(); + private final MemoryArbitrator memoryArbitrator; private final ExecutorService arbitrateExecutor; // TODO: integrated with mingzhen's monitor thread // private final Runnable queryGCThread; private MemoryManager() { - this.memoryArbitrator = new MemoryArbitrator(); + this.memoryArbitrator = new MemoryArbitratorImpl(); this.arbitrateExecutor = ExecutorUtil.newFixedThreadPool(ARBITRATE_MEMORY_THREAD_NUM, ARBITRATE_MEMORY_POOL_NAME); } - public IMemoryPool addQueryMemoryPool() { + public MemoryPool addQueryMemoryPool() { int count = queryMemoryPools.size(); String poolName = QUERY_MEMORY_POOL_NAME_PREFIX + DELIMINATOR + count + DELIMINATOR + System.currentTimeMillis(); - IMemoryPool queryPool = new QueryMemoryPool(poolName, this); + MemoryPool queryPool = new QueryMemoryPool(poolName, this); queryMemoryPools.add(queryPool); return queryPool; } - public void gcQueryMemoryPool(IMemoryPool pool) { + public void gcQueryMemoryPool(MemoryPool pool) { queryMemoryPools.remove(pool); long reclaimedMemory = pool.getAllocatedBytes(); pool.releaseSelf(); currentMemoryCapacityInBytes.addAndGet(reclaimedMemory); } - public long triggerLocalArbitration(IMemoryPool targetPool, long neededBytes) { + public long triggerLocalArbitration(MemoryPool targetPool, long neededBytes) { Future future = arbitrateExecutor.submit( () -> memoryArbitrator.reclaimLocally(targetPool, neededBytes)); try { - return future.get(IMemoryArbitrator.MAX_WAIT_TIME_FOR_LOCAL_RECLAIM, + return future.get(MemoryArbitrator.MAX_WAIT_TIME_FOR_LOCAL_RECLAIM, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { LOGGER.warn("MemoryManager: arbitration locally for {} timed out", targetPool, e); @@ -89,12 +89,12 @@ public long triggerLocalArbitration(IMemoryPool targetPool, long neededBytes) { return 0; } - public long triggerGlobalArbitration(IMemoryPool requestPool, long neededBytes) { + public long triggerGlobalArbitration(MemoryPool requestPool, long neededBytes) { Future future = arbitrateExecutor.submit( () -> memoryArbitrator.reclaimGlobally(requestPool, neededBytes)); try { - return future.get(IMemoryArbitrator.MAX_WAIT_TIME_FOR_GLOBAL_RECLAIM, + return future.get(MemoryArbitrator.MAX_WAIT_TIME_FOR_GLOBAL_RECLAIM, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { LOGGER.warn("MemoryManager: arbitration globally for {} timed out", requestPool, e); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java index 411ba2993b..18ef0e6d91 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java @@ -17,7 +17,7 @@ package org.apache.hugegraph.memory.allocator; -public abstract class AbstractAllocator implements IMemoryAllocator { +public abstract class AbstractAllocator implements MemoryAllocator { @Override public long tryToAllocateOnHeap(long size) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IMemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java similarity index 96% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IMemoryAllocator.java rename to hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java index f7e5b41cb6..b654501778 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/IMemoryAllocator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java @@ -20,7 +20,7 @@ import java.nio.ByteBuffer; // TODO(pjz): implement different memory allocate strategy. -public interface IMemoryAllocator { +public interface MemoryAllocator { long tryToAllocateOnHeap(long size); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java deleted file mode 100644 index bc59b30962..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/IMemoryArbitrator.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.hugegraph.memory.arbitrator; - -import org.apache.hugegraph.memory.pool.IMemoryPool; - -public interface IMemoryArbitrator { - - long MAX_WAIT_TIME_FOR_LOCAL_RECLAIM = 1000; - - long MAX_WAIT_TIME_FOR_GLOBAL_RECLAIM = 5000; - - long reclaimLocally(IMemoryPool queryPool, long neededBytes); - - long reclaimGlobally(IMemoryPool queryPool, long neededBytes); -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java index 17280d758c..45a43799e0 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java @@ -17,36 +17,15 @@ package org.apache.hugegraph.memory.arbitrator; -import org.apache.hugegraph.memory.pool.IMemoryPool; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.hugegraph.memory.pool.MemoryPool; -public class MemoryArbitrator implements IMemoryArbitrator { +public interface MemoryArbitrator { - private static final Logger LOGGER = LoggerFactory.getLogger(MemoryArbitrator.class); + long MAX_WAIT_TIME_FOR_LOCAL_RECLAIM = 1000; - @Override - public long reclaimLocally(IMemoryPool queryPool, long neededBytes) { - long startTime = System.currentTimeMillis(); - long res = queryPool.tryToReclaimLocalMemory(neededBytes); - LOGGER.info("[{}] reclaim local memory: {} bytes, took {} ms", - Thread.currentThread().getName(), - res, - System.currentTimeMillis() - startTime); - return res; - } + long MAX_WAIT_TIME_FOR_GLOBAL_RECLAIM = 5000; - @Override - public long reclaimGlobally(IMemoryPool queryPool, long neededBytes) { - long startTime = System.currentTimeMillis(); - // TODO - // 1. select the query task that uses the most memory - // 2. suspend that task - // 3. apply disk spill to that task - LOGGER.info("[{}] reclaim global memory: {} bytes, took {} ms", - Thread.currentThread().getName(), - 0, - System.currentTimeMillis() - startTime); - return 0; - } + long reclaimLocally(MemoryPool queryPool, long neededBytes); + + long reclaimGlobally(MemoryPool queryPool, long neededBytes); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java new file mode 100644 index 0000000000..1fda892e1f --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java @@ -0,0 +1,52 @@ +/* + * 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.hugegraph.memory.arbitrator; + +import org.apache.hugegraph.memory.pool.MemoryPool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MemoryArbitratorImpl implements MemoryArbitrator { + + private static final Logger LOGGER = LoggerFactory.getLogger(MemoryArbitratorImpl.class); + + @Override + public long reclaimLocally(MemoryPool queryPool, long neededBytes) { + long startTime = System.currentTimeMillis(); + long res = queryPool.tryToReclaimLocalMemory(neededBytes); + LOGGER.info("[{}] reclaim local memory: {} bytes, took {} ms", + Thread.currentThread().getName(), + res, + System.currentTimeMillis() - startTime); + return res; + } + + @Override + public long reclaimGlobally(MemoryPool queryPool, long neededBytes) { + long startTime = System.currentTimeMillis(); + // TODO + // 1. select the query task that uses the most memory + // 2. suspend that task + // 3. apply disk spill to that task + LOGGER.info("[{}] reclaim global memory: {} bytes, took {} ms", + Thread.currentThread().getName(), + 0, + System.currentTimeMillis() - startTime); + return 0; + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/IMemoryConsumer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java similarity index 96% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/IMemoryConsumer.java rename to hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java index 2ce5d80497..ca936c7754 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/IMemoryConsumer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java @@ -18,6 +18,6 @@ package org.apache.hugegraph.memory.consumer; // TODO(pjz): integrated it with HG objects such as edges and vertex. -public interface IMemoryConsumer { +public interface MemoryConsumer { } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index c1513aff51..f76c06170c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -23,14 +23,14 @@ import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; -public abstract class AbstractMemoryPool implements IMemoryPool { +public abstract class AbstractMemoryPool implements MemoryPool { - private final Set children = + private final Set children = new TreeSet<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); - private IMemoryPool parent; + private MemoryPool parent; protected MemoryPoolStats stats; - public AbstractMemoryPool(IMemoryPool parent, String memoryPoolName) { + public AbstractMemoryPool(MemoryPool parent, String memoryPoolName) { this.parent = parent; this.stats = new MemoryPoolStats(memoryPoolName); } @@ -40,7 +40,7 @@ public long tryToReclaimLocalMemory(long neededBytes) { long totalReclaimedBytes = 0; long currentNeededBytes = neededBytes; try { - for (IMemoryPool child : this.children) { + for (MemoryPool child : this.children) { long reclaimedMemory = child.tryToReclaimLocalMemory(currentNeededBytes); if (reclaimedMemory > 0) { currentNeededBytes -= reclaimedMemory; @@ -62,7 +62,7 @@ public long tryToReclaimLocalMemory(long neededBytes) { @Override public void releaseSelf() { try { - for (IMemoryPool child : this.children) { + for (MemoryPool child : this.children) { child.releaseSelf(); } } finally { @@ -107,7 +107,7 @@ public MemoryPoolStats getSnapShot() { } @Override - public IMemoryPool getParentPool() { + public MemoryPool getParentPool() { return parent; } @@ -117,7 +117,7 @@ public String getName() { } @Override - public Set getChildrenPools() { + public Set getChildrenPools() { return children; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java similarity index 92% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java rename to hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index aa9d94f610..c2638beeea 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/IMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -22,7 +22,7 @@ import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; -public interface IMemoryPool { +public interface MemoryPool { MemoryPoolStats getSnapShot(); @@ -44,9 +44,9 @@ public interface IMemoryPool { String getName(); - IMemoryPool getParentPool(); + MemoryPool getParentPool(); - Set getChildrenPools(); + Set getChildrenPools(); long requestMemory(long bytes); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index e98abea754..0408b0c232 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -19,9 +19,9 @@ import java.nio.ByteBuffer; -import org.apache.hugegraph.memory.allocator.IMemoryAllocator; +import org.apache.hugegraph.memory.allocator.MemoryAllocator; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; -import org.apache.hugegraph.memory.pool.IMemoryPool; +import org.apache.hugegraph.memory.pool.MemoryPool; public class OperatorMemoryPool extends AbstractMemoryPool { @@ -29,10 +29,10 @@ public class OperatorMemoryPool extends AbstractMemoryPool { private static final long ALIGNMENT = 8; private static final long MB = 1 << 20; // TODO: implement different allocate strategy & make it configurable. - private final IMemoryAllocator memoryAllocator; + private final MemoryAllocator memoryAllocator; - public OperatorMemoryPool(IMemoryPool parent, String poolName, - IMemoryAllocator memoryAllocator) { + public OperatorMemoryPool(MemoryPool parent, String poolName, + MemoryAllocator memoryAllocator) { super(parent, poolName); this.memoryAllocator = memoryAllocator; // TODO: this.stats.setMaxCapacity(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index f32c2118c5..d3d4de0345 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -18,11 +18,11 @@ package org.apache.hugegraph.memory.pool.impl; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; -import org.apache.hugegraph.memory.pool.IMemoryPool; +import org.apache.hugegraph.memory.pool.MemoryPool; public class TaskMemoryPool extends AbstractMemoryPool { - public TaskMemoryPool(IMemoryPool parent, String poolName) { + public TaskMemoryPool(MemoryPool parent, String poolName) { super(parent, poolName); // TODO: this.stats.setMaxCapacity(); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/IMemoryReclaimer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/MemoryReclaimer.java similarity index 95% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/IMemoryReclaimer.java rename to hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/MemoryReclaimer.java index 0a5e2eea6b..cf92c91057 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/IMemoryReclaimer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/MemoryReclaimer.java @@ -17,6 +17,6 @@ package org.apache.hugegraph.memory.reclaimer; -public interface IMemoryReclaimer { +public interface MemoryReclaimer { } From f6aeacecfa9a0b82b58cbfa49682fded8135b3a2 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Wed, 9 Oct 2024 15:30:20 +0800 Subject: [PATCH 06/48] fix review --- .../memory/pool/impl/MemoryPoolStats.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java index d7696e5942..33286963f5 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java @@ -46,11 +46,11 @@ public String toString() { } public String getMemoryPoolName() { - return memoryPoolName; + return this.memoryPoolName; } public long getUsedBytes() { - return usedBytes; + return this.usedBytes; } public void setUsedBytes(long usedBytes) { @@ -58,7 +58,7 @@ public void setUsedBytes(long usedBytes) { } public long getReservedBytes() { - return reservedBytes; + return this.reservedBytes; } public void setReservedBytes(long reservedBytes) { @@ -66,7 +66,7 @@ public void setReservedBytes(long reservedBytes) { } public long getCumulativeBytes() { - return cumulativeBytes; + return this.cumulativeBytes; } public void setCumulativeBytes(long cumulativeBytes) { @@ -74,7 +74,7 @@ public void setCumulativeBytes(long cumulativeBytes) { } public long getAllocatedBytes() { - return allocatedBytes; + return this.allocatedBytes; } public void setAllocatedBytes(long allocatedBytes) { @@ -82,7 +82,7 @@ public void setAllocatedBytes(long allocatedBytes) { } public long getNumShrinks() { - return numShrinks; + return this.numShrinks; } public void setNumShrinks(long numShrinks) { @@ -90,7 +90,7 @@ public void setNumShrinks(long numShrinks) { } public long getNumExpands() { - return numExpands; + return this.numExpands; } public void setNumExpands(long numExpands) { @@ -98,7 +98,7 @@ public void setNumExpands(long numExpands) { } public long getNumAborts() { - return numAborts; + return this.numAborts; } public void setNumAborts(long numAborts) { @@ -106,7 +106,7 @@ public void setNumAborts(long numAborts) { } public long getMaxCapacity() { - return maxCapacity; + return this.maxCapacity; } public void setMaxCapacity(long maxCapacity) { From 72e5bf3fa6cf6c1ed90b04b4a2fd0306f7786181 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Wed, 9 Oct 2024 15:32:02 +0800 Subject: [PATCH 07/48] remove useless allocator --- .../memory/allocator/AbstractAllocator.java | 31 ------------------- .../memory/allocator/MemoryAllocator.java | 4 --- 2 files changed, 35 deletions(-) delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java deleted file mode 100644 index 18ef0e6d91..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/AbstractAllocator.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.hugegraph.memory.allocator; - -public abstract class AbstractAllocator implements MemoryAllocator { - - @Override - public long tryToAllocateOnHeap(long size) { - return 0; - } - - @Override - public long forceAllocateOnHeap(long size) { - return 0; - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java index b654501778..4a5857d03d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java @@ -22,10 +22,6 @@ // TODO(pjz): implement different memory allocate strategy. public interface MemoryAllocator { - long tryToAllocateOnHeap(long size); - - long forceAllocateOnHeap(long size); - ByteBuffer tryToAllocateOffHeap(long size); ByteBuffer forceAllocateOffHeap(long size); From 48f48171416ffcc1be538f1809830b5ad8a451df Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Thu, 10 Oct 2024 14:23:18 +0800 Subject: [PATCH 08/48] netty allocator --- .../hugegraph/memory/MemoryManager.java | 7 ++- .../memory/allocator/MemoryAllocator.java | 6 +-- .../allocator/NettyMemoryAllocator.java | 45 +++++++++++++++++++ .../memory/pool/AbstractMemoryPool.java | 32 ++++++++++++- .../hugegraph/memory/pool/MemoryPool.java | 6 ++- .../memory/pool/impl/OperatorMemoryPool.java | 12 +++-- .../memory/pool/impl/QueryMemoryPool.java | 7 +-- .../memory/pool/impl/TaskMemoryPool.java | 5 --- 8 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index 3ca1aecdfd..b778a2b16c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -30,6 +30,7 @@ import org.apache.hugegraph.memory.arbitrator.MemoryArbitratorImpl; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.pool.impl.QueryMemoryPool; +import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.ExecutorUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,7 +43,9 @@ public class MemoryManager { private static final String DELIMINATOR = "_"; private static final int ARBITRATE_MEMORY_THREAD_NUM = 12; // TODO: read it from conf, current 1G - private final AtomicLong currentMemoryCapacityInBytes = new AtomicLong(1000_000_000); + public static final long MAX_MEMORY_CAPACITY_IN_BYTES = Bytes.GB; + private final AtomicLong currentMemoryCapacityInBytes = + new AtomicLong(MAX_MEMORY_CAPACITY_IN_BYTES); private final Set queryMemoryPools = new CopyOnWriteArraySet<>(); private final MemoryArbitrator memoryArbitrator; private final ExecutorService arbitrateExecutor; @@ -54,7 +57,7 @@ private MemoryManager() { this.arbitrateExecutor = ExecutorUtil.newFixedThreadPool(ARBITRATE_MEMORY_THREAD_NUM, ARBITRATE_MEMORY_POOL_NAME); } - + public MemoryPool addQueryMemoryPool() { int count = queryMemoryPools.size(); String poolName = diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java index 4a5857d03d..43da0e5c2a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java @@ -17,12 +17,10 @@ package org.apache.hugegraph.memory.allocator; -import java.nio.ByteBuffer; - // TODO(pjz): implement different memory allocate strategy. public interface MemoryAllocator { - ByteBuffer tryToAllocateOffHeap(long size); + Object tryToAllocateOffHeap(long size); - ByteBuffer forceAllocateOffHeap(long size); + Object forceAllocateOffHeap(long size); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java new file mode 100644 index 0000000000..b5c2662d66 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java @@ -0,0 +1,45 @@ +/* + * 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.hugegraph.memory.allocator; + +import org.apache.hugegraph.memory.MemoryManager; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.PooledByteBufAllocator; + +/** + * This class makes fully use of Netty's efficient memory management strategy. + */ +public class NettyMemoryAllocator implements MemoryAllocator { + + private final PooledByteBufAllocator offHeapAllocator = PooledByteBufAllocator.DEFAULT; + + @Override + public ByteBuf forceAllocateOffHeap(long size) { + return offHeapAllocator.directBuffer((int) size); + } + + @Override + public ByteBuf tryToAllocateOffHeap(long size) { + if (offHeapAllocator.metric().usedDirectMemory() + size < + MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES) { + return offHeapAllocator.directBuffer((int) size); + } + return null; + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index f76c06170c..a4bbe93daf 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -22,9 +22,12 @@ import java.util.TreeSet; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class AbstractMemoryPool implements MemoryPool { + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractMemoryPool.class); private final Set children = new TreeSet<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); private MemoryPool parent; @@ -59,6 +62,33 @@ public long tryToReclaimLocalMemory(long neededBytes) { } } + @Override + public boolean tryToDiskSpill() { + // 1. for every child, invoke disk spill + boolean res = true; + try { + for (MemoryPool child : this.children) { + res &= child.tryToDiskSpill(); + } + return res; + } catch (Exception e) { + LOGGER.error("Failed to try to disk spill", e); + return false; + } + // TODO: for upper caller, if spill failed, apply rollback + } + + /** + * called when one task is successfully executed and exited. + */ + @Override + public void gcChildPool(MemoryPool child) { + // 1. reclaim child's memory and update stats + stats.setReservedBytes(stats.getReservedBytes() - child.getSnapShot().getReservedBytes()); + // 2. release child + child.releaseSelf(); + } + @Override public void releaseSelf() { try { @@ -74,7 +104,7 @@ public void releaseSelf() { } @Override - public ByteBuffer tryToAcquireMemory(long bytes) { + public Object tryToAcquireMemory(long bytes) { // just record how much memory is used(update stats) stats.setUsedBytes(stats.getUsedBytes() + bytes); stats.setCumulativeBytes(stats.getCumulativeBytes() + bytes); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index c2638beeea..3592d851fa 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -28,11 +28,13 @@ public interface MemoryPool { long tryToReclaimLocalMemory(long neededBytes); - ByteBuffer tryToAcquireMemory(long bytes); + Object tryToAcquireMemory(long bytes); void releaseSelf(); - boolean tryToDiskSpill(); + void gcChildPool(MemoryPool child); + + boolean tryToDiskSpill() throws Exception; long getAllocatedBytes(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index 0408b0c232..3eeddf4acf 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -17,8 +17,6 @@ package org.apache.hugegraph.memory.pool.impl; -import java.nio.ByteBuffer; - import org.apache.hugegraph.memory.allocator.MemoryAllocator; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; import org.apache.hugegraph.memory.pool.MemoryPool; @@ -43,6 +41,12 @@ public boolean tryToDiskSpill() { return false; } + @Override + public void releaseSelf() { + super.releaseSelf(); + // TODO: release memory consumer, release byte buffer. + } + @Override public long tryToReclaimLocalMemory(long neededBytes) { // 1. try to reclaim self free memory @@ -63,7 +67,7 @@ public long tryToReclaimLocalMemory(long neededBytes) { * Operator need `size` bytes, operator pool will try to reserve some memory for it */ @Override - public ByteBuffer tryToAcquireMemory(long size) { + public Object tryToAcquireMemory(long size) { // 1. update statistic super.tryToAcquireMemory(size); // 2. allocate memory, currently use off-heap mode. @@ -85,11 +89,13 @@ public long requestMemory(long size) { long fatherRes = getParentPool().requestMemory(neededMemorySize); if (fatherRes < 0) { // TODO: new OOM exception + stats.setNumAborts(stats.getNumAborts() + 1); throw new OutOfMemoryError(); } // 4. update stats stats.setReservedBytes(stats.getReservedBytes() + neededMemorySize); stats.setAllocatedBytes(stats.getAllocatedBytes() + neededMemorySize); + stats.setNumExpands(stats.getNumExpands() + 1); return fatherRes; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 428b59096b..be1ce8dda6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -30,11 +30,6 @@ public QueryMemoryPool(String poolName, MemoryManager memoryManager) { // TODO: this.stats.setMaxCapacity(); } - @Override - public boolean tryToDiskSpill() { - return false; - } - @Override public long requestMemory(long bytes) { // 1. check whether self capacity is enough @@ -46,6 +41,7 @@ public long requestMemory(long bytes) { // here we don't update capacity, because memory is reclaimed from queryPool itself. stats.setReservedBytes(stats.getReservedBytes() + bytes); stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); + stats.setNumExpands(stats.getNumExpands() + 1); return bytes; } else { // 4. if still not enough, try to reclaim globally @@ -59,6 +55,7 @@ public long requestMemory(long bytes) { stats.setMaxCapacity(stats.getMaxCapacity() + globalReclaimedBytes); stats.setReservedBytes(stats.getReservedBytes() + bytes); stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); + stats.setNumExpands(stats.getNumExpands() + 1); return bytes; } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index d3d4de0345..439525aebf 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -27,11 +27,6 @@ public TaskMemoryPool(MemoryPool parent, String poolName) { // TODO: this.stats.setMaxCapacity(); } - @Override - public boolean tryToDiskSpill() { - return false; - } - @Override public long requestMemory(long bytes) { // TODO: check max capacity From d906d04b14cc6bd89b07a434ddf72e04eb4be194 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Sun, 13 Oct 2024 20:09:28 +0800 Subject: [PATCH 09/48] revert config.properties --- .../src/assembly/static/conf/graphs/hugegraph.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties index 63c41d3563..1a3532914b 100644 --- a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties +++ b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties @@ -19,7 +19,7 @@ edge.cache_type=l2 #vertex.default_label=vertex -backend=rocksdb +backend=hstore serializer=binary store=hugegraph From b308be098dbc6e4d85a4df58620375cb730cb3ba Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 22 Oct 2024 22:52:09 +0800 Subject: [PATCH 10/48] fix and improvement for allocation and deallocation --- .../hugegraph/memory/MemoryManager.java | 39 ++++++++- .../memory/allocator/MemoryAllocator.java | 7 +- .../allocator/NettyMemoryAllocator.java | 17 +++- .../allocator/OnHeapMemoryStrategy.java | 54 ++++++++++++ .../memory/pool/AbstractMemoryPool.java | 52 ++++++------ .../hugegraph/memory/pool/MemoryPool.java | 5 +- .../memory/pool/impl/MemoryPoolStats.java | 12 +-- .../memory/pool/impl/OperatorMemoryPool.java | 71 +++++++--------- .../memory/pool/impl/QueryMemoryPool.java | 82 ++++++++++++------- .../memory/pool/impl/TaskMemoryPool.java | 8 +- .../memory/reclaimer/MemoryReclaimer.java | 22 ----- .../memory/util/MemoryManageUtils.java | 47 +++++++++++ 12 files changed, 268 insertions(+), 148 deletions(-) create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/MemoryReclaimer.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryManageUtils.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index b778a2b16c..58501df766 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -44,8 +44,10 @@ public class MemoryManager { private static final int ARBITRATE_MEMORY_THREAD_NUM = 12; // TODO: read it from conf, current 1G public static final long MAX_MEMORY_CAPACITY_IN_BYTES = Bytes.GB; - private final AtomicLong currentMemoryCapacityInBytes = + private final AtomicLong currentAvailableMemoryInBytes = new AtomicLong(MAX_MEMORY_CAPACITY_IN_BYTES); + private final AtomicLong currentOffHeapAllocatedMemory = new AtomicLong(0); + private final AtomicLong currentOnHeapAllocatedMemory = new AtomicLong(0); private final Set queryMemoryPools = new CopyOnWriteArraySet<>(); private final MemoryArbitrator memoryArbitrator; private final ExecutorService arbitrateExecutor; @@ -57,7 +59,7 @@ private MemoryManager() { this.arbitrateExecutor = ExecutorUtil.newFixedThreadPool(ARBITRATE_MEMORY_THREAD_NUM, ARBITRATE_MEMORY_POOL_NAME); } - + public MemoryPool addQueryMemoryPool() { int count = queryMemoryPools.size(); String poolName = @@ -65,6 +67,7 @@ public MemoryPool addQueryMemoryPool() { System.currentTimeMillis(); MemoryPool queryPool = new QueryMemoryPool(poolName, this); queryMemoryPools.add(queryPool); + LOGGER.info("Manager added query memory pool {}", queryPool); return queryPool; } @@ -72,10 +75,12 @@ public void gcQueryMemoryPool(MemoryPool pool) { queryMemoryPools.remove(pool); long reclaimedMemory = pool.getAllocatedBytes(); pool.releaseSelf(); - currentMemoryCapacityInBytes.addAndGet(reclaimedMemory); + currentAvailableMemoryInBytes.addAndGet(reclaimedMemory); + LOGGER.info("Manager gc query memory pool {}", pool); } public long triggerLocalArbitration(MemoryPool targetPool, long neededBytes) { + LOGGER.info("LocalArbitration triggered by {}: needed bytes={}", targetPool, neededBytes); Future future = arbitrateExecutor.submit( () -> memoryArbitrator.reclaimLocally(targetPool, neededBytes)); @@ -93,6 +98,7 @@ public long triggerLocalArbitration(MemoryPool targetPool, long neededBytes) { } public long triggerGlobalArbitration(MemoryPool requestPool, long neededBytes) { + LOGGER.info("GlobalArbitration triggered by {}: needed bytes={}", requestPool, neededBytes); Future future = arbitrateExecutor.submit( () -> memoryArbitrator.reclaimGlobally(requestPool, neededBytes)); @@ -108,6 +114,33 @@ public long triggerGlobalArbitration(MemoryPool requestPool, long neededBytes) { return 0; } + public synchronized long handleRequestFromQueryPool(long size) { + // 1. check whole memory capacity. + if (currentAvailableMemoryInBytes.get() < size) { + LOGGER.info("There isn't enough memory for query pool to expand itself: " + + "requestSize={}, remainingCapacity={}", size, + currentAvailableMemoryInBytes.get()); + return -1; + } + currentAvailableMemoryInBytes.addAndGet(-size); + LOGGER.info("Expand query pool successfully: " + + "requestSize={}, afterThisExpandingRemainingCapacity={}", size, + currentAvailableMemoryInBytes.get()); + return size; + } + + public void consumeAvailableMemory(long size) { + currentAvailableMemoryInBytes.addAndGet(-size); + } + + public AtomicLong getCurrentOnHeapAllocatedMemory() { + return currentOnHeapAllocatedMemory; + } + + public AtomicLong getCurrentOffHeapAllocatedMemory() { + return currentOffHeapAllocatedMemory; + } + private static class MemoryManagerHolder { private static final MemoryManager INSTANCE = new MemoryManager(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java index 43da0e5c2a..17ed167c17 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java @@ -17,10 +17,11 @@ package org.apache.hugegraph.memory.allocator; -// TODO(pjz): implement different memory allocate strategy. public interface MemoryAllocator { - Object tryToAllocateOffHeap(long size); + Object tryToAllocate(long size); - Object forceAllocateOffHeap(long size); + Object forceAllocate(long size); + + void releaseMemory(long size); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java index b5c2662d66..a6e4958e85 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java @@ -28,18 +28,29 @@ public class NettyMemoryAllocator implements MemoryAllocator { private final PooledByteBufAllocator offHeapAllocator = PooledByteBufAllocator.DEFAULT; + private final MemoryManager memoryManager; + + public NettyMemoryAllocator(MemoryManager memoryManager) { + this.memoryManager = memoryManager; + } @Override - public ByteBuf forceAllocateOffHeap(long size) { + public ByteBuf forceAllocate(long size) { return offHeapAllocator.directBuffer((int) size); } @Override - public ByteBuf tryToAllocateOffHeap(long size) { - if (offHeapAllocator.metric().usedDirectMemory() + size < + public ByteBuf tryToAllocate(long size) { + if (memoryManager.getCurrentOnHeapAllocatedMemory().get() + + memoryManager.getCurrentOffHeapAllocatedMemory().get() + size < MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES) { return offHeapAllocator.directBuffer((int) size); } return null; } + + @Override + public void releaseMemory(long size) { + memoryManager.getCurrentOffHeapAllocatedMemory().addAndGet(-size); + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java new file mode 100644 index 0000000000..7651bd8cbd --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java @@ -0,0 +1,54 @@ +/* + * 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.hugegraph.memory.allocator; + +import org.apache.hugegraph.memory.MemoryManager; +import org.apache.hugegraph.util.Bytes; + +public class OnHeapMemoryStrategy implements MemoryAllocator { + + private final MemoryManager memoryManager; + + public OnHeapMemoryStrategy(MemoryManager memoryManager) { + this.memoryManager = memoryManager; + } + + @Override + public Object tryToAllocate(long size) { + if (memoryManager.getCurrentOnHeapAllocatedMemory().get() + + memoryManager.getCurrentOffHeapAllocatedMemory().get() + size < + MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES) { + int sizeOfByte = (int) (size / Bytes.BASE); + memoryManager.getCurrentOnHeapAllocatedMemory().addAndGet(sizeOfByte); + return new byte[sizeOfByte]; + } + return null; + } + + @Override + public Object forceAllocate(long size) { + int sizeOfByte = (int) (size / Bytes.BASE); + memoryManager.getCurrentOnHeapAllocatedMemory().addAndGet(sizeOfByte); + return new byte[sizeOfByte]; + } + + @Override + public void releaseMemory(long size) { + memoryManager.getCurrentOnHeapAllocatedMemory().addAndGet(-size); + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index a4bbe93daf..93898c7619 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -17,10 +17,11 @@ package org.apache.hugegraph.memory.pool; -import java.nio.ByteBuffer; +import java.util.Optional; import java.util.Set; import java.util.TreeSet; +import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,16 +31,20 @@ public abstract class AbstractMemoryPool implements MemoryPool { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractMemoryPool.class); private final Set children = new TreeSet<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); - private MemoryPool parent; + protected final MemoryManager memoryManager; + protected MemoryPool parent; protected MemoryPoolStats stats; - public AbstractMemoryPool(MemoryPool parent, String memoryPoolName) { + public AbstractMemoryPool(MemoryPool parent, String memoryPoolName, + MemoryManager memoryManager) { this.parent = parent; this.stats = new MemoryPoolStats(memoryPoolName); + this.memoryManager = memoryManager; } @Override public long tryToReclaimLocalMemory(long neededBytes) { + LOGGER.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); long totalReclaimedBytes = 0; long currentNeededBytes = neededBytes; try { @@ -54,6 +59,10 @@ public long tryToReclaimLocalMemory(long neededBytes) { } } } + LOGGER.info("[{}] has finished to reclaim memory: totalReclaimedBytes={}, " + + "neededBytes={}", + this, + totalReclaimedBytes, neededBytes); return totalReclaimedBytes; } finally { this.stats.setNumShrinks(this.stats.getNumShrinks() + 1); @@ -63,38 +72,31 @@ public long tryToReclaimLocalMemory(long neededBytes) { } @Override - public boolean tryToDiskSpill() { - // 1. for every child, invoke disk spill - boolean res = true; - try { - for (MemoryPool child : this.children) { - res &= child.tryToDiskSpill(); - } - return res; - } catch (Exception e) { - LOGGER.error("Failed to try to disk spill", e); - return false; + public void gcChildPool(MemoryPool child, boolean force) { + if (force) { + child.releaseSelf(); } - // TODO: for upper caller, if spill failed, apply rollback + // reclaim child's memory and update stats + stats.setAllocatedBytes( + stats.getAllocatedBytes() - child.getAllocatedBytes()); + stats.setUsedBytes(stats.getUsedBytes() - child.getUsedBytes()); + this.children.remove(child); + memoryManager.consumeAvailableMemory(-child.getAllocatedBytes()); } /** - * called when one task is successfully executed and exited. + * called when one layer pool is successfully executed and exited. */ - @Override - public void gcChildPool(MemoryPool child) { - // 1. reclaim child's memory and update stats - stats.setReservedBytes(stats.getReservedBytes() - child.getSnapShot().getReservedBytes()); - // 2. release child - child.releaseSelf(); - } - @Override public void releaseSelf() { + LOGGER.info("[{}] starts to releaseSelf", this); try { + // update father + Optional.ofNullable(parent).ifPresent(parent -> parent.gcChildPool(this, false)); for (MemoryPool child : this.children) { - child.releaseSelf(); + gcChildPool(child, true); } + LOGGER.info("[{}] finishes to releaseSelf", this); } finally { // Make these objs be GCed by JVM quickly. this.stats = null; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index 3592d851fa..1b6a4142a5 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -17,7 +17,6 @@ package org.apache.hugegraph.memory.pool; -import java.nio.ByteBuffer; import java.util.Set; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; @@ -32,9 +31,7 @@ public interface MemoryPool { void releaseSelf(); - void gcChildPool(MemoryPool child); - - boolean tryToDiskSpill() throws Exception; + void gcChildPool(MemoryPool child, boolean force); long getAllocatedBytes(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java index 33286963f5..c5de6b7e3d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java @@ -22,7 +22,6 @@ public class MemoryPoolStats { private final String memoryPoolName; private long maxCapacity; private long usedBytes; - private long reservedBytes; private long cumulativeBytes; private long allocatedBytes; @@ -36,11 +35,10 @@ public MemoryPoolStats(String MemoryPoolName) { @Override public String toString() { - return String.format("MemoryPool-%s: {maxCapacity[%d], usedBytes[%d], reservedBytes[%d]," + + return String.format("MemoryPool-%s: {maxCapacity[%d], usedBytes[%d]," + "cumulativeBytes[%d], allocatedBytes[%d], numShrinks[%d], " + "numExpands[%d], numAborts[%d]}.", memoryPoolName, maxCapacity, usedBytes, - reservedBytes, cumulativeBytes, allocatedBytes, numShrinks, numExpands, numAborts); } @@ -57,14 +55,6 @@ public void setUsedBytes(long usedBytes) { this.usedBytes = usedBytes; } - public long getReservedBytes() { - return this.reservedBytes; - } - - public void setReservedBytes(long reservedBytes) { - this.reservedBytes = reservedBytes; - } - public long getCumulativeBytes() { return this.cumulativeBytes; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index 3eeddf4acf..4ce2aa9010 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -17,49 +17,56 @@ package org.apache.hugegraph.memory.pool.impl; +import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.allocator.MemoryAllocator; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; import org.apache.hugegraph.memory.pool.MemoryPool; +import org.apache.hugegraph.memory.util.MemoryManageUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class OperatorMemoryPool extends AbstractMemoryPool { - // TODO: configurable - private static final long ALIGNMENT = 8; - private static final long MB = 1 << 20; - // TODO: implement different allocate strategy & make it configurable. + private static final Logger LOGGER = LoggerFactory.getLogger(OperatorMemoryPool.class); private final MemoryAllocator memoryAllocator; public OperatorMemoryPool(MemoryPool parent, String poolName, - MemoryAllocator memoryAllocator) { - super(parent, poolName); + MemoryAllocator memoryAllocator, MemoryManager memoryManager) { + super(parent, poolName, memoryManager); this.memoryAllocator = memoryAllocator; - // TODO: this.stats.setMaxCapacity(); - } - - @Override - public boolean tryToDiskSpill() { - return false; } @Override public void releaseSelf() { super.releaseSelf(); + memoryAllocator.releaseMemory(getAllocatedBytes()); // TODO: release memory consumer, release byte buffer. } @Override public long tryToReclaimLocalMemory(long neededBytes) { + LOGGER.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); // 1. try to reclaim self free memory long reclaimableBytes = getFreeBytes(); // try its best to reclaim memory if (reclaimableBytes <= neededBytes) { // 2. update stats stats.setAllocatedBytes(stats.getUsedBytes()); - stats.setReservedBytes(stats.getUsedBytes()); + LOGGER.info("[{}] has tried its best to reclaim memory: " + + "reclaimedBytes={}," + + " " + + "neededBytes={}", + this, + reclaimableBytes, neededBytes); return reclaimableBytes; } stats.setAllocatedBytes(stats.getAllocatedBytes() - neededBytes); - stats.setReservedBytes(stats.getReservedBytes() - neededBytes); + LOGGER.info("[{}] has reclaim enough memory: " + + "reclaimedBytes={}," + + " " + + "neededBytes={}", + this, + neededBytes, neededBytes); return neededBytes; } @@ -68,18 +75,18 @@ public long tryToReclaimLocalMemory(long neededBytes) { */ @Override public Object tryToAcquireMemory(long size) { + LOGGER.info("[{}] tryToAcquireMemory: size={}", this, size); // 1. update statistic super.tryToAcquireMemory(size); // 2. allocate memory, currently use off-heap mode. - // if you use on-heap mode, we only track memory usage here. - return memoryAllocator.tryToAllocateOffHeap(size); + return memoryAllocator.tryToAllocate(size); } @Override public long requestMemory(long size) { - // TODO: check max capacity + LOGGER.info("[{}] requestMemory: request size={}", this, size); // 1. align size - long alignedSize = sizeAlign(size); + long alignedSize = MemoryManageUtils.sizeAlign(size); // 2. reserve(round) long neededMemorySize = calculateReserveMemoryDelta(alignedSize); if (neededMemorySize <= 0) { @@ -88,22 +95,18 @@ public long requestMemory(long size) { // 3. call father long fatherRes = getParentPool().requestMemory(neededMemorySize); if (fatherRes < 0) { + LOGGER.error("[{}] requestMemory failed because of OOM, request size={}", this, size); // TODO: new OOM exception stats.setNumAborts(stats.getNumAborts() + 1); throw new OutOfMemoryError(); } // 4. update stats - stats.setReservedBytes(stats.getReservedBytes() + neededMemorySize); stats.setAllocatedBytes(stats.getAllocatedBytes() + neededMemorySize); stats.setNumExpands(stats.getNumExpands() + 1); + LOGGER.info("[{}] requestMemory success: requestedMemorySize={}", this, fatherRes); return fatherRes; } - private long sizeAlign(long size) { - long reminder = size % ALIGNMENT; - return reminder == 0 ? size : size + ALIGNMENT - reminder; - } - /** * This method should be synchronized. */ @@ -115,24 +118,6 @@ private synchronized long calculateReserveMemoryDelta(long size) { return 0; } // 3. if needed, calculate rounded size and return it - return roundDelta(stats.getReservedBytes(), neededSize); - } - - private long roundDelta(long reservedSize, long delta) { - return quantizedSize(reservedSize + delta) - reservedSize; - } - - private long quantizedSize(long size) { - if (size < 16 * MB) { - return roundUp(size, MB); - } - if (size < 64 * MB) { - return roundUp(size, 4 * MB); - } - return roundUp(size, 8 * MB); - } - - private long roundUp(long size, long factor) { - return (size + factor - 1) / factor * factor; + return MemoryManageUtils.roundDelta(getAllocatedBytes(), neededSize); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index be1ce8dda6..0f243ff575 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -19,54 +19,78 @@ import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; +import org.apache.hugegraph.memory.util.MemoryManageUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class QueryMemoryPool extends AbstractMemoryPool { - private final MemoryManager memoryManager; + private static final Logger LOGGER = LoggerFactory.getLogger(QueryMemoryPool.class); public QueryMemoryPool(String poolName, MemoryManager memoryManager) { - super(null, poolName); - this.memoryManager = memoryManager; - // TODO: this.stats.setMaxCapacity(); + super(null, poolName, memoryManager); + // TODO: this.stats.setMaxCapacity(); read from conf } @Override public long requestMemory(long bytes) { // 1. check whether self capacity is enough if (getMaxCapacityBytes() - stats.getAllocatedBytes() < bytes) { - // 2. if not, call manager to invoke arbitrate locally - long reclaimedBytes = memoryManager.triggerLocalArbitration(this, bytes); - // 3. if arbitrate successes, update stats and return success - if (reclaimedBytes - bytes >= 0) { - // here we don't update capacity, because memory is reclaimed from queryPool itself. - stats.setReservedBytes(stats.getReservedBytes() + bytes); + // 2.1 if not, first try to acquire memory from manager + long managerReturnedMemoryInBytes = tryToExpandSelfCapacity(bytes); + if (managerReturnedMemoryInBytes > 0) { + stats.setMaxCapacity(getMaxCapacityBytes() + managerReturnedMemoryInBytes); stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); stats.setNumExpands(stats.getNumExpands() + 1); + memoryManager.consumeAvailableMemory(bytes); return bytes; - } else { - // 4. if still not enough, try to reclaim globally - long globalReclaimedBytes = memoryManager.triggerGlobalArbitration(this, - bytes - - reclaimedBytes); - reclaimedBytes += globalReclaimedBytes; - // 5. if memory is enough, update stats and return success - if (reclaimedBytes - bytes >= 0) { - // add capacity - stats.setMaxCapacity(stats.getMaxCapacity() + globalReclaimedBytes); - stats.setReservedBytes(stats.getReservedBytes() + bytes); - stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); - stats.setNumExpands(stats.getNumExpands() + 1); - return bytes; - } } - // 6. if arbitrate fails, return -1, indicating that request failed. - return -1; + // 2.2 if requiring memory from manager failed, call manager to invoke arbitrate locally + return requestMemoryThroughArbitration(bytes); } else { - // 7. if capacity is enough, return success - stats.setReservedBytes(stats.getReservedBytes() + bytes); + // 3. if capacity is enough, return success stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); + memoryManager.consumeAvailableMemory(bytes); return bytes; } } + private long tryToExpandSelfCapacity(long size) { + LOGGER.info("[{}] try to expand its capacity: size={}", this, size); + long alignedSize = MemoryManageUtils.sizeAlign(size); + long realNeededSize = + MemoryManageUtils.roundDelta(getAllocatedBytes(), alignedSize); + return memoryManager.handleRequestFromQueryPool(realNeededSize); + } + + private long requestMemoryThroughArbitration(long bytes) { + LOGGER.info("[{}] try to request memory from manager through arbitration: size={}", this, + bytes); + long reclaimedBytes = memoryManager.triggerLocalArbitration(this, bytes); + // 1. if arbitrate successes, update stats and return success + if (reclaimedBytes - bytes >= 0) { + // here we don't update capacity & reserved & allocated, because memory is + // reclaimed from queryPool itself. + stats.setNumExpands(stats.getNumExpands() + 1); + memoryManager.consumeAvailableMemory(bytes); + return bytes; + } else { + // 2. if still not enough, try to reclaim globally + long globalReclaimedBytes = memoryManager.triggerGlobalArbitration(this, + bytes - + reclaimedBytes); + reclaimedBytes += globalReclaimedBytes; + // 3. if memory is enough, update stats and return success + if (reclaimedBytes - bytes >= 0) { + // add capacity + stats.setMaxCapacity(stats.getMaxCapacity() + globalReclaimedBytes); + stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); + stats.setNumExpands(stats.getNumExpands() + 1); + memoryManager.consumeAvailableMemory(bytes); + return bytes; + } + } + // 4. if arbitrate fails, return -1, indicating that request failed. + return -1; + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index 439525aebf..d99c8955ee 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -17,22 +17,20 @@ package org.apache.hugegraph.memory.pool.impl; +import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; import org.apache.hugegraph.memory.pool.MemoryPool; public class TaskMemoryPool extends AbstractMemoryPool { - public TaskMemoryPool(MemoryPool parent, String poolName) { - super(parent, poolName); - // TODO: this.stats.setMaxCapacity(); + public TaskMemoryPool(MemoryPool parent, String poolName, MemoryManager memoryManager) { + super(parent, poolName, memoryManager); } @Override public long requestMemory(long bytes) { - // TODO: check max capacity long parentRes = getParentPool().requestMemory(bytes); if (parentRes > 0) { - stats.setReservedBytes(stats.getReservedBytes() + parentRes); stats.setAllocatedBytes(stats.getAllocatedBytes() + parentRes); } return parentRes; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/MemoryReclaimer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/MemoryReclaimer.java deleted file mode 100644 index cf92c91057..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/reclaimer/MemoryReclaimer.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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.hugegraph.memory.reclaimer; - -public interface MemoryReclaimer { - -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryManageUtils.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryManageUtils.java new file mode 100644 index 0000000000..bf5b79a6a9 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryManageUtils.java @@ -0,0 +1,47 @@ +/* + * 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.hugegraph.memory.util; + +public class MemoryManageUtils { + + // TODO: configurable + private static final long ALIGNMENT = 8; + private static final long MB = 1 << 20; + + public static long sizeAlign(long size) { + long reminder = size % ALIGNMENT; + return reminder == 0 ? size : size + ALIGNMENT - reminder; + } + + public static long roundDelta(long reservedSize, long delta) { + return quantizedSize(reservedSize + delta) - reservedSize; + } + + private static long quantizedSize(long size) { + if (size < 16 * MB) { + return roundUp(size, MB); + } + if (size < 64 * MB) { + return roundUp(size, 4 * MB); + } + return roundUp(size, 8 * MB); + } + + private static long roundUp(long size, long factor) { + return (size + factor - 1) / factor * factor; + } +} From ea9a4593020a29355b19eb2314a67aa1fb4d939b Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 22 Oct 2024 22:57:47 +0800 Subject: [PATCH 11/48] move monitor --- .../main/java/org/apache/hugegraph/memory/MemoryManager.java | 3 +-- .../java/org/apache/hugegraph/memory/util}/MemoryMonitor.java | 2 +- .../main/java/org/apache/hugegraph/dist/HugeGraphServer.java | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) rename hugegraph-server/{hugegraph-dist/src/main/java/org/apache/hugegraph/dist => hugegraph-core/src/main/java/org/apache/hugegraph/memory/util}/MemoryMonitor.java (99%) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index 58501df766..f83bd99892 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -51,8 +51,7 @@ public class MemoryManager { private final Set queryMemoryPools = new CopyOnWriteArraySet<>(); private final MemoryArbitrator memoryArbitrator; private final ExecutorService arbitrateExecutor; - // TODO: integrated with mingzhen's monitor thread - // private final Runnable queryGCThread; + private final MemoryMonitor memoryMonitor; private MemoryManager() { this.memoryArbitrator = new MemoryArbitratorImpl(); diff --git a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/MemoryMonitor.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryMonitor.java similarity index 99% rename from hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/MemoryMonitor.java rename to hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryMonitor.java index 18b7cc170f..e7c29e24db 100644 --- a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/MemoryMonitor.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryMonitor.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.hugegraph.dist; +package org.apache.hugegraph.memory.util; import java.lang.management.ManagementFactory; import java.lang.management.MemoryUsage; diff --git a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGraphServer.java b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGraphServer.java index 2652324f44..29d49fb700 100644 --- a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGraphServer.java +++ b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGraphServer.java @@ -24,6 +24,7 @@ import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.config.ServerOptions; import org.apache.hugegraph.event.EventHub; +import org.apache.hugegraph.memory.util.MemoryMonitor; import org.apache.hugegraph.server.RestServer; import org.apache.hugegraph.util.ConfigUtil; import org.apache.hugegraph.util.Log; From f552fd2460137bfb085b368741bbdea806d3d77a Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 22 Oct 2024 22:57:58 +0800 Subject: [PATCH 12/48] Revert "move monitor" This reverts commit ea9a4593020a29355b19eb2314a67aa1fb4d939b. --- .../main/java/org/apache/hugegraph/memory/MemoryManager.java | 3 ++- .../main/java/org/apache/hugegraph/dist/HugeGraphServer.java | 1 - .../main/java/org/apache/hugegraph/dist}/MemoryMonitor.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename hugegraph-server/{hugegraph-core/src/main/java/org/apache/hugegraph/memory/util => hugegraph-dist/src/main/java/org/apache/hugegraph/dist}/MemoryMonitor.java (99%) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index f83bd99892..58501df766 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -51,7 +51,8 @@ public class MemoryManager { private final Set queryMemoryPools = new CopyOnWriteArraySet<>(); private final MemoryArbitrator memoryArbitrator; private final ExecutorService arbitrateExecutor; - private final MemoryMonitor memoryMonitor; + // TODO: integrated with mingzhen's monitor thread + // private final Runnable queryGCThread; private MemoryManager() { this.memoryArbitrator = new MemoryArbitratorImpl(); diff --git a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGraphServer.java b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGraphServer.java index 29d49fb700..2652324f44 100644 --- a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGraphServer.java +++ b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/HugeGraphServer.java @@ -24,7 +24,6 @@ import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.config.ServerOptions; import org.apache.hugegraph.event.EventHub; -import org.apache.hugegraph.memory.util.MemoryMonitor; import org.apache.hugegraph.server.RestServer; import org.apache.hugegraph.util.ConfigUtil; import org.apache.hugegraph.util.Log; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryMonitor.java b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/MemoryMonitor.java similarity index 99% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryMonitor.java rename to hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/MemoryMonitor.java index e7c29e24db..18b7cc170f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryMonitor.java +++ b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/dist/MemoryMonitor.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.hugegraph.memory.util; +package org.apache.hugegraph.dist; import java.lang.management.ManagementFactory; import java.lang.management.MemoryUsage; From 8a2c65ca19b60c343b86671b9f1ff11a11bdc54f Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 22 Oct 2024 23:28:29 +0800 Subject: [PATCH 13/48] improve memory arbitration --- .../hugegraph/memory/MemoryManager.java | 15 ++++---- .../arbitrator/MemoryArbitratorImpl.java | 36 +++++++++++++++---- .../memory/pool/AbstractMemoryPool.java | 13 +++---- .../hugegraph/memory/pool/MemoryPool.java | 2 -- .../memory/pool/impl/QueryMemoryPool.java | 6 ++-- 5 files changed, 46 insertions(+), 26 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index 58501df766..1f9eb1e331 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -17,8 +17,8 @@ package org.apache.hugegraph.memory; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; +import java.util.PriorityQueue; +import java.util.Queue; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; @@ -48,14 +48,13 @@ public class MemoryManager { new AtomicLong(MAX_MEMORY_CAPACITY_IN_BYTES); private final AtomicLong currentOffHeapAllocatedMemory = new AtomicLong(0); private final AtomicLong currentOnHeapAllocatedMemory = new AtomicLong(0); - private final Set queryMemoryPools = new CopyOnWriteArraySet<>(); + private final Queue queryMemoryPools = + new PriorityQueue<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); private final MemoryArbitrator memoryArbitrator; private final ExecutorService arbitrateExecutor; - // TODO: integrated with mingzhen's monitor thread - // private final Runnable queryGCThread; private MemoryManager() { - this.memoryArbitrator = new MemoryArbitratorImpl(); + this.memoryArbitrator = new MemoryArbitratorImpl(this); this.arbitrateExecutor = ExecutorUtil.newFixedThreadPool(ARBITRATE_MEMORY_THREAD_NUM, ARBITRATE_MEMORY_POOL_NAME); } @@ -129,6 +128,10 @@ public synchronized long handleRequestFromQueryPool(long size) { return size; } + public Queue getCurrentQueryMemoryPools() { + return new PriorityQueue<>(queryMemoryPools); + } + public void consumeAvailableMemory(long size) { currentAvailableMemoryInBytes.addAndGet(-size); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java index 1fda892e1f..84a4a3386d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java @@ -17,17 +17,27 @@ package org.apache.hugegraph.memory.arbitrator; +import java.util.Queue; + +import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.MemoryPool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +// TODO: consider concurrency public class MemoryArbitratorImpl implements MemoryArbitrator { private static final Logger LOGGER = LoggerFactory.getLogger(MemoryArbitratorImpl.class); + private final MemoryManager memoryManager; + + public MemoryArbitratorImpl(MemoryManager memoryManager) { + this.memoryManager = memoryManager; + } @Override public long reclaimLocally(MemoryPool queryPool, long neededBytes) { long startTime = System.currentTimeMillis(); + // TODO:suspend that task long res = queryPool.tryToReclaimLocalMemory(neededBytes); LOGGER.info("[{}] reclaim local memory: {} bytes, took {} ms", Thread.currentThread().getName(), @@ -39,14 +49,28 @@ public long reclaimLocally(MemoryPool queryPool, long neededBytes) { @Override public long reclaimGlobally(MemoryPool queryPool, long neededBytes) { long startTime = System.currentTimeMillis(); - // TODO - // 1. select the query task that uses the most memory - // 2. suspend that task - // 3. apply disk spill to that task + long totalReclaimedBytes = 0; + long currentNeededBytes = neededBytes; + Queue currentMemoryPool = memoryManager.getCurrentQueryMemoryPools(); + while (!currentMemoryPool.isEmpty()) { + MemoryPool memoryPool = currentMemoryPool.poll(); + if (memoryPool.equals(queryPool)) { + continue; + } + LOGGER.info("Global reclaim triggerred by {} select {} to reclaim", queryPool, + memoryPool); + // TODO:suspend that task + long res = memoryPool.tryToReclaimLocalMemory(currentNeededBytes); + totalReclaimedBytes += res; + currentNeededBytes -= res; + if (currentNeededBytes <= 0) { + break; + } + } LOGGER.info("[{}] reclaim global memory: {} bytes, took {} ms", Thread.currentThread().getName(), - 0, + totalReclaimedBytes, System.currentTimeMillis() - startTime); - return 0; + return totalReclaimedBytes; } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 93898c7619..44650193b4 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -18,8 +18,8 @@ package org.apache.hugegraph.memory.pool; import java.util.Optional; -import java.util.Set; -import java.util.TreeSet; +import java.util.PriorityQueue; +import java.util.Queue; import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; @@ -29,8 +29,8 @@ public abstract class AbstractMemoryPool implements MemoryPool { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractMemoryPool.class); - private final Set children = - new TreeSet<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); + private final Queue children = + new PriorityQueue<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); protected final MemoryManager memoryManager; protected MemoryPool parent; protected MemoryPoolStats stats; @@ -148,11 +148,6 @@ public String getName() { return stats.getMemoryPoolName(); } - @Override - public Set getChildrenPools() { - return children; - } - @Override public String toString() { return getSnapShot().toString(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index 1b6a4142a5..29cef1667a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -45,7 +45,5 @@ public interface MemoryPool { MemoryPool getParentPool(); - Set getChildrenPools(); - long requestMemory(long bytes); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 0f243ff575..1e686ad305 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -66,19 +66,19 @@ private long tryToExpandSelfCapacity(long size) { private long requestMemoryThroughArbitration(long bytes) { LOGGER.info("[{}] try to request memory from manager through arbitration: size={}", this, bytes); + stats.setNumExpands(stats.getNumExpands() + 1); long reclaimedBytes = memoryManager.triggerLocalArbitration(this, bytes); // 1. if arbitrate successes, update stats and return success if (reclaimedBytes - bytes >= 0) { // here we don't update capacity & reserved & allocated, because memory is // reclaimed from queryPool itself. - stats.setNumExpands(stats.getNumExpands() + 1); memoryManager.consumeAvailableMemory(bytes); return bytes; } else { // 2. if still not enough, try to reclaim globally + long globalArbitrationNeededBytes = bytes - reclaimedBytes; long globalReclaimedBytes = memoryManager.triggerGlobalArbitration(this, - bytes - - reclaimedBytes); + globalArbitrationNeededBytes); reclaimedBytes += globalReclaimedBytes; // 3. if memory is enough, update stats and return success if (reclaimedBytes - bytes >= 0) { From c37f86994198c5b03b749e346a0db684b66286fe Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Wed, 23 Oct 2024 14:06:27 +0800 Subject: [PATCH 14/48] suspend query when arbitration & kill query when OOM --- .../hugegraph/memory/MemoryManager.java | 4 +- .../arbitrator/MemoryArbitratorImpl.java | 2 - .../memory/pool/AbstractMemoryPool.java | 86 ++++++++--- .../hugegraph/memory/pool/MemoryPool.java | 13 +- .../memory/pool/impl/OperatorMemoryPool.java | 135 ++++++++++++------ .../memory/pool/impl/QueryMemoryPool.java | 49 ++++--- .../memory/pool/impl/TaskMemoryPool.java | 29 +++- .../util/QueryOutOfMemoryException.java | 33 +++++ 8 files changed, 258 insertions(+), 93 deletions(-) create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/QueryOutOfMemoryException.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index 1f9eb1e331..a6f4e9c295 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -71,11 +71,11 @@ public MemoryPool addQueryMemoryPool() { } public void gcQueryMemoryPool(MemoryPool pool) { + LOGGER.info("Manager gc query memory pool {}", pool); queryMemoryPools.remove(pool); long reclaimedMemory = pool.getAllocatedBytes(); - pool.releaseSelf(); + pool.releaseSelf(String.format("GC query memory pool %s", pool)); currentAvailableMemoryInBytes.addAndGet(reclaimedMemory); - LOGGER.info("Manager gc query memory pool {}", pool); } public long triggerLocalArbitration(MemoryPool targetPool, long neededBytes) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java index 84a4a3386d..a85d13acf8 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java @@ -37,7 +37,6 @@ public MemoryArbitratorImpl(MemoryManager memoryManager) { @Override public long reclaimLocally(MemoryPool queryPool, long neededBytes) { long startTime = System.currentTimeMillis(); - // TODO:suspend that task long res = queryPool.tryToReclaimLocalMemory(neededBytes); LOGGER.info("[{}] reclaim local memory: {} bytes, took {} ms", Thread.currentThread().getName(), @@ -59,7 +58,6 @@ public long reclaimGlobally(MemoryPool queryPool, long neededBytes) { } LOGGER.info("Global reclaim triggerred by {} select {} to reclaim", queryPool, memoryPool); - // TODO:suspend that task long res = memoryPool.tryToReclaimLocalMemory(currentNeededBytes); totalReclaimedBytes += res; currentNeededBytes -= res; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 44650193b4..8c7e537246 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -20,6 +20,9 @@ import java.util.Optional; import java.util.PriorityQueue; import java.util.Queue; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; @@ -32,8 +35,12 @@ public abstract class AbstractMemoryPool implements MemoryPool { private final Queue children = new PriorityQueue<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); protected final MemoryManager memoryManager; - protected MemoryPool parent; - protected MemoryPoolStats stats; + protected final ReentrantLock arbitrationLock = new ReentrantLock(); + protected final Condition condition = arbitrationLock.newCondition(); + protected final AtomicBoolean isBeingArbitrated = new AtomicBoolean(false); + protected final MemoryPoolStats stats; + protected boolean isClosed = false; + private MemoryPool parent; public AbstractMemoryPool(MemoryPool parent, String memoryPoolName, MemoryManager memoryManager) { @@ -44,10 +51,16 @@ public AbstractMemoryPool(MemoryPool parent, String memoryPoolName, @Override public long tryToReclaimLocalMemory(long neededBytes) { + if (isClosed) { + LOGGER.warn("[{}] is already closed, will abort this reclaim", this); + return 0; + } LOGGER.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); long totalReclaimedBytes = 0; long currentNeededBytes = neededBytes; try { + this.arbitrationLock.lock(); + this.isBeingArbitrated.set(true); for (MemoryPool child : this.children) { long reclaimedMemory = child.tryToReclaimLocalMemory(currentNeededBytes); if (reclaimedMemory > 0) { @@ -68,69 +81,88 @@ public long tryToReclaimLocalMemory(long neededBytes) { this.stats.setNumShrinks(this.stats.getNumShrinks() + 1); this.stats.setAllocatedBytes( this.stats.getAllocatedBytes() - totalReclaimedBytes); + this.isBeingArbitrated.set(false); + this.arbitrationLock.unlock(); + this.condition.signalAll(); } } - @Override - public void gcChildPool(MemoryPool child, boolean force) { - if (force) { - child.releaseSelf(); - } - // reclaim child's memory and update stats - stats.setAllocatedBytes( - stats.getAllocatedBytes() - child.getAllocatedBytes()); - stats.setUsedBytes(stats.getUsedBytes() - child.getUsedBytes()); - this.children.remove(child); - memoryManager.consumeAvailableMemory(-child.getAllocatedBytes()); - } - /** * called when one layer pool is successfully executed and exited. */ @Override - public void releaseSelf() { - LOGGER.info("[{}] starts to releaseSelf", this); + public synchronized void releaseSelf(String reason) { try { + if (isBeingArbitrated.get()) { + condition.await(); + } + LOGGER.info("[{}] starts to releaseSelf because of {}", this, reason); + this.isClosed = true; // update father Optional.ofNullable(parent).ifPresent(parent -> parent.gcChildPool(this, false)); for (MemoryPool child : this.children) { gcChildPool(child, true); } LOGGER.info("[{}] finishes to releaseSelf", this); + } catch (InterruptedException e) { + LOGGER.error("Failed to release self because ", e); + Thread.currentThread().interrupt(); } finally { // Make these objs be GCed by JVM quickly. - this.stats = null; this.parent = null; this.children.clear(); } } @Override - public Object tryToAcquireMemory(long bytes) { + public void gcChildPool(MemoryPool child, boolean force) { + if (force) { + child.releaseSelf(String.format("[%s] releaseChildPool", this)); + } + // reclaim child's memory and update stats + stats.setAllocatedBytes( + stats.getAllocatedBytes() - child.getAllocatedBytes()); + stats.setUsedBytes(stats.getUsedBytes() - child.getUsedBytes()); + memoryManager.consumeAvailableMemory(-child.getAllocatedBytes()); + this.children.remove(child); + } + + @Override + public Object tryToAcquireMemoryInternal(long bytes) { + if (isClosed) { + LOGGER.warn("[{}] is already closed, will abort this allocate", this); + return 0; + } // just record how much memory is used(update stats) stats.setUsedBytes(stats.getUsedBytes() + bytes); stats.setCumulativeBytes(stats.getCumulativeBytes() + bytes); return null; } + @Override + public Object requireMemory(long bytes) { + return null; + } + @Override public long getMaxCapacityBytes() { - return stats.getMaxCapacity(); + return Optional.of(stats).map(MemoryPoolStats::getMaxCapacity).orElse(0L); } @Override public long getUsedBytes() { - return stats.getUsedBytes(); + return Optional.of(stats).map(MemoryPoolStats::getUsedBytes).orElse(0L); } @Override public long getFreeBytes() { - return stats.getAllocatedBytes() - stats.getUsedBytes(); + return Optional.of(stats) + .map(stats -> stats.getAllocatedBytes() - stats.getUsedBytes()).orElse(0L); } @Override public long getAllocatedBytes() { - return stats.getAllocatedBytes(); + return Optional.of(stats).map(MemoryPoolStats::getAllocatedBytes).orElse(0L); } @Override @@ -152,4 +184,12 @@ public String getName() { public String toString() { return getSnapShot().toString(); } + + @Override + public MemoryPool findRootQueryPool() { + if (parent == null) { + return this; + } + return getParentPool().findRootQueryPool(); + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index 29cef1667a..7c396ede91 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -17,9 +17,8 @@ package org.apache.hugegraph.memory.pool; -import java.util.Set; - import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; +import org.apache.hugegraph.memory.util.QueryOutOfMemoryException; public interface MemoryPool { @@ -27,9 +26,13 @@ public interface MemoryPool { long tryToReclaimLocalMemory(long neededBytes); - Object tryToAcquireMemory(long bytes); + Object requireMemory(long bytes); + + long requestMemoryInternal(long bytes) throws QueryOutOfMemoryException; + + Object tryToAcquireMemoryInternal(long bytes); - void releaseSelf(); + void releaseSelf(String reason); void gcChildPool(MemoryPool child, boolean force); @@ -45,5 +48,5 @@ public interface MemoryPool { MemoryPool getParentPool(); - long requestMemory(long bytes); + MemoryPool findRootQueryPool(); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index 4ce2aa9010..b748c48419 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -22,6 +22,7 @@ import org.apache.hugegraph.memory.pool.AbstractMemoryPool; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.util.MemoryManageUtils; +import org.apache.hugegraph.memory.util.QueryOutOfMemoryException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,74 +38,128 @@ public OperatorMemoryPool(MemoryPool parent, String poolName, } @Override - public void releaseSelf() { - super.releaseSelf(); + public synchronized void releaseSelf(String reason) { memoryAllocator.releaseMemory(getAllocatedBytes()); + super.releaseSelf(reason); // TODO: release memory consumer, release byte buffer. } @Override public long tryToReclaimLocalMemory(long neededBytes) { + if (isClosed) { + LOGGER.warn("[{}] is already closed, will abort this reclaim", this); + return 0; + } LOGGER.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); - // 1. try to reclaim self free memory - long reclaimableBytes = getFreeBytes(); - // try its best to reclaim memory - if (reclaimableBytes <= neededBytes) { - // 2. update stats - stats.setAllocatedBytes(stats.getUsedBytes()); - LOGGER.info("[{}] has tried its best to reclaim memory: " + + try { + this.arbitrationLock.lock(); + this.isBeingArbitrated.set(true); + // 1. try to reclaim self free memory + long reclaimableBytes = getFreeBytes(); + // try its best to reclaim memory + if (reclaimableBytes <= neededBytes) { + // 2. update stats + stats.setAllocatedBytes(stats.getUsedBytes()); + LOGGER.info("[{}] has tried its best to reclaim memory: " + + "reclaimedBytes={}," + + " " + + "neededBytes={}", + this, + reclaimableBytes, neededBytes); + return reclaimableBytes; + } + stats.setAllocatedBytes(stats.getAllocatedBytes() - neededBytes); + LOGGER.info("[{}] has reclaim enough memory: " + "reclaimedBytes={}," + " " + "neededBytes={}", this, - reclaimableBytes, neededBytes); - return reclaimableBytes; + neededBytes, neededBytes); + + return neededBytes; + } finally { + this.isBeingArbitrated.set(false); + this.arbitrationLock.unlock(); + this.condition.signalAll(); + } + } + + /** + * called by user + */ + @Override + public Object requireMemory(long bytes) { + try { + // use lock to ensure the atomicity of the two-step operation + this.arbitrationLock.lock(); + long realBytes = requestMemoryInternal(bytes); + return tryToAcquireMemoryInternal(realBytes); + } catch (QueryOutOfMemoryException e) { + // Abort this query + LOGGER.warn("[{}] detected an OOM exception when request memory, will ABORT this " + + "query and release corresponding memory...", + this); + findRootQueryPool().releaseSelf(String.format(e.getMessage())); + return null; + } finally { + this.arbitrationLock.unlock(); } - stats.setAllocatedBytes(stats.getAllocatedBytes() - neededBytes); - LOGGER.info("[{}] has reclaim enough memory: " + - "reclaimedBytes={}," + - " " + - "neededBytes={}", - this, - neededBytes, neededBytes); - return neededBytes; } /** * Operator need `size` bytes, operator pool will try to reserve some memory for it */ @Override - public Object tryToAcquireMemory(long size) { + public Object tryToAcquireMemoryInternal(long size) { + if (isClosed) { + LOGGER.warn("[{}] is already closed, will abort this allocate", this); + return 0; + } LOGGER.info("[{}] tryToAcquireMemory: size={}", this, size); // 1. update statistic - super.tryToAcquireMemory(size); + super.tryToAcquireMemoryInternal(size); // 2. allocate memory, currently use off-heap mode. return memoryAllocator.tryToAllocate(size); } @Override - public long requestMemory(long size) { - LOGGER.info("[{}] requestMemory: request size={}", this, size); - // 1. align size - long alignedSize = MemoryManageUtils.sizeAlign(size); - // 2. reserve(round) - long neededMemorySize = calculateReserveMemoryDelta(alignedSize); - if (neededMemorySize <= 0) { + public long requestMemoryInternal(long size) throws QueryOutOfMemoryException { + if (isClosed) { + LOGGER.warn("[{}] is already closed, will abort this request", this); return 0; } - // 3. call father - long fatherRes = getParentPool().requestMemory(neededMemorySize); - if (fatherRes < 0) { - LOGGER.error("[{}] requestMemory failed because of OOM, request size={}", this, size); - // TODO: new OOM exception - stats.setNumAborts(stats.getNumAborts() + 1); - throw new OutOfMemoryError(); + try { + if (isBeingArbitrated.get()) { + condition.await(); + } + LOGGER.info("[{}] requestMemory: request size={}", this, size); + // 1. align size + long alignedSize = MemoryManageUtils.sizeAlign(size); + // 2. reserve(round) + long neededMemorySize = calculateReserveMemoryDelta(alignedSize); + if (neededMemorySize <= 0) { + return 0; + } + // 3. call father + long fatherRes = getParentPool().requestMemoryInternal(neededMemorySize); + if (fatherRes < 0) { + LOGGER.error("[{}] requestMemory failed because of OOM, request size={}", this, + size); + stats.setNumAborts(stats.getNumAborts() + 1); + throw new QueryOutOfMemoryException(String.format("%s requestMemory failed " + + "because of OOM, request " + + "size=%s", this, size)); + } + // 4. update stats + stats.setAllocatedBytes(stats.getAllocatedBytes() + neededMemorySize); + stats.setNumExpands(stats.getNumExpands() + 1); + LOGGER.info("[{}] requestMemory success: requestedMemorySize={}", this, fatherRes); + return fatherRes; + } catch (InterruptedException e) { + LOGGER.error("Failed to release self because ", e); + Thread.currentThread().interrupt(); + return 0; } - // 4. update stats - stats.setAllocatedBytes(stats.getAllocatedBytes() + neededMemorySize); - stats.setNumExpands(stats.getNumExpands() + 1); - LOGGER.info("[{}] requestMemory success: requestedMemorySize={}", this, fatherRes); - return fatherRes; } /** diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 1e686ad305..19a79b9490 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -20,38 +20,55 @@ import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; import org.apache.hugegraph.memory.util.MemoryManageUtils; +import org.apache.hugegraph.util.Bytes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class QueryMemoryPool extends AbstractMemoryPool { private static final Logger LOGGER = LoggerFactory.getLogger(QueryMemoryPool.class); + // TODO: read from conf + private static final long QUERY_POOL_MAX_CAPACITY = Bytes.MB * 100; public QueryMemoryPool(String poolName, MemoryManager memoryManager) { super(null, poolName, memoryManager); - // TODO: this.stats.setMaxCapacity(); read from conf + this.stats.setMaxCapacity(QUERY_POOL_MAX_CAPACITY); } @Override - public long requestMemory(long bytes) { - // 1. check whether self capacity is enough - if (getMaxCapacityBytes() - stats.getAllocatedBytes() < bytes) { - // 2.1 if not, first try to acquire memory from manager - long managerReturnedMemoryInBytes = tryToExpandSelfCapacity(bytes); - if (managerReturnedMemoryInBytes > 0) { - stats.setMaxCapacity(getMaxCapacityBytes() + managerReturnedMemoryInBytes); + public long requestMemoryInternal(long bytes) { + if (isClosed) { + LOGGER.warn("[{}] is already closed, will abort this request", this); + return 0; + } + try { + if (isBeingArbitrated.get()) { + condition.await(); + } + // 1. check whether self capacity is enough + if (getMaxCapacityBytes() - stats.getAllocatedBytes() < bytes) { + // 2.1 if not, first try to acquire memory from manager + long managerReturnedMemoryInBytes = tryToExpandSelfCapacity(bytes); + if (managerReturnedMemoryInBytes > 0) { + stats.setMaxCapacity(getMaxCapacityBytes() + managerReturnedMemoryInBytes); + stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); + stats.setNumExpands(stats.getNumExpands() + 1); + memoryManager.consumeAvailableMemory(bytes); + return bytes; + } + // 2.2 if requiring memory from manager failed, call manager to invoke arbitrate + // locally + return requestMemoryThroughArbitration(bytes); + } else { + // 3. if capacity is enough, return success stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); - stats.setNumExpands(stats.getNumExpands() + 1); memoryManager.consumeAvailableMemory(bytes); return bytes; } - // 2.2 if requiring memory from manager failed, call manager to invoke arbitrate locally - return requestMemoryThroughArbitration(bytes); - } else { - // 3. if capacity is enough, return success - stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); - memoryManager.consumeAvailableMemory(bytes); - return bytes; + } catch (InterruptedException e) { + LOGGER.error("Failed to release self because ", e); + Thread.currentThread().interrupt(); + return 0; } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index d99c8955ee..7945951e0c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -20,19 +20,38 @@ import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; import org.apache.hugegraph.memory.pool.MemoryPool; +import org.apache.hugegraph.memory.util.QueryOutOfMemoryException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class TaskMemoryPool extends AbstractMemoryPool { + private static final Logger LOGGER = LoggerFactory.getLogger(TaskMemoryPool.class); + public TaskMemoryPool(MemoryPool parent, String poolName, MemoryManager memoryManager) { super(parent, poolName, memoryManager); } @Override - public long requestMemory(long bytes) { - long parentRes = getParentPool().requestMemory(bytes); - if (parentRes > 0) { - stats.setAllocatedBytes(stats.getAllocatedBytes() + parentRes); + public long requestMemoryInternal(long bytes) throws QueryOutOfMemoryException { + if (isClosed) { + LOGGER.warn("[{}] is already closed, will abort this request", this); + return 0; + } + try { + if (isBeingArbitrated.get()) { + condition.await(); + } + long parentRes = getParentPool().requestMemoryInternal(bytes); + if (parentRes > 0) { + stats.setAllocatedBytes(stats.getAllocatedBytes() + parentRes); + } + return parentRes; + } catch (InterruptedException e) { + LOGGER.error("Failed to release self because ", e); + Thread.currentThread().interrupt(); + return 0; } - return parentRes; + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/QueryOutOfMemoryException.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/QueryOutOfMemoryException.java new file mode 100644 index 0000000000..0accda9168 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/QueryOutOfMemoryException.java @@ -0,0 +1,33 @@ +/* + * 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.hugegraph.memory.util; + +public class QueryOutOfMemoryException extends Exception { + + public QueryOutOfMemoryException(String message) { + super(message); + } + + public QueryOutOfMemoryException(String message, Throwable cause) { + super(message, cause); + } + + public QueryOutOfMemoryException(Exception e) { + super(e); + } + +} From 5904909fbdf297edb434f0560ab1aa34e15a4f18 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Wed, 23 Oct 2024 14:13:35 +0800 Subject: [PATCH 15/48] fix review --- .../hugegraph/memory/MemoryManager.java | 36 +++++----- .../arbitrator/MemoryArbitratorImpl.java | 25 ++++--- .../memory/pool/AbstractMemoryPool.java | 52 +++++++------- .../memory/pool/impl/OperatorMemoryPool.java | 72 +++++++++---------- .../memory/pool/impl/QueryMemoryPool.java | 50 ++++++------- .../memory/pool/impl/TaskMemoryPool.java | 14 ++-- 6 files changed, 124 insertions(+), 125 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index a6f4e9c295..da13ef81e1 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -37,7 +37,7 @@ public class MemoryManager { - private static final Logger LOGGER = LoggerFactory.getLogger(MemoryManager.class); + private static final Logger LOG = LoggerFactory.getLogger(MemoryManager.class); private static final String QUERY_MEMORY_POOL_NAME_PREFIX = "QueryMemoryPool"; private static final String ARBITRATE_MEMORY_POOL_NAME = "ArbitrateMemoryPool"; private static final String DELIMINATOR = "_"; @@ -66,12 +66,12 @@ public MemoryPool addQueryMemoryPool() { System.currentTimeMillis(); MemoryPool queryPool = new QueryMemoryPool(poolName, this); queryMemoryPools.add(queryPool); - LOGGER.info("Manager added query memory pool {}", queryPool); + LOG.info("Manager added query memory pool {}", queryPool); return queryPool; } public void gcQueryMemoryPool(MemoryPool pool) { - LOGGER.info("Manager gc query memory pool {}", pool); + LOG.info("Manager gc query memory pool {}", pool); queryMemoryPools.remove(pool); long reclaimedMemory = pool.getAllocatedBytes(); pool.releaseSelf(String.format("GC query memory pool %s", pool)); @@ -79,7 +79,7 @@ public void gcQueryMemoryPool(MemoryPool pool) { } public long triggerLocalArbitration(MemoryPool targetPool, long neededBytes) { - LOGGER.info("LocalArbitration triggered by {}: needed bytes={}", targetPool, neededBytes); + LOG.info("LocalArbitration triggered by {}: needed bytes={}", targetPool, neededBytes); Future future = arbitrateExecutor.submit( () -> memoryArbitrator.reclaimLocally(targetPool, neededBytes)); @@ -87,17 +87,17 @@ public long triggerLocalArbitration(MemoryPool targetPool, long neededBytes) { return future.get(MemoryArbitrator.MAX_WAIT_TIME_FOR_LOCAL_RECLAIM, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { - LOGGER.warn("MemoryManager: arbitration locally for {} timed out", targetPool, e); + LOG.warn("MemoryManager: arbitration locally for {} timed out", targetPool, e); } catch (InterruptedException | ExecutionException e) { - LOGGER.error("MemoryManager: arbitration locally for {} interrupted or failed", - targetPool, - e); + LOG.error("MemoryManager: arbitration locally for {} interrupted or failed", + targetPool, + e); } return 0; } public long triggerGlobalArbitration(MemoryPool requestPool, long neededBytes) { - LOGGER.info("GlobalArbitration triggered by {}: needed bytes={}", requestPool, neededBytes); + LOG.info("GlobalArbitration triggered by {}: needed bytes={}", requestPool, neededBytes); Future future = arbitrateExecutor.submit( () -> memoryArbitrator.reclaimGlobally(requestPool, neededBytes)); @@ -105,10 +105,10 @@ public long triggerGlobalArbitration(MemoryPool requestPool, long neededBytes) { return future.get(MemoryArbitrator.MAX_WAIT_TIME_FOR_GLOBAL_RECLAIM, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { - LOGGER.warn("MemoryManager: arbitration globally for {} timed out", requestPool, e); + LOG.warn("MemoryManager: arbitration globally for {} timed out", requestPool, e); } catch (InterruptedException | ExecutionException e) { - LOGGER.error("MemoryManager: arbitration globally for {} interrupted or failed", - requestPool, e); + LOG.error("MemoryManager: arbitration globally for {} interrupted or failed", + requestPool, e); } return 0; } @@ -116,15 +116,15 @@ public long triggerGlobalArbitration(MemoryPool requestPool, long neededBytes) { public synchronized long handleRequestFromQueryPool(long size) { // 1. check whole memory capacity. if (currentAvailableMemoryInBytes.get() < size) { - LOGGER.info("There isn't enough memory for query pool to expand itself: " + - "requestSize={}, remainingCapacity={}", size, - currentAvailableMemoryInBytes.get()); + LOG.info("There isn't enough memory for query pool to expand itself: " + + "requestSize={}, remainingCapacity={}", size, + currentAvailableMemoryInBytes.get()); return -1; } currentAvailableMemoryInBytes.addAndGet(-size); - LOGGER.info("Expand query pool successfully: " + - "requestSize={}, afterThisExpandingRemainingCapacity={}", size, - currentAvailableMemoryInBytes.get()); + LOG.info("Expand query pool successfully: " + + "requestSize={}, afterThisExpandingRemainingCapacity={}", size, + currentAvailableMemoryInBytes.get()); return size; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java index a85d13acf8..67e33a5a8b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java @@ -24,10 +24,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -// TODO: consider concurrency public class MemoryArbitratorImpl implements MemoryArbitrator { - private static final Logger LOGGER = LoggerFactory.getLogger(MemoryArbitratorImpl.class); + private static final Logger LOG = LoggerFactory.getLogger(MemoryArbitratorImpl.class); private final MemoryManager memoryManager; public MemoryArbitratorImpl(MemoryManager memoryManager) { @@ -38,10 +37,10 @@ public MemoryArbitratorImpl(MemoryManager memoryManager) { public long reclaimLocally(MemoryPool queryPool, long neededBytes) { long startTime = System.currentTimeMillis(); long res = queryPool.tryToReclaimLocalMemory(neededBytes); - LOGGER.info("[{}] reclaim local memory: {} bytes, took {} ms", - Thread.currentThread().getName(), - res, - System.currentTimeMillis() - startTime); + LOG.info("[{}] reclaim local memory: {} bytes, took {} ms", + Thread.currentThread().getName(), + res, + System.currentTimeMillis() - startTime); return res; } @@ -50,14 +49,14 @@ public long reclaimGlobally(MemoryPool queryPool, long neededBytes) { long startTime = System.currentTimeMillis(); long totalReclaimedBytes = 0; long currentNeededBytes = neededBytes; - Queue currentMemoryPool = memoryManager.getCurrentQueryMemoryPools(); + Queue currentMemoryPool = this.memoryManager.getCurrentQueryMemoryPools(); while (!currentMemoryPool.isEmpty()) { MemoryPool memoryPool = currentMemoryPool.poll(); if (memoryPool.equals(queryPool)) { continue; } - LOGGER.info("Global reclaim triggerred by {} select {} to reclaim", queryPool, - memoryPool); + LOG.info("Global reclaim triggerred by {} select {} to reclaim", queryPool, + memoryPool); long res = memoryPool.tryToReclaimLocalMemory(currentNeededBytes); totalReclaimedBytes += res; currentNeededBytes -= res; @@ -65,10 +64,10 @@ public long reclaimGlobally(MemoryPool queryPool, long neededBytes) { break; } } - LOGGER.info("[{}] reclaim global memory: {} bytes, took {} ms", - Thread.currentThread().getName(), - totalReclaimedBytes, - System.currentTimeMillis() - startTime); + LOG.info("[{}] reclaim global memory: {} bytes, took {} ms", + Thread.currentThread().getName(), + totalReclaimedBytes, + System.currentTimeMillis() - startTime); return totalReclaimedBytes; } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 8c7e537246..639874d639 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -31,7 +31,7 @@ public abstract class AbstractMemoryPool implements MemoryPool { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractMemoryPool.class); + private static final Logger LOG = LoggerFactory.getLogger(AbstractMemoryPool.class); private final Queue children = new PriorityQueue<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); protected final MemoryManager memoryManager; @@ -52,10 +52,10 @@ public AbstractMemoryPool(MemoryPool parent, String memoryPoolName, @Override public long tryToReclaimLocalMemory(long neededBytes) { if (isClosed) { - LOGGER.warn("[{}] is already closed, will abort this reclaim", this); + LOG.warn("[{}] is already closed, will abort this reclaim", this); return 0; } - LOGGER.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); + LOG.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); long totalReclaimedBytes = 0; long currentNeededBytes = neededBytes; try { @@ -72,10 +72,10 @@ public long tryToReclaimLocalMemory(long neededBytes) { } } } - LOGGER.info("[{}] has finished to reclaim memory: totalReclaimedBytes={}, " + - "neededBytes={}", - this, - totalReclaimedBytes, neededBytes); + LOG.info("[{}] has finished to reclaim memory: totalReclaimedBytes={}, " + + "neededBytes={}", + this, + totalReclaimedBytes, neededBytes); return totalReclaimedBytes; } finally { this.stats.setNumShrinks(this.stats.getNumShrinks() + 1); @@ -93,19 +93,19 @@ public long tryToReclaimLocalMemory(long neededBytes) { @Override public synchronized void releaseSelf(String reason) { try { - if (isBeingArbitrated.get()) { - condition.await(); + if (this.isBeingArbitrated.get()) { + this.condition.await(); } - LOGGER.info("[{}] starts to releaseSelf because of {}", this, reason); + LOG.info("[{}] starts to releaseSelf because of {}", this, reason); this.isClosed = true; // update father - Optional.ofNullable(parent).ifPresent(parent -> parent.gcChildPool(this, false)); + Optional.ofNullable(this.parent).ifPresent(parent -> parent.gcChildPool(this, false)); for (MemoryPool child : this.children) { gcChildPool(child, true); } - LOGGER.info("[{}] finishes to releaseSelf", this); + LOG.info("[{}] finishes to releaseSelf", this); } catch (InterruptedException e) { - LOGGER.error("Failed to release self because ", e); + LOG.error("Failed to release self because ", e); Thread.currentThread().interrupt(); } finally { // Make these objs be GCed by JVM quickly. @@ -120,9 +120,9 @@ public void gcChildPool(MemoryPool child, boolean force) { child.releaseSelf(String.format("[%s] releaseChildPool", this)); } // reclaim child's memory and update stats - stats.setAllocatedBytes( + this.stats.setAllocatedBytes( stats.getAllocatedBytes() - child.getAllocatedBytes()); - stats.setUsedBytes(stats.getUsedBytes() - child.getUsedBytes()); + this.stats.setUsedBytes(this.stats.getUsedBytes() - child.getUsedBytes()); memoryManager.consumeAvailableMemory(-child.getAllocatedBytes()); this.children.remove(child); } @@ -130,12 +130,12 @@ public void gcChildPool(MemoryPool child, boolean force) { @Override public Object tryToAcquireMemoryInternal(long bytes) { if (isClosed) { - LOGGER.warn("[{}] is already closed, will abort this allocate", this); + LOG.warn("[{}] is already closed, will abort this allocate", this); return 0; } // just record how much memory is used(update stats) - stats.setUsedBytes(stats.getUsedBytes() + bytes); - stats.setCumulativeBytes(stats.getCumulativeBytes() + bytes); + this.stats.setUsedBytes(this.stats.getUsedBytes() + bytes); + this.stats.setCumulativeBytes(this.stats.getCumulativeBytes() + bytes); return null; } @@ -146,38 +146,38 @@ public Object requireMemory(long bytes) { @Override public long getMaxCapacityBytes() { - return Optional.of(stats).map(MemoryPoolStats::getMaxCapacity).orElse(0L); + return Optional.of(this.stats).map(MemoryPoolStats::getMaxCapacity).orElse(0L); } @Override public long getUsedBytes() { - return Optional.of(stats).map(MemoryPoolStats::getUsedBytes).orElse(0L); + return Optional.of(this.stats).map(MemoryPoolStats::getUsedBytes).orElse(0L); } @Override public long getFreeBytes() { - return Optional.of(stats) + return Optional.of(this.stats) .map(stats -> stats.getAllocatedBytes() - stats.getUsedBytes()).orElse(0L); } @Override public long getAllocatedBytes() { - return Optional.of(stats).map(MemoryPoolStats::getAllocatedBytes).orElse(0L); + return Optional.of(this.stats).map(MemoryPoolStats::getAllocatedBytes).orElse(0L); } @Override public MemoryPoolStats getSnapShot() { - return stats; + return this.stats; } @Override public MemoryPool getParentPool() { - return parent; + return this.parent; } @Override public String getName() { - return stats.getMemoryPoolName(); + return this.stats.getMemoryPoolName(); } @Override @@ -187,7 +187,7 @@ public String toString() { @Override public MemoryPool findRootQueryPool() { - if (parent == null) { + if (this.parent == null) { return this; } return getParentPool().findRootQueryPool(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index b748c48419..eb57cd78d8 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -28,7 +28,7 @@ public class OperatorMemoryPool extends AbstractMemoryPool { - private static final Logger LOGGER = LoggerFactory.getLogger(OperatorMemoryPool.class); + private static final Logger LOG = LoggerFactory.getLogger(OperatorMemoryPool.class); private final MemoryAllocator memoryAllocator; public OperatorMemoryPool(MemoryPool parent, String poolName, @@ -39,18 +39,18 @@ public OperatorMemoryPool(MemoryPool parent, String poolName, @Override public synchronized void releaseSelf(String reason) { - memoryAllocator.releaseMemory(getAllocatedBytes()); + this.memoryAllocator.releaseMemory(getAllocatedBytes()); super.releaseSelf(reason); // TODO: release memory consumer, release byte buffer. } @Override public long tryToReclaimLocalMemory(long neededBytes) { - if (isClosed) { - LOGGER.warn("[{}] is already closed, will abort this reclaim", this); + if (this.isClosed) { + LOG.warn("[{}] is already closed, will abort this reclaim", this); return 0; } - LOGGER.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); + LOG.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); try { this.arbitrationLock.lock(); this.isBeingArbitrated.set(true); @@ -60,21 +60,21 @@ public long tryToReclaimLocalMemory(long neededBytes) { if (reclaimableBytes <= neededBytes) { // 2. update stats stats.setAllocatedBytes(stats.getUsedBytes()); - LOGGER.info("[{}] has tried its best to reclaim memory: " + - "reclaimedBytes={}," + - " " + - "neededBytes={}", - this, - reclaimableBytes, neededBytes); + LOG.info("[{}] has tried its best to reclaim memory: " + + "reclaimedBytes={}," + + " " + + "neededBytes={}", + this, + reclaimableBytes, neededBytes); return reclaimableBytes; } stats.setAllocatedBytes(stats.getAllocatedBytes() - neededBytes); - LOGGER.info("[{}] has reclaim enough memory: " + - "reclaimedBytes={}," + - " " + - "neededBytes={}", - this, - neededBytes, neededBytes); + LOG.info("[{}] has reclaim enough memory: " + + "reclaimedBytes={}," + + " " + + "neededBytes={}", + this, + neededBytes, neededBytes); return neededBytes; } finally { @@ -96,9 +96,9 @@ public Object requireMemory(long bytes) { return tryToAcquireMemoryInternal(realBytes); } catch (QueryOutOfMemoryException e) { // Abort this query - LOGGER.warn("[{}] detected an OOM exception when request memory, will ABORT this " + - "query and release corresponding memory...", - this); + LOG.warn("[{}] detected an OOM exception when request memory, will ABORT this " + + "query and release corresponding memory...", + this); findRootQueryPool().releaseSelf(String.format(e.getMessage())); return null; } finally { @@ -111,28 +111,28 @@ public Object requireMemory(long bytes) { */ @Override public Object tryToAcquireMemoryInternal(long size) { - if (isClosed) { - LOGGER.warn("[{}] is already closed, will abort this allocate", this); + if (this.isClosed) { + LOG.warn("[{}] is already closed, will abort this allocate", this); return 0; } - LOGGER.info("[{}] tryToAcquireMemory: size={}", this, size); + LOG.info("[{}] tryToAcquireMemory: size={}", this, size); // 1. update statistic super.tryToAcquireMemoryInternal(size); // 2. allocate memory, currently use off-heap mode. - return memoryAllocator.tryToAllocate(size); + return this.memoryAllocator.tryToAllocate(size); } @Override public long requestMemoryInternal(long size) throws QueryOutOfMemoryException { - if (isClosed) { - LOGGER.warn("[{}] is already closed, will abort this request", this); + if (this.isClosed) { + LOG.warn("[{}] is already closed, will abort this request", this); return 0; } try { - if (isBeingArbitrated.get()) { - condition.await(); + if (this.isBeingArbitrated.get()) { + this.condition.await(); } - LOGGER.info("[{}] requestMemory: request size={}", this, size); + LOG.info("[{}] requestMemory: request size={}", this, size); // 1. align size long alignedSize = MemoryManageUtils.sizeAlign(size); // 2. reserve(round) @@ -143,20 +143,20 @@ public long requestMemoryInternal(long size) throws QueryOutOfMemoryException { // 3. call father long fatherRes = getParentPool().requestMemoryInternal(neededMemorySize); if (fatherRes < 0) { - LOGGER.error("[{}] requestMemory failed because of OOM, request size={}", this, - size); - stats.setNumAborts(stats.getNumAborts() + 1); + LOG.error("[{}] requestMemory failed because of OOM, request size={}", this, + size); + this.stats.setNumAborts(this.stats.getNumAborts() + 1); throw new QueryOutOfMemoryException(String.format("%s requestMemory failed " + "because of OOM, request " + "size=%s", this, size)); } // 4. update stats - stats.setAllocatedBytes(stats.getAllocatedBytes() + neededMemorySize); - stats.setNumExpands(stats.getNumExpands() + 1); - LOGGER.info("[{}] requestMemory success: requestedMemorySize={}", this, fatherRes); + this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + neededMemorySize); + this.stats.setNumExpands(this.stats.getNumExpands() + 1); + LOG.info("[{}] requestMemory success: requestedMemorySize={}", this, fatherRes); return fatherRes; } catch (InterruptedException e) { - LOGGER.error("Failed to release self because ", e); + LOG.error("Failed to release self because ", e); Thread.currentThread().interrupt(); return 0; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 19a79b9490..be08827d86 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -26,7 +26,7 @@ public class QueryMemoryPool extends AbstractMemoryPool { - private static final Logger LOGGER = LoggerFactory.getLogger(QueryMemoryPool.class); + private static final Logger LOG = LoggerFactory.getLogger(QueryMemoryPool.class); // TODO: read from conf private static final long QUERY_POOL_MAX_CAPACITY = Bytes.MB * 100; @@ -37,23 +37,23 @@ public QueryMemoryPool(String poolName, MemoryManager memoryManager) { @Override public long requestMemoryInternal(long bytes) { - if (isClosed) { - LOGGER.warn("[{}] is already closed, will abort this request", this); + if (this.isClosed) { + LOG.warn("[{}] is already closed, will abort this request", this); return 0; } try { - if (isBeingArbitrated.get()) { - condition.await(); + if (this.isBeingArbitrated.get()) { + this.condition.await(); } // 1. check whether self capacity is enough if (getMaxCapacityBytes() - stats.getAllocatedBytes() < bytes) { // 2.1 if not, first try to acquire memory from manager long managerReturnedMemoryInBytes = tryToExpandSelfCapacity(bytes); if (managerReturnedMemoryInBytes > 0) { - stats.setMaxCapacity(getMaxCapacityBytes() + managerReturnedMemoryInBytes); - stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); - stats.setNumExpands(stats.getNumExpands() + 1); - memoryManager.consumeAvailableMemory(bytes); + this.stats.setMaxCapacity(getMaxCapacityBytes() + managerReturnedMemoryInBytes); + this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + bytes); + this.stats.setNumExpands(this.stats.getNumExpands() + 1); + this.memoryManager.consumeAvailableMemory(bytes); return bytes; } // 2.2 if requiring memory from manager failed, call manager to invoke arbitrate @@ -61,49 +61,49 @@ public long requestMemoryInternal(long bytes) { return requestMemoryThroughArbitration(bytes); } else { // 3. if capacity is enough, return success - stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); - memoryManager.consumeAvailableMemory(bytes); + this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + bytes); + this.memoryManager.consumeAvailableMemory(bytes); return bytes; } } catch (InterruptedException e) { - LOGGER.error("Failed to release self because ", e); + LOG.error("Failed to release self because ", e); Thread.currentThread().interrupt(); return 0; } } private long tryToExpandSelfCapacity(long size) { - LOGGER.info("[{}] try to expand its capacity: size={}", this, size); + LOG.info("[{}] try to expand its capacity: size={}", this, size); long alignedSize = MemoryManageUtils.sizeAlign(size); long realNeededSize = MemoryManageUtils.roundDelta(getAllocatedBytes(), alignedSize); - return memoryManager.handleRequestFromQueryPool(realNeededSize); + return this.memoryManager.handleRequestFromQueryPool(realNeededSize); } private long requestMemoryThroughArbitration(long bytes) { - LOGGER.info("[{}] try to request memory from manager through arbitration: size={}", this, - bytes); - stats.setNumExpands(stats.getNumExpands() + 1); - long reclaimedBytes = memoryManager.triggerLocalArbitration(this, bytes); + LOG.info("[{}] try to request memory from manager through arbitration: size={}", this, + bytes); + this.stats.setNumExpands(this.stats.getNumExpands() + 1); + long reclaimedBytes = this.memoryManager.triggerLocalArbitration(this, bytes); // 1. if arbitrate successes, update stats and return success if (reclaimedBytes - bytes >= 0) { // here we don't update capacity & reserved & allocated, because memory is // reclaimed from queryPool itself. - memoryManager.consumeAvailableMemory(bytes); + this.memoryManager.consumeAvailableMemory(bytes); return bytes; } else { // 2. if still not enough, try to reclaim globally long globalArbitrationNeededBytes = bytes - reclaimedBytes; - long globalReclaimedBytes = memoryManager.triggerGlobalArbitration(this, - globalArbitrationNeededBytes); + long globalReclaimedBytes = this.memoryManager.triggerGlobalArbitration(this, + globalArbitrationNeededBytes); reclaimedBytes += globalReclaimedBytes; // 3. if memory is enough, update stats and return success if (reclaimedBytes - bytes >= 0) { // add capacity - stats.setMaxCapacity(stats.getMaxCapacity() + globalReclaimedBytes); - stats.setAllocatedBytes(stats.getAllocatedBytes() + bytes); - stats.setNumExpands(stats.getNumExpands() + 1); - memoryManager.consumeAvailableMemory(bytes); + this.stats.setMaxCapacity(this.stats.getMaxCapacity() + globalReclaimedBytes); + this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + bytes); + this.stats.setNumExpands(this.stats.getNumExpands() + 1); + this.memoryManager.consumeAvailableMemory(bytes); return bytes; } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index 7945951e0c..39489e458d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -26,7 +26,7 @@ public class TaskMemoryPool extends AbstractMemoryPool { - private static final Logger LOGGER = LoggerFactory.getLogger(TaskMemoryPool.class); + private static final Logger LOG = LoggerFactory.getLogger(TaskMemoryPool.class); public TaskMemoryPool(MemoryPool parent, String poolName, MemoryManager memoryManager) { super(parent, poolName, memoryManager); @@ -34,21 +34,21 @@ public TaskMemoryPool(MemoryPool parent, String poolName, MemoryManager memoryMa @Override public long requestMemoryInternal(long bytes) throws QueryOutOfMemoryException { - if (isClosed) { - LOGGER.warn("[{}] is already closed, will abort this request", this); + if (this.isClosed) { + LOG.warn("[{}] is already closed, will abort this request", this); return 0; } try { - if (isBeingArbitrated.get()) { - condition.await(); + if (this.isBeingArbitrated.get()) { + this.condition.await(); } long parentRes = getParentPool().requestMemoryInternal(bytes); if (parentRes > 0) { - stats.setAllocatedBytes(stats.getAllocatedBytes() + parentRes); + this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + parentRes); } return parentRes; } catch (InterruptedException e) { - LOGGER.error("Failed to release self because ", e); + LOG.error("Failed to release self because ", e); Thread.currentThread().interrupt(); return 0; } From 0e70e44ff65aba51613f7904b2d49ba0a145efe5 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Wed, 23 Oct 2024 22:49:24 +0800 Subject: [PATCH 16/48] fury test --- hugegraph-server/hugegraph-core/pom.xml | 10 ++ .../hugegraph/memory/allocator/Bar.java | 15 +++ .../hugegraph/memory/allocator/Foo.java | 18 +++ .../memory/allocator/FuryMemoryAllocator.java | 96 ++++++++++++++++ .../memory/consumer/MemoryConsumer.java | 5 +- .../memory/consumer/impl/EdgeFuryVersion.java | 105 ++++++++++++++++++ .../apache/hugegraph/structure/HugeEdge.java | 4 + .../hugegraph/structure/HugeElement.java | 5 + pom.xml | 2 +- 9 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Bar.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Foo.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/FuryMemoryAllocator.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeFuryVersion.java diff --git a/hugegraph-server/hugegraph-core/pom.xml b/hugegraph-server/hugegraph-core/pom.xml index 6b6a37e7ad..99d9658c71 100644 --- a/hugegraph-server/hugegraph-core/pom.xml +++ b/hugegraph-server/hugegraph-core/pom.xml @@ -96,6 +96,16 @@ org.apache.tinkerpop gremlin-driver + + org.apache.fury + fury-core + 0.9.0-SNAPSHOT + + + org.apache.fury + fury-format + 0.9.0-SNAPSHOT + diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Bar.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Bar.java new file mode 100644 index 0000000000..8da17eca09 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Bar.java @@ -0,0 +1,15 @@ +package org.apache.hugegraph.memory.allocator; + +import java.util.Arrays; +import java.util.List; + +public class Bar { + + public String f1; + public List f2; + + @Override + public String toString() { + return f1 + "\n" + Arrays.toString(f2.toArray()); + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Foo.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Foo.java new file mode 100644 index 0000000000..3e96a6d1b0 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Foo.java @@ -0,0 +1,18 @@ +package org.apache.hugegraph.memory.allocator; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class Foo { + + public int f1; + public List f2; + public Map f3; + public List f4; + + @Override + public String toString() { + return f1 + "\n" + Arrays.toString(f2.toArray()) + "\n" + Arrays.toString(f4.toArray()); + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/FuryMemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/FuryMemoryAllocator.java new file mode 100644 index 0000000000..8cb9bf78cd --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/FuryMemoryAllocator.java @@ -0,0 +1,96 @@ +/* + * 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.hugegraph.memory.allocator; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.LongStream; + +import org.apache.fury.format.encoder.Encoders; +import org.apache.fury.format.encoder.RowEncoder; +import org.apache.fury.format.row.binary.BinaryArray; +import org.apache.fury.format.row.binary.BinaryRow; +import org.apache.hugegraph.memory.MemoryManager; + +public class FuryMemoryAllocator implements MemoryAllocator { + + private final MemoryManager memoryManager; + + public FuryMemoryAllocator(MemoryManager memoryManager) { + this.memoryManager = memoryManager; + } + + @Override + public BinaryRow forceAllocate(long size) { + return null; + } + + @Override + public BinaryRow tryToAllocate(long size) { + return null; + } + + @Override + public void releaseMemory(long size) { + memoryManager.getCurrentOffHeapAllocatedMemory().addAndGet(-size); + } + + public static void main(String[] args) { + RowEncoder encoder = Encoders.bean(Foo.class); + Foo foo = new Foo(); + foo.f1 = 10; + foo.f2 = IntStream.range(0, 1000000).boxed().collect(Collectors.toList()); + foo.f3 = + IntStream.range(0, 1000000).boxed().collect(Collectors.toMap(i -> "k" + i, i -> i)); + List bars = new ArrayList<>(1000000); + for (int i = 0; i < 1000000; i++) { + Bar bar = new Bar(); + bar.f1 = "s" + i; + bar.f2 = LongStream.range(0, 10).boxed().collect(Collectors.toList()); + bars.add(bar); + } + foo.f4 = bars; + // Can be zero-copy read by python + BinaryRow binaryRow = encoder.toRow(foo); + foo = null; + for (int i = 0; i < 1000; i++) { + System.gc(); + } + // can be data from python + Foo newFoo = encoder.fromRow(binaryRow); + System.out.println(newFoo); + // zero-copy read List f2 + BinaryArray binaryArray2 = binaryRow.getArray(1); + // zero-copy read List f4 + BinaryArray binaryArray4 = binaryRow.getArray(3); + // zero-copy read 11th element of `readList f4` + BinaryRow barStruct = binaryArray4.getStruct(10); + // zero-copy read 6th of f2 of 11th element of `readList f4` + barStruct.getArray(1).getInt64(5); + RowEncoder barEncoder = Encoders.bean(Bar.class); + // deserialize part of data. + Bar newBar = barEncoder.fromRow(barStruct); + Bar newBar2 = barEncoder.fromRow(binaryArray4.getStruct(20)); + System.out.println(newBar); + System.out.println(newBar2); + } +} + + diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java index ca936c7754..df026d9b00 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java @@ -17,7 +17,10 @@ package org.apache.hugegraph.memory.consumer; -// TODO(pjz): integrated it with HG objects such as edges and vertex. +import org.apache.fury.format.row.binary.BinaryRow; + public interface MemoryConsumer { + // BinaryRow deserializeToFury(Class beanClass, Object value); + } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeFuryVersion.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeFuryVersion.java new file mode 100644 index 0000000000..3efc36ba32 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeFuryVersion.java @@ -0,0 +1,105 @@ +/* + * 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.hugegraph.memory.consumer.impl; + +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.ex.ConfigurationException; +import org.apache.commons.configuration2.io.FileHandler; +import org.apache.fury.format.encoder.Encoders; +import org.apache.fury.format.encoder.RowEncoder; +import org.apache.fury.format.row.binary.BinaryRow; +import org.apache.hugegraph.HugeGraph; +import org.apache.hugegraph.StandardHugeGraph; +import org.apache.hugegraph.backend.id.EdgeId; +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.config.HugeConfig; +import org.apache.hugegraph.memory.allocator.Bar; +import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.schema.SchemaManager; +import org.apache.hugegraph.structure.HugeEdge; +import org.apache.hugegraph.structure.HugeVertex; +import org.apache.hugegraph.type.define.Directions; + +public class EdgeFuryVersion extends HugeEdge implements MemoryConsumer { + + private final RowEncoder idRowEncoder = Encoders.bean(EdgeId.class); + private final RowEncoder barEncoder = Encoders.bean(Bar.class); + + private HugeEdge tmpOnHeapEdge; + private BinaryRow furyEdge; + + public EdgeFuryVersion(HugeEdge edge) { + this.tmpOnHeapEdge = edge; + } + + public void deserialize() { + + RowEncoder selfEncoder = Encoders.bean(HugeEdge.class); + furyEdge = selfEncoder.toRow(tmpOnHeapEdge); + // let GC collect the tmp onHeap memory edge + tmpOnHeapEdge = null; + } + + private Id getId() { + BinaryRow idStruct = furyEdge.getStruct(0); + return idRowEncoder.fromRow(idStruct); + } + + public void printSchema() { + System.out.println(furyEdge.getSchema()); + } + + public static HugeGraph buildGraph() throws ConfigurationException { + String PATH = + "/Users/pengjunzhi/THU/incubator-hugegraph/hugegraph-commons/hugegraph-common/src" + + "/test/java/org/apache/hugegraph/unit/config/"; + String CONF = PATH + "test.conf"; + PropertiesConfiguration configuration = new PropertiesConfiguration(); + FileHandler fileHandler = new FileHandler(configuration); + fileHandler.load(CONF); + HugeConfig config = new HugeConfig(configuration); + HugeGraph graph = new StandardHugeGraph(config); + SchemaManager schema = graph.schema(); + schema.propertyKey("name").asText().create(); + schema.vertexLabel("book") + .properties("name") + .primaryKeys("name") + .enableLabelIndex(false) + .create(); + return graph; + } + + private static Id buildId(HugeGraph graph) { + HugeVertex java = new HugeVertex(graph, IdGenerator.of("java"), + graph.vertexLabel("book")); + Id id = new EdgeId(java, Directions.OUT, IdGenerator.of("test"), IdGenerator.of("test"), + "test", java); + return id; + } + + public static void main(String[] args) throws ConfigurationException { + HugeGraph graph = buildGraph(); + Id id = buildId(graph); + HugeEdge testEdge = new HugeEdge(graph, id, EdgeLabel.NONE); + EdgeFuryVersion edgeFuryVersion = new EdgeFuryVersion(testEdge); + edgeFuryVersion.deserialize(); + edgeFuryVersion.printSchema(); + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java index 5bf7011a6f..ff187bdbe4 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java @@ -59,6 +59,10 @@ public class HugeEdge extends HugeElement implements Edge, Cloneable { private HugeVertex targetVertex; private boolean isOutEdge; + public HugeEdge() { + this.label = null; + } + public HugeEdge(HugeVertex owner, Id id, EdgeLabel label, HugeVertex other) { this(owner.graph(), id, label); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeElement.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeElement.java index adb12f31bc..7bfea20abc 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeElement.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeElement.java @@ -66,6 +66,11 @@ public abstract class HugeElement implements Element, GraphType, Idfiable, Compa private boolean propLoaded; private boolean defaultValueUpdated; + public HugeElement() { + // empty constructor + this.graph = null; + } + public HugeElement(final HugeGraph graph) { E.checkArgument(graph != null, "HugeElement graph can't be null"); this.graph = graph; diff --git a/pom.xml b/pom.xml index 1fa07660ee..f24b611ae2 100644 --- a/pom.xml +++ b/pom.xml @@ -94,7 +94,7 @@ 11 UTF-8 bash - 1.5.0 + 1.3.0 From 5d7154127e0498c65b25780eeb09a4a4863321fe Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Wed, 23 Oct 2024 22:49:53 +0800 Subject: [PATCH 17/48] offHeap magic --- .../hugegraph/memory/consumer/impl/EdgeOffHeapVersion.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeOffHeapVersion.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeOffHeapVersion.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeOffHeapVersion.java new file mode 100644 index 0000000000..da262e1eda --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeOffHeapVersion.java @@ -0,0 +1,5 @@ +package org.apache.hugegraph.memory.consumer.impl; + +public class EdgeOffHeapVersion { + +} From f73f0ab8d6d8db2a9015621f17aee16cf12a6d48 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Wed, 23 Oct 2024 22:49:56 +0800 Subject: [PATCH 18/48] Revert "fury test" This reverts commit 0e70e44ff65aba51613f7904b2d49ba0a145efe5. --- hugegraph-server/hugegraph-core/pom.xml | 10 -- .../hugegraph/memory/allocator/Bar.java | 15 --- .../hugegraph/memory/allocator/Foo.java | 18 --- .../memory/allocator/FuryMemoryAllocator.java | 96 ---------------- .../memory/consumer/MemoryConsumer.java | 5 +- .../memory/consumer/impl/EdgeFuryVersion.java | 105 ------------------ .../apache/hugegraph/structure/HugeEdge.java | 4 - .../hugegraph/structure/HugeElement.java | 5 - pom.xml | 2 +- 9 files changed, 2 insertions(+), 258 deletions(-) delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Bar.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Foo.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/FuryMemoryAllocator.java delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeFuryVersion.java diff --git a/hugegraph-server/hugegraph-core/pom.xml b/hugegraph-server/hugegraph-core/pom.xml index 99d9658c71..6b6a37e7ad 100644 --- a/hugegraph-server/hugegraph-core/pom.xml +++ b/hugegraph-server/hugegraph-core/pom.xml @@ -96,16 +96,6 @@ org.apache.tinkerpop gremlin-driver - - org.apache.fury - fury-core - 0.9.0-SNAPSHOT - - - org.apache.fury - fury-format - 0.9.0-SNAPSHOT - diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Bar.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Bar.java deleted file mode 100644 index 8da17eca09..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Bar.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.apache.hugegraph.memory.allocator; - -import java.util.Arrays; -import java.util.List; - -public class Bar { - - public String f1; - public List f2; - - @Override - public String toString() { - return f1 + "\n" + Arrays.toString(f2.toArray()); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Foo.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Foo.java deleted file mode 100644 index 3e96a6d1b0..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/Foo.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.apache.hugegraph.memory.allocator; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -public class Foo { - - public int f1; - public List f2; - public Map f3; - public List f4; - - @Override - public String toString() { - return f1 + "\n" + Arrays.toString(f2.toArray()) + "\n" + Arrays.toString(f4.toArray()); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/FuryMemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/FuryMemoryAllocator.java deleted file mode 100644 index 8cb9bf78cd..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/FuryMemoryAllocator.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.hugegraph.memory.allocator; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.LongStream; - -import org.apache.fury.format.encoder.Encoders; -import org.apache.fury.format.encoder.RowEncoder; -import org.apache.fury.format.row.binary.BinaryArray; -import org.apache.fury.format.row.binary.BinaryRow; -import org.apache.hugegraph.memory.MemoryManager; - -public class FuryMemoryAllocator implements MemoryAllocator { - - private final MemoryManager memoryManager; - - public FuryMemoryAllocator(MemoryManager memoryManager) { - this.memoryManager = memoryManager; - } - - @Override - public BinaryRow forceAllocate(long size) { - return null; - } - - @Override - public BinaryRow tryToAllocate(long size) { - return null; - } - - @Override - public void releaseMemory(long size) { - memoryManager.getCurrentOffHeapAllocatedMemory().addAndGet(-size); - } - - public static void main(String[] args) { - RowEncoder encoder = Encoders.bean(Foo.class); - Foo foo = new Foo(); - foo.f1 = 10; - foo.f2 = IntStream.range(0, 1000000).boxed().collect(Collectors.toList()); - foo.f3 = - IntStream.range(0, 1000000).boxed().collect(Collectors.toMap(i -> "k" + i, i -> i)); - List bars = new ArrayList<>(1000000); - for (int i = 0; i < 1000000; i++) { - Bar bar = new Bar(); - bar.f1 = "s" + i; - bar.f2 = LongStream.range(0, 10).boxed().collect(Collectors.toList()); - bars.add(bar); - } - foo.f4 = bars; - // Can be zero-copy read by python - BinaryRow binaryRow = encoder.toRow(foo); - foo = null; - for (int i = 0; i < 1000; i++) { - System.gc(); - } - // can be data from python - Foo newFoo = encoder.fromRow(binaryRow); - System.out.println(newFoo); - // zero-copy read List f2 - BinaryArray binaryArray2 = binaryRow.getArray(1); - // zero-copy read List f4 - BinaryArray binaryArray4 = binaryRow.getArray(3); - // zero-copy read 11th element of `readList f4` - BinaryRow barStruct = binaryArray4.getStruct(10); - // zero-copy read 6th of f2 of 11th element of `readList f4` - barStruct.getArray(1).getInt64(5); - RowEncoder barEncoder = Encoders.bean(Bar.class); - // deserialize part of data. - Bar newBar = barEncoder.fromRow(barStruct); - Bar newBar2 = barEncoder.fromRow(binaryArray4.getStruct(20)); - System.out.println(newBar); - System.out.println(newBar2); - } -} - - diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java index df026d9b00..ca936c7754 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java @@ -17,10 +17,7 @@ package org.apache.hugegraph.memory.consumer; -import org.apache.fury.format.row.binary.BinaryRow; - +// TODO(pjz): integrated it with HG objects such as edges and vertex. public interface MemoryConsumer { - // BinaryRow deserializeToFury(Class beanClass, Object value); - } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeFuryVersion.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeFuryVersion.java deleted file mode 100644 index 3efc36ba32..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeFuryVersion.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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.hugegraph.memory.consumer.impl; - -import org.apache.commons.configuration2.PropertiesConfiguration; -import org.apache.commons.configuration2.ex.ConfigurationException; -import org.apache.commons.configuration2.io.FileHandler; -import org.apache.fury.format.encoder.Encoders; -import org.apache.fury.format.encoder.RowEncoder; -import org.apache.fury.format.row.binary.BinaryRow; -import org.apache.hugegraph.HugeGraph; -import org.apache.hugegraph.StandardHugeGraph; -import org.apache.hugegraph.backend.id.EdgeId; -import org.apache.hugegraph.backend.id.Id; -import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.config.HugeConfig; -import org.apache.hugegraph.memory.allocator.Bar; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; -import org.apache.hugegraph.schema.EdgeLabel; -import org.apache.hugegraph.schema.SchemaManager; -import org.apache.hugegraph.structure.HugeEdge; -import org.apache.hugegraph.structure.HugeVertex; -import org.apache.hugegraph.type.define.Directions; - -public class EdgeFuryVersion extends HugeEdge implements MemoryConsumer { - - private final RowEncoder idRowEncoder = Encoders.bean(EdgeId.class); - private final RowEncoder barEncoder = Encoders.bean(Bar.class); - - private HugeEdge tmpOnHeapEdge; - private BinaryRow furyEdge; - - public EdgeFuryVersion(HugeEdge edge) { - this.tmpOnHeapEdge = edge; - } - - public void deserialize() { - - RowEncoder selfEncoder = Encoders.bean(HugeEdge.class); - furyEdge = selfEncoder.toRow(tmpOnHeapEdge); - // let GC collect the tmp onHeap memory edge - tmpOnHeapEdge = null; - } - - private Id getId() { - BinaryRow idStruct = furyEdge.getStruct(0); - return idRowEncoder.fromRow(idStruct); - } - - public void printSchema() { - System.out.println(furyEdge.getSchema()); - } - - public static HugeGraph buildGraph() throws ConfigurationException { - String PATH = - "/Users/pengjunzhi/THU/incubator-hugegraph/hugegraph-commons/hugegraph-common/src" + - "/test/java/org/apache/hugegraph/unit/config/"; - String CONF = PATH + "test.conf"; - PropertiesConfiguration configuration = new PropertiesConfiguration(); - FileHandler fileHandler = new FileHandler(configuration); - fileHandler.load(CONF); - HugeConfig config = new HugeConfig(configuration); - HugeGraph graph = new StandardHugeGraph(config); - SchemaManager schema = graph.schema(); - schema.propertyKey("name").asText().create(); - schema.vertexLabel("book") - .properties("name") - .primaryKeys("name") - .enableLabelIndex(false) - .create(); - return graph; - } - - private static Id buildId(HugeGraph graph) { - HugeVertex java = new HugeVertex(graph, IdGenerator.of("java"), - graph.vertexLabel("book")); - Id id = new EdgeId(java, Directions.OUT, IdGenerator.of("test"), IdGenerator.of("test"), - "test", java); - return id; - } - - public static void main(String[] args) throws ConfigurationException { - HugeGraph graph = buildGraph(); - Id id = buildId(graph); - HugeEdge testEdge = new HugeEdge(graph, id, EdgeLabel.NONE); - EdgeFuryVersion edgeFuryVersion = new EdgeFuryVersion(testEdge); - edgeFuryVersion.deserialize(); - edgeFuryVersion.printSchema(); - } -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java index ff187bdbe4..5bf7011a6f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java @@ -59,10 +59,6 @@ public class HugeEdge extends HugeElement implements Edge, Cloneable { private HugeVertex targetVertex; private boolean isOutEdge; - public HugeEdge() { - this.label = null; - } - public HugeEdge(HugeVertex owner, Id id, EdgeLabel label, HugeVertex other) { this(owner.graph(), id, label); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeElement.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeElement.java index 7bfea20abc..adb12f31bc 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeElement.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeElement.java @@ -66,11 +66,6 @@ public abstract class HugeElement implements Element, GraphType, Idfiable, Compa private boolean propLoaded; private boolean defaultValueUpdated; - public HugeElement() { - // empty constructor - this.graph = null; - } - public HugeElement(final HugeGraph graph) { E.checkArgument(graph != null, "HugeElement graph can't be null"); this.graph = graph; diff --git a/pom.xml b/pom.xml index f24b611ae2..1fa07660ee 100644 --- a/pom.xml +++ b/pom.xml @@ -94,7 +94,7 @@ 11 UTF-8 bash - 1.3.0 + 1.5.0 From 871015e26ae38972cfbee83856d7d0eeab7c542d Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Thu, 24 Oct 2024 00:11:07 +0800 Subject: [PATCH 19/48] offHeap magic util --- .../memory/util/OffHeapMemoryAccess.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryAccess.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryAccess.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryAccess.java new file mode 100644 index 0000000000..345716243b --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryAccess.java @@ -0,0 +1,95 @@ +/* + * 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.hugegraph.memory.util; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sun.misc.Unsafe; + +// NOTE: due to different layout of klass in various versions of JDK, this class may easily crash! +public class OffHeapMemoryAccess { + + private static final Logger LOG = LoggerFactory.getLogger(OffHeapMemoryAccess.class); + private static final Unsafe UNSAFE; + + static { + Unsafe unsafe; + try { + Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + unsafeField.setAccessible(true); + unsafe = (Unsafe) unsafeField.get(null); + } catch (Throwable cause) { + LOG.warn("sun.misc.Unsafe.theUnsafe: unavailable.", cause); + throw new UnsupportedOperationException("Unsafe is not supported in this platform."); + } + UNSAFE = unsafe; + } + + public static long allocateObjectToOffHeap(Object obj) { + long size = sizeOf(obj); + System.out.println(size); + long address = getUnsafe().allocateMemory(size); + // test object was copied to off-heap + getUnsafe().copyMemory( + obj, // source object + 0, // source offset is zero - copy an entire object + null, + // destination is specified by absolute address, so destination object is null + address, // destination address + size + ); + return address; + } + + public static T retrieveObjectFromOffHeap(Class clazz, long address) throws + NoSuchFieldException, + NoSuchMethodException, + InstantiationException, + IllegalAccessException, + InvocationTargetException { + T pointer = clazz.getDeclaredConstructor().newInstance(); + // pointer is just a handler that stores address of some object + // NOTE: we agree that all pointer classes must have a pointer field. + long offset = getUnsafe().objectFieldOffset(clazz.getDeclaredField("pointer")); + // set pointer to off-heap copy of the test object + getUnsafe().putLong(pointer, offset, address); + return pointer; + } + + public static void freeOffHeapMemory(long address) { + getUnsafe().freeMemory(address); + } + + private static Unsafe getUnsafe() { + return UNSAFE; + } + + private static long sizeOf(Object object) { + Unsafe unsafe = getUnsafe(); + return unsafe.getAddress(normalize(unsafe.getInt(object, 4L)) + 8L); + } + + private static long normalize(int value) { + if (value >= 0) return value; + return (~0L >>> 32) & value; + } +} From 8344443574974521939008b94de27ff2327a0c8c Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Sat, 26 Oct 2024 00:18:43 +0800 Subject: [PATCH 20/48] complete adoption for all id --- hugegraph-server/hugegraph-core/pom.xml | 5 + .../backend/cache/CachedBackendStore.java | 11 +- .../apache/hugegraph/backend/id/EdgeId.java | 21 +- .../hugegraph/backend/id/IdGenerator.java | 20 +- .../serializer/BinaryBackendEntry.java | 9 +- .../allocator/OnHeapMemoryStrategy.java | 4 +- .../memory/consumer/MemoryConsumer.java | 26 +- .../consumer/impl/id/BinaryIdOffHeap.java | 132 +++++++++ .../consumer/impl/id/EdgeIdOffHeap.java | 276 ++++++++++++++++++ .../consumer/impl/id/LongIdOffHeap.java | 148 ++++++++++ .../consumer/impl/id/ObjectIdOffHeap.java | 101 +++++++ .../consumer/impl/id/QueryIdOffHeap.java | 113 +++++++ .../consumer/impl/id/StringIdOffHeap.java | 133 +++++++++ .../consumer/impl/id/UuidIdOffHeap.java | 141 +++++++++ .../memory/util/FurySerializationUtils.java | 35 +++ .../util/SerializationRuntimeException.java | 25 ++ 16 files changed, 1169 insertions(+), 31 deletions(-) create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/FurySerializationUtils.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/SerializationRuntimeException.java diff --git a/hugegraph-server/hugegraph-core/pom.xml b/hugegraph-server/hugegraph-core/pom.xml index 6b6a37e7ad..a12580b6d6 100644 --- a/hugegraph-server/hugegraph-core/pom.xml +++ b/hugegraph-server/hugegraph-core/pom.xml @@ -96,6 +96,11 @@ org.apache.tinkerpop gremlin-driver + + org.apache.fury + fury-core + 0.9.0-SNAPSHOT + diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedBackendStore.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedBackendStore.java index e266c0623f..3cc88bbf71 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedBackendStore.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/cache/CachedBackendStore.java @@ -215,16 +215,21 @@ public Number queryNumber(Query query) { /** * Query as an Id for cache */ - static class QueryId implements Id { + public static class QueryId implements Id { - private String query; - private int hashCode; + protected String query; + protected int hashCode; public QueryId(Query q) { this.query = q.toString(); this.hashCode = q.hashCode(); } + public QueryId(String query, int hashCode) { + this.query = query; + this.hashCode = hashCode; + } + @Override public IdType type() { return IdType.UNKNOWN; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/EdgeId.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/EdgeId.java index fe030a153f..14116d8575 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/EdgeId.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/EdgeId.java @@ -32,8 +32,8 @@ * > sortKeys > target-vertex-id } * NOTE: *

1. for edges with edgeLabelType = NORMAL: edgeLabelId = parentEdgeLabelId = subEdgeLabelId; - * for edges with edgeLabelType = PARENT: edgeLabelId = subEdgeLabelId, parentEdgeLabelId = - * edgeLabelId.fatherId + * for edges with edgeLabelType = PARENT: edgeLabelId = subEdgeLabelId, parentEdgeLabelId = + * edgeLabelId.fatherId *

2.if we use `entry.type()` which is IN or OUT as a part of id, * an edge's id will be different due to different directions (belongs * to 2 owner vertex) @@ -49,15 +49,14 @@ public class EdgeId implements Id { HugeKeys.OTHER_VERTEX }; - private final Id ownerVertexId; - private final Directions direction; - private final Id edgeLabelId; - private final Id subLabelId; - private final String sortValues; - private final Id otherVertexId; - - private final boolean directed; - private String cache; + protected final Id ownerVertexId; + protected final Id edgeLabelId; + protected final Id subLabelId; + protected final Id otherVertexId; + protected final Directions direction; + protected final boolean directed; + protected String sortValues; + protected String cache; public EdgeId(HugeVertex ownerVertex, Directions direction, Id edgeLabelId, Id subLabelId, String sortValues, HugeVertex otherVertex) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/IdGenerator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/IdGenerator.java index 9261d31fe8..17cc11684c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/IdGenerator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/IdGenerator.java @@ -119,15 +119,15 @@ public static IdType idType(Id id) { return IdType.UNKNOWN; } - private static int compareType(Id id1, Id id2) { + public static int compareType(Id id1, Id id2) { return idType(id1).ordinal() - idType(id2).ordinal(); } /****************************** id defines ******************************/ - public static final class StringId implements Id { + public static class StringId implements Id { - private final String id; + protected String id; public StringId(String id) { E.checkArgument(!id.isEmpty(), "The id can't be empty"); @@ -196,11 +196,11 @@ public String toString() { } } - public static final class LongId extends Number implements Id { + public static class LongId extends Number implements Id { private static final long serialVersionUID = -7732461469037400190L; - private final long id; + protected Long id; public LongId(long id) { this.id = id; @@ -270,7 +270,7 @@ public String toString() { @Override public int intValue() { - return (int) this.id; + return this.id.intValue(); } @Override @@ -289,9 +289,9 @@ public double doubleValue() { } } - public static final class UuidId implements Id { + public static class UuidId implements Id { - private final UUID uuid; + protected UUID uuid; public UuidId(String string) { this(StringEncoding.uuid(string)); @@ -379,9 +379,9 @@ public String toString() { /** * This class is just used by backend store for wrapper object as Id */ - public static final class ObjectId implements Id { + public static class ObjectId implements Id { - private final Object object; + protected Object object; public ObjectId(Object object) { E.checkNotNull(object, "object"); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryBackendEntry.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryBackendEntry.java index ca605f0b65..9dfb8b4e5c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryBackendEntry.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryBackendEntry.java @@ -49,7 +49,8 @@ public BinaryBackendEntry(HugeType type, byte[] bytes, boolean enablePartition) } // FIXME: `enablePartition` is unused here - public BinaryBackendEntry(HugeType type, byte[] bytes, boolean enablePartition, boolean isOlap) { + public BinaryBackendEntry(HugeType type, byte[] bytes, boolean enablePartition, + boolean isOlap) { this(type, BytesBuffer.wrap(bytes).parseOlapId(type, isOlap)); } @@ -207,10 +208,10 @@ public int hashCode() { return this.id().hashCode() ^ this.columns.size(); } - public static final class BinaryId implements Id { + public static class BinaryId implements Id { - private final byte[] bytes; - private final Id id; + protected byte[] bytes; + protected Id id; public BinaryId(byte[] bytes, Id id) { this.bytes = bytes; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java index 7651bd8cbd..401283254f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java @@ -29,7 +29,7 @@ public OnHeapMemoryStrategy(MemoryManager memoryManager) { } @Override - public Object tryToAllocate(long size) { + public byte[] tryToAllocate(long size) { if (memoryManager.getCurrentOnHeapAllocatedMemory().get() + memoryManager.getCurrentOffHeapAllocatedMemory().get() + size < MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES) { @@ -41,7 +41,7 @@ public Object tryToAllocate(long size) { } @Override - public Object forceAllocate(long size) { + public byte[] forceAllocate(long size) { int sizeOfByte = (int) (size / Bytes.BASE); memoryManager.getCurrentOnHeapAllocatedMemory().addAndGet(sizeOfByte); return new byte[sizeOfByte]; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java index ca936c7754..8eb4cc0489 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java @@ -17,7 +17,31 @@ package org.apache.hugegraph.memory.consumer; -// TODO(pjz): integrated it with HG objects such as edges and vertex. +import org.apache.hugegraph.memory.pool.MemoryPool; + +/** + * This interface is used by immutable, memory-heavy objects which will be stored in off heap. + */ public interface MemoryConsumer { + /** + * This method will read Off heap ByteBuf storing binary data of self. + * + * @return self value + */ + Object zeroCopyReadFromByteBuf(); + + /** + * Serialize to DataOutputStream in stack first, then request an off heap ByteBuf from + * OperatorMemoryPool based on size of DataOutputStream. Finally, serializing it to ByteBuf. + */ + void serializeSelfToByteBuf(); + + /** + * Called after serializingSelfToByteBuf, pointing all self's on heap vars to null, in order + * to let GC release all its on heap memory. + */ + void releaseOriginalOnHeapVars(); + + MemoryPool getOperatorMemoryPool(); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java new file mode 100644 index 0000000000..8215f98749 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java @@ -0,0 +1,132 @@ +/* + * 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.hugegraph.memory.consumer.impl.id; + +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; +import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.pool.MemoryPool; +import org.apache.hugegraph.util.Bytes; +import org.apache.hugegraph.util.E; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; + +public class BinaryIdOffHeap extends BinaryBackendEntry.BinaryId implements MemoryConsumer { + + private final MemoryPool memoryPool; + private final MemoryConsumer originId; + private ByteBuf bytesOffHeap; + + public BinaryIdOffHeap(byte[] bytes, Id id, MemoryPool memoryPool, MemoryConsumer originId) { + super(bytes, id); + this.memoryPool = memoryPool; + this.originId = originId; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + @Override + public void serializeSelfToByteBuf() { + this.bytesOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); + this.bytesOffHeap.markReaderIndex(); + this.bytesOffHeap.writeBytes(bytes); + } + + @Override + public BinaryBackendEntry.BinaryId zeroCopyReadFromByteBuf() { + return new BinaryBackendEntry.BinaryId(ByteBufUtil.getBytes(bytesOffHeap), + (Id) originId.zeroCopyReadFromByteBuf()); + } + + @Override + public MemoryPool getOperatorMemoryPool() { + return this.memoryPool; + } + + @Override + public void releaseOriginalOnHeapVars() { + this.bytes = null; + this.id = null; + } + + @Override + public Object asObject() { + return bytesOffHeap.nioBuffer(); + } + + @Override + public String toString() { + return "0x" + Bytes.toHex(asBytes()); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof BinaryIdOffHeap)) { + return false; + } + return bytesOffHeap.equals(((BinaryIdOffHeap) other).bytesOffHeap); + } + + @Override + public int hashCode() { + return bytesOffHeap.hashCode(); + } + + @Override + public int length() { + return bytesOffHeap.readableBytes(); + } + + @Override + public byte[] asBytes(int offset) { + E.checkArgument(offset < this.bytesOffHeap.readableBytes(), + "Invalid offset %s, must be < length %s", + offset, this.bytesOffHeap.readableBytes()); + try { + // zero-copy read + byte[] tmpBytes = new byte[offset]; + this.bytesOffHeap.readBytes(tmpBytes); + return tmpBytes; + } finally { + this.bytesOffHeap.resetReaderIndex(); + } + } + + @Override + public byte[] asBytes() { + try { + // zero-copy read + byte[] tmpBytes = new byte[bytesOffHeap.readableBytes()]; + this.bytesOffHeap.readBytes(tmpBytes); + return tmpBytes; + } finally { + this.bytesOffHeap.resetReaderIndex(); + } + } + + @Override + public int compareTo(Id other) { + return bytesOffHeap.compareTo(((BinaryIdOffHeap) other).bytesOffHeap); + } + + @Override + public Id origin() { + return (Id) originId.zeroCopyReadFromByteBuf(); + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java new file mode 100644 index 0000000000..98d30f3dd6 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java @@ -0,0 +1,276 @@ +/* + * 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.hugegraph.memory.consumer.impl.id; + +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +import org.apache.hugegraph.backend.id.EdgeId; +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.id.IdUtil; +import org.apache.hugegraph.backend.id.SplicingIdGenerator; +import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.pool.MemoryPool; +import org.apache.hugegraph.structure.HugeVertex; +import org.apache.hugegraph.type.define.Directions; + +import io.netty.buffer.ByteBuf; + +// TODO: rewrite static method in EdgeId +public class EdgeIdOffHeap extends EdgeId implements MemoryConsumer { + + private final MemoryPool memoryPool; + private final MemoryConsumer ownerVertexIdOffHeap; + private final MemoryConsumer edgeLabelIdOffHeap; + private final MemoryConsumer subLabelIdOffHeap; + private final MemoryConsumer otherVertexIdOffHeap; + private ByteBuf sortValuesOffHeap; + private ByteBuf cacheOffHeap; + + public EdgeIdOffHeap(HugeVertex ownerVertex, + Directions direction, + Id edgeLabelId, + Id subLabelId, + String sortValues, + HugeVertex otherVertex, + MemoryPool memoryPool, + MemoryConsumer ownerVertexIdOffHeap, + MemoryConsumer edgeLabelIdOffHeap, + MemoryConsumer subLabelIdOffHeap, + MemoryConsumer otherVertexIdOffHeap) { + super(ownerVertex, direction, edgeLabelId, subLabelId, sortValues, otherVertex); + this.memoryPool = memoryPool; + this.ownerVertexIdOffHeap = ownerVertexIdOffHeap; + this.edgeLabelIdOffHeap = edgeLabelIdOffHeap; + this.subLabelIdOffHeap = subLabelIdOffHeap; + this.otherVertexIdOffHeap = otherVertexIdOffHeap; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + public EdgeIdOffHeap(Id ownerVertexId, + Directions direction, + Id edgeLabelId, + Id subLabelId, + String sortValues, + Id otherVertexId, + MemoryPool memoryPool, + MemoryConsumer ownerVertexIdOffHeap, + MemoryConsumer edgeLabelIdOffHeap, + MemoryConsumer subLabelIdOffHeap, + MemoryConsumer otherVertexIdOffHeap) { + super(ownerVertexId, direction, edgeLabelId, subLabelId, + sortValues, otherVertexId, false); + this.memoryPool = memoryPool; + this.ownerVertexIdOffHeap = ownerVertexIdOffHeap; + this.edgeLabelIdOffHeap = edgeLabelIdOffHeap; + this.subLabelIdOffHeap = subLabelIdOffHeap; + this.otherVertexIdOffHeap = otherVertexIdOffHeap; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + public EdgeIdOffHeap(Id ownerVertexId, + Directions direction, + Id edgeLabelId, + Id subLabelId, + String sortValues, + Id otherVertexId, + boolean directed, + MemoryPool memoryPool, + MemoryConsumer ownerVertexIdOffHeap, + MemoryConsumer edgeLabelIdOffHeap, + MemoryConsumer subLabelIdOffHeap, + MemoryConsumer otherVertexIdOffHeap) { + super(ownerVertexId, direction, edgeLabelId, subLabelId, sortValues, otherVertexId, + directed); + this.memoryPool = memoryPool; + this.ownerVertexIdOffHeap = ownerVertexIdOffHeap; + this.edgeLabelIdOffHeap = edgeLabelIdOffHeap; + this.subLabelIdOffHeap = subLabelIdOffHeap; + this.otherVertexIdOffHeap = otherVertexIdOffHeap; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + @Override + public Object zeroCopyReadFromByteBuf() { + try { + return new EdgeId((HugeVertex) this.ownerVertexIdOffHeap.zeroCopyReadFromByteBuf(), + this.direction, + (Id) this.edgeLabelIdOffHeap.zeroCopyReadFromByteBuf(), + (Id) this.subLabelIdOffHeap.zeroCopyReadFromByteBuf(), + this.sortValuesOffHeap.toString(StandardCharsets.UTF_8), + (HugeVertex) this.otherVertexIdOffHeap.zeroCopyReadFromByteBuf()); + } finally { + this.sortValuesOffHeap.resetReaderIndex(); + } + } + + @Override + public void serializeSelfToByteBuf() { + byte[] stringBytes = sortValues.getBytes((StandardCharsets.UTF_8)); + this.sortValuesOffHeap = (ByteBuf) memoryPool.requireMemory(stringBytes.length); + this.sortValuesOffHeap.markReaderIndex(); + this.sortValuesOffHeap.writeBytes(stringBytes); + } + + @Override + public void releaseOriginalOnHeapVars() { + this.sortValues = null; + } + + @Override + public MemoryPool getOperatorMemoryPool() { + return memoryPool; + } + + @Override + public EdgeId switchDirection() { + Directions newDirection = this.direction.opposite(); + return new EdgeIdOffHeap(this.otherVertexId, + newDirection, + this.edgeLabelId, + this.subLabelId, + this.sortValues, + this.ownerVertexId, + this.memoryPool, + this.ownerVertexIdOffHeap, + this.edgeLabelIdOffHeap, + this.subLabelIdOffHeap, + this.otherVertexIdOffHeap); + } + + @Override + public EdgeId directed(boolean directed) { + return new EdgeIdOffHeap(this.otherVertexId, + this.direction, + this.edgeLabelId, + this.subLabelId, + this.sortValues, + this.ownerVertexId, + directed, + this.memoryPool, + this.ownerVertexIdOffHeap, + this.edgeLabelIdOffHeap, + this.subLabelIdOffHeap, + this.otherVertexIdOffHeap); + } + + @Override + public Id ownerVertexId() { + return (Id) this.ownerVertexIdOffHeap.zeroCopyReadFromByteBuf(); + } + + @Override + public Id edgeLabelId() { + return (Id) this.edgeLabelIdOffHeap.zeroCopyReadFromByteBuf(); + } + + @Override + public Id subLabelId() { + return (Id) this.subLabelIdOffHeap.zeroCopyReadFromByteBuf(); + } + + @Override + public String sortValues() { + try { + return this.sortValuesOffHeap.toString(StandardCharsets.UTF_8); + } finally { + this.sortValuesOffHeap.resetReaderIndex(); + } + } + + @Override + public Id otherVertexId() { + return (Id) this.otherVertexIdOffHeap.zeroCopyReadFromByteBuf(); + } + + @Override + public String asString() { + if (this.cacheOffHeap != null) { + try { + return this.cacheOffHeap.toString(StandardCharsets.UTF_8); + } finally { + this.cacheOffHeap.resetReaderIndex(); + } + } + String tmpCache; + if (this.directed) { + tmpCache = SplicingIdGenerator.concat( + IdUtil.writeString((Id) this.ownerVertexIdOffHeap.zeroCopyReadFromByteBuf()), + this.direction.type().string(), + IdUtil.writeLong((Id) this.edgeLabelIdOffHeap.zeroCopyReadFromByteBuf()), + IdUtil.writeLong((Id) this.subLabelIdOffHeap.zeroCopyReadFromByteBuf()), + this.sortValues(), + IdUtil.writeString((Id) this.otherVertexIdOffHeap.zeroCopyReadFromByteBuf())); + } else { + tmpCache = SplicingIdGenerator.concat( + IdUtil.writeString((Id) this.ownerVertexIdOffHeap.zeroCopyReadFromByteBuf()), + IdUtil.writeLong((Id) this.edgeLabelIdOffHeap.zeroCopyReadFromByteBuf()), + IdUtil.writeLong((Id) this.subLabelIdOffHeap.zeroCopyReadFromByteBuf()), + this.sortValues(), + IdUtil.writeString((Id) this.otherVertexIdOffHeap.zeroCopyReadFromByteBuf())); + } + byte[] tmpCacheBytes = tmpCache.getBytes(StandardCharsets.UTF_8); + this.cacheOffHeap = (ByteBuf) memoryPool.requireMemory(tmpCacheBytes.length); + this.cacheOffHeap.markReaderIndex(); + this.cacheOffHeap.writeBytes(tmpCacheBytes); + return tmpCache; + } + + @Override + public int hashCode() { + if (this.directed) { + return Objects.hash(this.ownerVertexIdOffHeap, + this.direction, + this.edgeLabelIdOffHeap, + this.subLabelIdOffHeap, + this.sortValuesOffHeap, + this.otherVertexIdOffHeap); + } else { + return Objects.hash(this.otherVertexIdOffHeap, + this.edgeLabelIdOffHeap, + this.subLabelIdOffHeap, + this.sortValuesOffHeap, + this.ownerVertexIdOffHeap); + } + } + + @Override + public boolean equals(Object object) { + if (!(object instanceof EdgeIdOffHeap)) { + return false; + } + EdgeIdOffHeap other = (EdgeIdOffHeap) object; + if (this.directed) { + return this.ownerVertexIdOffHeap.equals(other.ownerVertexIdOffHeap) && + this.direction == other.direction && + this.edgeLabelIdOffHeap.equals(other.edgeLabelIdOffHeap) && + this.subLabelIdOffHeap.equals(other.subLabelIdOffHeap) && + this.sortValuesOffHeap.equals(other.sortValuesOffHeap) && + this.otherVertexIdOffHeap.equals(other.otherVertexIdOffHeap); + } else { + return this.otherVertexIdOffHeap.equals(other.otherVertexIdOffHeap) && + this.edgeLabelIdOffHeap.equals(other.edgeLabelIdOffHeap) && + this.subLabelIdOffHeap.equals(other.subLabelIdOffHeap) && + this.sortValuesOffHeap.equals(other.sortValuesOffHeap) && + this.ownerVertexIdOffHeap.equals(other.ownerVertexIdOffHeap); + } + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java new file mode 100644 index 0000000000..6c7bf65d66 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java @@ -0,0 +1,148 @@ +/* + * 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.hugegraph.memory.consumer.impl.id; + +import static org.apache.hugegraph.backend.id.IdGenerator.compareType; + +import java.util.Objects; + +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.pool.MemoryPool; +import org.apache.hugegraph.util.NumericUtil; + +import io.netty.buffer.ByteBuf; + +public class LongIdOffHeap extends IdGenerator.LongId implements MemoryConsumer { + + private final MemoryPool memoryPool; + private ByteBuf idOffHeap; + + public LongIdOffHeap(MemoryPool memoryPool, long id) { + super(id); + this.memoryPool = memoryPool; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + public LongIdOffHeap(MemoryPool memoryPool, byte[] bytes) { + super(bytes); + this.memoryPool = memoryPool; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + @Override + public Object zeroCopyReadFromByteBuf() { + try { + return new IdGenerator.LongId(idOffHeap.readLong()); + } finally { + idOffHeap.resetReaderIndex(); + } + + } + + @Override + public void serializeSelfToByteBuf() { + this.idOffHeap = (ByteBuf) memoryPool.requireMemory(Long.BYTES); + this.idOffHeap.markReaderIndex(); + this.idOffHeap.writeLong(id); + } + + @Override + public void releaseOriginalOnHeapVars() { + this.id = null; + } + + @Override + public MemoryPool getOperatorMemoryPool() { + return memoryPool; + } + + @Override + public long asLong() { + try { + return idOffHeap.readLong(); + } finally { + idOffHeap.resetReaderIndex(); + } + } + + @Override + public Object asObject() { + return this.asLong(); + } + + @Override + public String asString() { + return Long.toString(this.asLong()); + } + + @Override + public byte[] asBytes() { + return NumericUtil.longToBytes(this.asLong()); + } + + @Override + public int compareTo(Id other) { + int cmp = compareType(this, other); + if (cmp != 0) { + return cmp; + } + return Long.compare(this.asLong(), other.asLong()); + } + + @Override + public int hashCode() { + return Objects.hash(idOffHeap); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof Number)) { + return false; + } + return this.asLong() == ((Number) other).longValue(); + } + + @Override + public String toString() { + return String.valueOf(this.asLong()); + } + + @Override + public int intValue() { + return (int) this.asLong(); + } + + @Override + public long longValue() { + return this.asLong(); + } + + @Override + public float floatValue() { + return this.asLong(); + } + + @Override + public double doubleValue() { + return this.asLong(); + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java new file mode 100644 index 0000000000..5bf4a58093 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java @@ -0,0 +1,101 @@ +/* + * 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.hugegraph.memory.consumer.impl.id; + +import java.util.Objects; + +import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.pool.MemoryPool; +import org.apache.hugegraph.memory.util.FurySerializationUtils; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; + +public class ObjectIdOffHeap extends IdGenerator.ObjectId implements MemoryConsumer { + + private final MemoryPool memoryPool; + private ByteBuf objectOffHeap; + + public ObjectIdOffHeap(Object object, MemoryPool memoryPool) { + super(object); + this.memoryPool = memoryPool; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + @Override + public Object zeroCopyReadFromByteBuf() { + return new IdGenerator.ObjectId(FurySerializationUtils.FURY.deserialize( + ByteBufUtil.getBytes(this.objectOffHeap))); + } + + @Override + public void serializeSelfToByteBuf() { + byte[] bytes = FurySerializationUtils.FURY.serialize(object); + this.objectOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); + this.objectOffHeap.markReaderIndex(); + this.objectOffHeap.writeBytes(bytes); + //try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + // ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream)) { + // // serialize attributes to outputStream + // outputStream.writeObject(this.object); + // objectOffHeap = (ByteBuf) memoryPool.requireMemory(byteArrayOutputStream.size()); + // objectOffHeap.writeBytes(byteArrayOutputStream.toByteArray()); + //} catch (IOException e) { + // LOG.error("Unexpected error occurs when serializing ObjectId.", e); + // throw new SerializationRuntimeException(e); + //} + } + + @Override + public void releaseOriginalOnHeapVars() { + this.object = null; + } + + @Override + public MemoryPool getOperatorMemoryPool() { + return memoryPool; + } + + @Override + public Object asObject() { + return FurySerializationUtils.FURY.deserialize(ByteBufUtil.getBytes(objectOffHeap)); + } + + @Override + public int hashCode() { + return Objects.hash(objectOffHeap); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ObjectIdOffHeap)) { + return false; + } + return this.objectOffHeap.equals(((ObjectIdOffHeap) other).objectOffHeap); + } + + @Override + public String toString() { + return super.toString(); + } +} + + + diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java new file mode 100644 index 0000000000..b2852992a9 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java @@ -0,0 +1,113 @@ +/* + * 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.hugegraph.memory.consumer.impl.id; + +import java.nio.charset.StandardCharsets; + +import org.apache.hugegraph.backend.cache.CachedBackendStore; +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.pool.MemoryPool; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; + +public class QueryIdOffHeap extends CachedBackendStore.QueryId implements MemoryConsumer { + + private final MemoryPool memoryPool; + private ByteBuf queryOffHeap; + + public QueryIdOffHeap(MemoryPool memoryPool, Query q) { + super(q); + this.memoryPool = memoryPool; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + @Override + public Object zeroCopyReadFromByteBuf() { + try { + return new CachedBackendStore.QueryId( + this.queryOffHeap.toString(StandardCharsets.UTF_8), + this.hashCode); + } finally { + queryOffHeap.resetReaderIndex(); + } + } + + @Override + public void serializeSelfToByteBuf() { + byte[] stringBytes = query.getBytes((StandardCharsets.UTF_8)); + this.queryOffHeap = (ByteBuf) memoryPool.requireMemory(stringBytes.length); + this.queryOffHeap.markReaderIndex(); + this.queryOffHeap.writeBytes(stringBytes); + } + + @Override + public void releaseOriginalOnHeapVars() { + this.query = null; + } + + @Override + public MemoryPool getOperatorMemoryPool() { + return memoryPool; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof QueryIdOffHeap)) { + return false; + } + return this.queryOffHeap.equals(((QueryIdOffHeap) other).queryOffHeap); + } + + @Override + public int compareTo(Id o) { + return this.asString().compareTo(o.asString()); + } + + @Override + public Object asObject() { + return this.asString(); + } + + @Override + public String asString() { + try { + return this.queryOffHeap.toString(StandardCharsets.UTF_8); + } finally { + this.queryOffHeap.resetReaderIndex(); + } + } + + @Override + public byte[] asBytes() { + return ByteBufUtil.getBytes(this.queryOffHeap); + } + + @Override + public String toString() { + return this.asString(); + } + + @Override + public int length() { + return this.asString().length(); + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java new file mode 100644 index 0000000000..e924a17a61 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java @@ -0,0 +1,133 @@ +/* + * 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.hugegraph.memory.consumer.impl.id; + +import static org.apache.hugegraph.backend.id.IdGenerator.compareType; + +import java.nio.charset.StandardCharsets; + +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.pool.MemoryPool; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; + +public class StringIdOffHeap extends IdGenerator.StringId implements MemoryConsumer { + + private final MemoryPool memoryPool; + private ByteBuf idOffHeap; + + public StringIdOffHeap(MemoryPool memoryPool, String id) { + super(id); + this.memoryPool = memoryPool; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + public StringIdOffHeap(MemoryPool memoryPool, byte[] bytes) { + super(bytes); + this.memoryPool = memoryPool; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + @Override + public Object zeroCopyReadFromByteBuf() { + try { + return new IdGenerator.StringId(idOffHeap.toString(StandardCharsets.UTF_8)); + } finally { + idOffHeap.resetReaderIndex(); + } + } + + @Override + public void serializeSelfToByteBuf() { + byte[] stringBytes = id.getBytes((StandardCharsets.UTF_8)); + this.idOffHeap = (ByteBuf) memoryPool.requireMemory(stringBytes.length); + this.idOffHeap.markReaderIndex(); + this.idOffHeap.writeBytes(stringBytes); + } + + @Override + public void releaseOriginalOnHeapVars() { + this.id = null; + } + + @Override + public MemoryPool getOperatorMemoryPool() { + return memoryPool; + } + + @Override + public Object asObject() { + return this.asString(); + } + + @Override + public String asString() { + try { + return this.idOffHeap.toString(StandardCharsets.UTF_8); + } finally { + this.idOffHeap.resetReaderIndex(); + } + } + + @Override + public long asLong() { + return Long.parseLong(this.asString()); + } + + @Override + public byte[] asBytes() { + return ByteBufUtil.getBytes(this.idOffHeap); + } + + @Override + public int length() { + return this.asString().length(); + } + + @Override + public int compareTo(Id other) { + int cmp = compareType(this, other); + if (cmp != 0) { + return cmp; + } + return this.asString().compareTo(other.asString()); + } + + @Override + public int hashCode() { + return this.idOffHeap.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof StringIdOffHeap)) { + return false; + } + return this.idOffHeap.equals(((StringIdOffHeap) other).idOffHeap); + } + + @Override + public String toString() { + return this.asString(); + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java new file mode 100644 index 0000000000..b21b72ad63 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java @@ -0,0 +1,141 @@ +/* + * 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.hugegraph.memory.consumer.impl.id; + +import static org.apache.hugegraph.backend.id.IdGenerator.compareType; + +import java.io.IOException; +import java.util.UUID; + +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.backend.serializer.BytesBuffer; +import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.pool.MemoryPool; +import org.apache.hugegraph.memory.util.FurySerializationUtils; +import org.apache.hugegraph.memory.util.SerializationRuntimeException; +import org.apache.hugegraph.util.E; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; + +public class UuidIdOffHeap extends IdGenerator.UuidId implements MemoryConsumer { + + private static final Logger LOG = LoggerFactory.getLogger(UuidIdOffHeap.class); + private final MemoryPool memoryPool; + private ByteBuf idOffHeap; + + public UuidIdOffHeap(MemoryPool memoryPool, String string) { + super(string); + this.memoryPool = memoryPool; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + public UuidIdOffHeap(MemoryPool memoryPool, byte[] bytes) { + super(bytes); + this.memoryPool = memoryPool; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + public UuidIdOffHeap(MemoryPool memoryPool, UUID uuid) { + super(uuid); + this.memoryPool = memoryPool; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + @Override + public Object zeroCopyReadFromByteBuf() { + return new IdGenerator.UuidId((UUID) FurySerializationUtils.FURY.deserialize( + ByteBufUtil.getBytes(this.idOffHeap))); + } + + @Override + public void serializeSelfToByteBuf() { + byte[] bytes = FurySerializationUtils.FURY.serialize(uuid); + this.idOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); + this.idOffHeap.markReaderIndex(); + this.idOffHeap.writeBytes(bytes); + } + + @Override + public void releaseOriginalOnHeapVars() { + this.uuid = null; + } + + @Override + public MemoryPool getOperatorMemoryPool() { + return memoryPool; + } + + @Override + public Object asObject() { + return FurySerializationUtils.FURY.deserialize( + ByteBufUtil.getBytes(this.idOffHeap)); + } + + @Override + public String asString() { + return this.asObject().toString(); + } + + @Override + public byte[] asBytes() { + try (BytesBuffer buffer = BytesBuffer.allocate(16)) { + UUID tmp = (UUID) this.asObject(); + buffer.writeLong(tmp.getMostSignificantBits()); + buffer.writeLong(tmp.getLeastSignificantBits()); + return buffer.bytes(); + } catch (IOException e) { + LOG.error("Unexpected error occurs when allocate bytesBuffer.", e); + throw new SerializationRuntimeException(e); + } + } + + @Override + public int compareTo(Id other) { + E.checkNotNull(other, "compare id"); + int cmp = compareType(this, other); + if (cmp != 0) { + return cmp; + } + return ((UUID) this.asObject()).compareTo((UUID) other.asObject()); + } + + @Override + public int hashCode() { + return this.idOffHeap.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof UuidIdOffHeap)) { + return false; + } + return this.asObject().equals(((UuidIdOffHeap) other).asObject()); + } + + @Override + public String toString() { + return this.asString(); + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/FurySerializationUtils.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/FurySerializationUtils.java new file mode 100644 index 0000000000..c8388747da --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/FurySerializationUtils.java @@ -0,0 +1,35 @@ +/* + * 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.hugegraph.memory.util; + +import java.util.UUID; + +import org.apache.fury.Fury; +import org.apache.fury.config.Language; + +public class FurySerializationUtils { + + public static final Fury FURY = Fury.builder().withLanguage(Language.JAVA) + // not mandatory to register all class + .requireClassRegistration(false) + .build(); + + static { + FURY.register(UUID.class); + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/SerializationRuntimeException.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/SerializationRuntimeException.java new file mode 100644 index 0000000000..83ce7c043f --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/SerializationRuntimeException.java @@ -0,0 +1,25 @@ +/* + * 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.hugegraph.memory.util; + +public class SerializationRuntimeException extends RuntimeException { + + public SerializationRuntimeException(Throwable e) { + super("Unexpected error occurs in serialization", e); + } +} From d9cf408a7e0908fbaa9ee28ba0790fe43ab99674 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Sat, 26 Oct 2024 21:14:16 +0800 Subject: [PATCH 21/48] complete property adoption --- .../consumer/impl/EdgeOffHeapVersion.java | 5 - .../consumer/impl/id/ObjectIdOffHeap.java | 10 -- .../property/HugeEdgePropertyOffHeap.java | 93 +++++++++++++++++++ .../property/HugeVertexPropertyOffHeap.java | 85 +++++++++++++++++ .../hugegraph/structure/HugeProperty.java | 2 +- 5 files changed, 179 insertions(+), 16 deletions(-) delete mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeOffHeapVersion.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeOffHeapVersion.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeOffHeapVersion.java deleted file mode 100644 index da262e1eda..0000000000 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/EdgeOffHeapVersion.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.apache.hugegraph.memory.consumer.impl; - -public class EdgeOffHeapVersion { - -} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java index 5bf4a58093..93c8506033 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java @@ -51,16 +51,6 @@ public void serializeSelfToByteBuf() { this.objectOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); this.objectOffHeap.markReaderIndex(); this.objectOffHeap.writeBytes(bytes); - //try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - // ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream)) { - // // serialize attributes to outputStream - // outputStream.writeObject(this.object); - // objectOffHeap = (ByteBuf) memoryPool.requireMemory(byteArrayOutputStream.size()); - // objectOffHeap.writeBytes(byteArrayOutputStream.toByteArray()); - //} catch (IOException e) { - // LOG.error("Unexpected error occurs when serializing ObjectId.", e); - // throw new SerializationRuntimeException(e); - //} } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java new file mode 100644 index 0000000000..c2cf91a713 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java @@ -0,0 +1,93 @@ +/* + * 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.hugegraph.memory.consumer.impl.property; + +import java.util.NoSuchElementException; + +import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.pool.MemoryPool; +import org.apache.hugegraph.memory.util.FurySerializationUtils; +import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.structure.HugeEdge; +import org.apache.hugegraph.structure.HugeEdgeProperty; +import org.apache.hugegraph.structure.HugeElement; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; + +public class HugeEdgePropertyOffHeap extends HugeEdgeProperty implements MemoryConsumer { + + private final MemoryPool memoryPool; + private ByteBuf valueOffHeap; + + public HugeEdgePropertyOffHeap(MemoryPool memoryPool, HugeElement owner, PropertyKey key, + V value) { + super(owner, key, value); + this.memoryPool = memoryPool; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + @Override + public Object zeroCopyReadFromByteBuf() { + return new HugeEdgeProperty<>(this.owner, this.pkey, + FurySerializationUtils.FURY.deserialize( + ByteBufUtil.getBytes(this.valueOffHeap))); + } + + @Override + public void serializeSelfToByteBuf() { + byte[] bytes = FurySerializationUtils.FURY.serialize(this.value); + this.valueOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); + this.valueOffHeap.markReaderIndex(); + this.valueOffHeap.writeBytes(bytes); + } + + @Override + public void releaseOriginalOnHeapVars() { + this.value = null; + } + + @Override + public MemoryPool getOperatorMemoryPool() { + return memoryPool; + } + + @Override + public HugeEdgeProperty switchEdgeOwner() { + assert this.owner instanceof HugeEdge; + return new HugeEdgeProperty<>(((HugeEdge) this.owner).switchOwner(), + this.pkey, this.value()); + } + + @Override + public Object serialValue(boolean encodeNumber) { + return this.pkey.serialValue(this.value(), encodeNumber); + } + + @Override + public boolean isPresent() { + return this.value() != null; + } + + @Override + public V value() throws NoSuchElementException { + return (V) FurySerializationUtils.FURY.deserialize( + ByteBufUtil.getBytes(this.valueOffHeap)); + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java new file mode 100644 index 0000000000..194da3ec15 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java @@ -0,0 +1,85 @@ +/* + * 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.hugegraph.memory.consumer.impl.property; + +import java.util.NoSuchElementException; + +import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.pool.MemoryPool; +import org.apache.hugegraph.memory.util.FurySerializationUtils; +import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.structure.HugeElement; +import org.apache.hugegraph.structure.HugeVertexProperty; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; + +public class HugeVertexPropertyOffHeap extends HugeVertexProperty implements MemoryConsumer { + + private final MemoryPool memoryPool; + private ByteBuf valueOffHeap; + + public HugeVertexPropertyOffHeap(MemoryPool memoryPool, HugeElement owner, PropertyKey key, + V value) { + super(owner, key, value); + this.memoryPool = memoryPool; + serializeSelfToByteBuf(); + releaseOriginalOnHeapVars(); + } + + @Override + public Object zeroCopyReadFromByteBuf() { + return new HugeVertexProperty<>(this.owner, this.pkey, + FurySerializationUtils.FURY.deserialize( + ByteBufUtil.getBytes(this.valueOffHeap))); + } + + @Override + public void serializeSelfToByteBuf() { + byte[] bytes = FurySerializationUtils.FURY.serialize(this.value); + this.valueOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); + this.valueOffHeap.markReaderIndex(); + this.valueOffHeap.writeBytes(bytes); + } + + @Override + public void releaseOriginalOnHeapVars() { + this.value = null; + } + + @Override + public MemoryPool getOperatorMemoryPool() { + return memoryPool; + } + + @Override + public Object serialValue(boolean encodeNumber) { + return this.pkey.serialValue(this.value(), encodeNumber); + } + + @Override + public boolean isPresent() { + return this.value() != null; + } + + @Override + public V value() throws NoSuchElementException { + return (V) FurySerializationUtils.FURY.deserialize( + ByteBufUtil.getBytes(this.valueOffHeap)); + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeProperty.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeProperty.java index cc96bd27b8..65472e148b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeProperty.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeProperty.java @@ -31,7 +31,7 @@ public abstract class HugeProperty implements Property, GraphType { protected final HugeElement owner; protected final PropertyKey pkey; - protected final V value; + protected V value; public HugeProperty(HugeElement owner, PropertyKey pkey, V value) { E.checkArgument(owner != null, "Property owner can't be null"); From aaeacb54d214470a1689c15e77a6bd9438620257 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Sat, 26 Oct 2024 21:39:38 +0800 Subject: [PATCH 22/48] release ByteBuf off heap memory block --- .../memory/allocator/MemoryAllocator.java | 4 +++- .../allocator/NettyMemoryAllocator.java | 20 ++++++++++++++++++- .../allocator/OnHeapMemoryStrategy.java | 7 ++++++- .../memory/consumer/MemoryConsumer.java | 6 ++++++ .../consumer/impl/id/BinaryIdOffHeap.java | 8 ++++++++ .../consumer/impl/id/EdgeIdOffHeap.java | 8 ++++++++ .../consumer/impl/id/LongIdOffHeap.java | 7 +++++++ .../consumer/impl/id/ObjectIdOffHeap.java | 7 +++++++ .../consumer/impl/id/QueryIdOffHeap.java | 7 +++++++ .../consumer/impl/id/StringIdOffHeap.java | 7 +++++++ .../consumer/impl/id/UuidIdOffHeap.java | 7 +++++++ .../property/HugeEdgePropertyOffHeap.java | 7 +++++++ .../property/HugeVertexPropertyOffHeap.java | 7 +++++++ .../memory/pool/AbstractMemoryPool.java | 6 ++++++ .../hugegraph/memory/pool/MemoryPool.java | 3 +++ .../memory/pool/impl/OperatorMemoryPool.java | 17 +++++++++++++++- 16 files changed, 124 insertions(+), 4 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java index 17ed167c17..9e8f443429 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/MemoryAllocator.java @@ -23,5 +23,7 @@ public interface MemoryAllocator { Object forceAllocate(long size); - void releaseMemory(long size); + void returnMemoryToManager(long size); + + void releaseMemoryBlock(Object memoryBlock); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java index a6e4958e85..579bb68829 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java @@ -21,6 +21,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.PooledByteBufAllocator; +import io.netty.util.ReferenceCountUtil; /** * This class makes fully use of Netty's efficient memory management strategy. @@ -50,7 +51,24 @@ public ByteBuf tryToAllocate(long size) { } @Override - public void releaseMemory(long size) { + public void returnMemoryToManager(long size) { memoryManager.getCurrentOffHeapAllocatedMemory().addAndGet(-size); } + + @Override + public void releaseMemoryBlock(Object memoryBlock) { + if (!(memoryBlock instanceof ByteBuf)) { + throw new IllegalArgumentException("memoryBlock must be ByteBuf"); + } + ByteBuf buf = (ByteBuf) memoryBlock; + ReferenceCountUtil.safeRelease(buf, ReferenceCountUtil.refCnt(buf)); + } + + public static void main(String[] args) { + MemoryAllocator netty = new NettyMemoryAllocator(null); + ByteBuf buf = (ByteBuf) netty.forceAllocate(1024); + System.out.println(ReferenceCountUtil.refCnt(buf)); + netty.releaseMemoryBlock(buf); + System.out.println(ReferenceCountUtil.refCnt(buf)); + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java index 401283254f..cf5d57a9cd 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java @@ -48,7 +48,12 @@ public byte[] forceAllocate(long size) { } @Override - public void releaseMemory(long size) { + public void returnMemoryToManager(long size) { memoryManager.getCurrentOnHeapAllocatedMemory().addAndGet(-size); } + + @Override + public void releaseMemoryBlock(Object memoryBlock) { + memoryBlock = null; + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java index 8eb4cc0489..bb860750e0 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java @@ -17,8 +17,12 @@ package org.apache.hugegraph.memory.consumer; +import java.util.List; + import org.apache.hugegraph.memory.pool.MemoryPool; +import io.netty.buffer.ByteBuf; + /** * This interface is used by immutable, memory-heavy objects which will be stored in off heap. */ @@ -44,4 +48,6 @@ public interface MemoryConsumer { void releaseOriginalOnHeapVars(); MemoryPool getOperatorMemoryPool(); + + List getAllOffHeapByteBuf(); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java index 8215f98749..334257e988 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java @@ -17,6 +17,9 @@ package org.apache.hugegraph.memory.consumer.impl.id; +import java.util.Collections; +import java.util.List; + import org.apache.hugegraph.backend.id.Id; import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; import org.apache.hugegraph.memory.consumer.MemoryConsumer; @@ -59,6 +62,11 @@ public MemoryPool getOperatorMemoryPool() { return this.memoryPool; } + @Override + public List getAllOffHeapByteBuf() { + return Collections.singletonList(bytesOffHeap); + } + @Override public void releaseOriginalOnHeapVars() { this.bytes = null; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java index 98d30f3dd6..a63c8c5c38 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java @@ -18,6 +18,7 @@ package org.apache.hugegraph.memory.consumer.impl.id; import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.Objects; import org.apache.hugegraph.backend.id.EdgeId; @@ -29,6 +30,8 @@ import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.define.Directions; +import com.google.common.collect.Lists; + import io.netty.buffer.ByteBuf; // TODO: rewrite static method in EdgeId @@ -140,6 +143,11 @@ public MemoryPool getOperatorMemoryPool() { return memoryPool; } + @Override + public List getAllOffHeapByteBuf() { + return Lists.newArrayList(this.sortValuesOffHeap, this.cacheOffHeap); + } + @Override public EdgeId switchDirection() { Directions newDirection = this.direction.opposite(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java index 6c7bf65d66..c0f1345460 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java @@ -19,6 +19,8 @@ import static org.apache.hugegraph.backend.id.IdGenerator.compareType; +import java.util.Collections; +import java.util.List; import java.util.Objects; import org.apache.hugegraph.backend.id.Id; @@ -75,6 +77,11 @@ public MemoryPool getOperatorMemoryPool() { return memoryPool; } + @Override + public List getAllOffHeapByteBuf() { + return Collections.singletonList(idOffHeap); + } + @Override public long asLong() { try { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java index 93c8506033..e6ff53c9fe 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.memory.consumer.impl.id; +import java.util.Collections; +import java.util.List; import java.util.Objects; import org.apache.hugegraph.backend.id.IdGenerator; @@ -63,6 +65,11 @@ public MemoryPool getOperatorMemoryPool() { return memoryPool; } + @Override + public List getAllOffHeapByteBuf() { + return Collections.singletonList(objectOffHeap); + } + @Override public Object asObject() { return FurySerializationUtils.FURY.deserialize(ByteBufUtil.getBytes(objectOffHeap)); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java index b2852992a9..9f62e0c67c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java @@ -18,6 +18,8 @@ package org.apache.hugegraph.memory.consumer.impl.id; import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; import org.apache.hugegraph.backend.cache.CachedBackendStore; import org.apache.hugegraph.backend.id.Id; @@ -69,6 +71,11 @@ public MemoryPool getOperatorMemoryPool() { return memoryPool; } + @Override + public List getAllOffHeapByteBuf() { + return Collections.singletonList(queryOffHeap); + } + @Override public boolean equals(Object other) { if (!(other instanceof QueryIdOffHeap)) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java index e924a17a61..3501026963 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java @@ -20,6 +20,8 @@ import static org.apache.hugegraph.backend.id.IdGenerator.compareType; import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; import org.apache.hugegraph.backend.id.Id; import org.apache.hugegraph.backend.id.IdGenerator; @@ -75,6 +77,11 @@ public MemoryPool getOperatorMemoryPool() { return memoryPool; } + @Override + public List getAllOffHeapByteBuf() { + return Collections.singletonList(idOffHeap); + } + @Override public Object asObject() { return this.asString(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java index b21b72ad63..3b2ba7e372 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java @@ -20,6 +20,8 @@ import static org.apache.hugegraph.backend.id.IdGenerator.compareType; import java.io.IOException; +import java.util.Collections; +import java.util.List; import java.util.UUID; import org.apache.hugegraph.backend.id.Id; @@ -87,6 +89,11 @@ public MemoryPool getOperatorMemoryPool() { return memoryPool; } + @Override + public List getAllOffHeapByteBuf() { + return Collections.singletonList(idOffHeap); + } + @Override public Object asObject() { return FurySerializationUtils.FURY.deserialize( diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java index c2cf91a713..9ed058fef3 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.memory.consumer.impl.property; +import java.util.Collections; +import java.util.List; import java.util.NoSuchElementException; import org.apache.hugegraph.memory.consumer.MemoryConsumer; @@ -68,6 +70,11 @@ public MemoryPool getOperatorMemoryPool() { return memoryPool; } + @Override + public List getAllOffHeapByteBuf() { + return Collections.singletonList(valueOffHeap); + } + @Override public HugeEdgeProperty switchEdgeOwner() { assert this.owner instanceof HugeEdge; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java index 194da3ec15..7d6bd3a107 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.memory.consumer.impl.property; +import java.util.Collections; +import java.util.List; import java.util.NoSuchElementException; import org.apache.hugegraph.memory.consumer.MemoryConsumer; @@ -67,6 +69,11 @@ public MemoryPool getOperatorMemoryPool() { return memoryPool; } + @Override + public List getAllOffHeapByteBuf() { + return Collections.singletonList(valueOffHeap); + } + @Override public Object serialValue(boolean encodeNumber) { return this.pkey.serialValue(this.value(), encodeNumber); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 639874d639..9c193702dc 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -25,6 +25,7 @@ import java.util.concurrent.locks.ReentrantLock; import org.apache.hugegraph.memory.MemoryManager; +import org.apache.hugegraph.memory.consumer.MemoryConsumer; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -139,6 +140,11 @@ public Object tryToAcquireMemoryInternal(long bytes) { return null; } + @Override + public void bindMemoryConsumer(MemoryConsumer memoryConsumer) { + // default do nothing + } + @Override public Object requireMemory(long bytes) { return null; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index 7c396ede91..c928008941 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -17,6 +17,7 @@ package org.apache.hugegraph.memory.pool; +import org.apache.hugegraph.memory.consumer.MemoryConsumer; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; import org.apache.hugegraph.memory.util.QueryOutOfMemoryException; @@ -49,4 +50,6 @@ public interface MemoryPool { MemoryPool getParentPool(); MemoryPool findRootQueryPool(); + + void bindMemoryConsumer(MemoryConsumer memoryConsumer); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index eb57cd78d8..506e725c4e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -17,8 +17,12 @@ package org.apache.hugegraph.memory.pool.impl; +import java.util.HashSet; +import java.util.Set; + import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.allocator.MemoryAllocator; +import org.apache.hugegraph.memory.consumer.MemoryConsumer; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.util.MemoryManageUtils; @@ -30,16 +34,27 @@ public class OperatorMemoryPool extends AbstractMemoryPool { private static final Logger LOG = LoggerFactory.getLogger(OperatorMemoryPool.class); private final MemoryAllocator memoryAllocator; + private final Set memoryConsumers; public OperatorMemoryPool(MemoryPool parent, String poolName, MemoryAllocator memoryAllocator, MemoryManager memoryManager) { super(parent, poolName, memoryManager); this.memoryAllocator = memoryAllocator; + this.memoryConsumers = new HashSet<>(); + } + + @Override + public void bindMemoryConsumer(MemoryConsumer memoryConsumer) { + this.memoryConsumers.add(memoryConsumer); } @Override public synchronized void releaseSelf(String reason) { - this.memoryAllocator.releaseMemory(getAllocatedBytes()); + this.memoryAllocator.returnMemoryToManager(getAllocatedBytes()); + this.memoryConsumers.forEach(memoryConsumer -> { + memoryConsumer.getAllOffHeapByteBuf().forEach(memoryAllocator::releaseMemoryBlock); + }); + this.memoryConsumers.clear(); super.releaseSelf(reason); // TODO: release memory consumer, release byte buffer. } From ef0d6296a36764a1cee9f753dbd28396bd43f665 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Sun, 27 Oct 2024 20:23:06 +0800 Subject: [PATCH 23/48] complete allocate memory test and fix bug --- .../hugegraph/memory/MemoryManager.java | 12 +- .../allocator/NettyMemoryAllocator.java | 18 +-- .../allocator/OnHeapMemoryStrategy.java | 27 ++-- .../memory/consumer/MemoryConsumer.java | 2 +- .../consumer/impl/id/BinaryIdOffHeap.java | 2 +- .../consumer/impl/id/EdgeIdOffHeap.java | 2 +- .../consumer/impl/id/LongIdOffHeap.java | 2 +- .../consumer/impl/id/ObjectIdOffHeap.java | 2 +- .../consumer/impl/id/QueryIdOffHeap.java | 2 +- .../consumer/impl/id/StringIdOffHeap.java | 2 +- .../consumer/impl/id/UuidIdOffHeap.java | 2 +- .../property/HugeEdgePropertyOffHeap.java | 2 +- .../property/HugeVertexPropertyOffHeap.java | 2 +- .../memory/pool/impl/OperatorMemoryPool.java | 2 +- .../core/memory/MemoryAllocateTest.java | 121 ++++++++++++++++++ .../core/memory/MemoryConsumerTest.java | 2 + .../core/memory/MemoryManagerTest.java | 2 + 17 files changed, 162 insertions(+), 42 deletions(-) create mode 100644 hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryAllocateTest.java create mode 100644 hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java create mode 100644 hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManagerTest.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index da13ef81e1..afb74e040f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -46,8 +46,8 @@ public class MemoryManager { public static final long MAX_MEMORY_CAPACITY_IN_BYTES = Bytes.GB; private final AtomicLong currentAvailableMemoryInBytes = new AtomicLong(MAX_MEMORY_CAPACITY_IN_BYTES); - private final AtomicLong currentOffHeapAllocatedMemory = new AtomicLong(0); - private final AtomicLong currentOnHeapAllocatedMemory = new AtomicLong(0); + private final AtomicLong currentOffHeapAllocatedMemoryInBytes = new AtomicLong(0); + private final AtomicLong currentOnHeapAllocatedMemoryInBytes = new AtomicLong(0); private final Queue queryMemoryPools = new PriorityQueue<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); private final MemoryArbitrator memoryArbitrator; @@ -136,12 +136,12 @@ public void consumeAvailableMemory(long size) { currentAvailableMemoryInBytes.addAndGet(-size); } - public AtomicLong getCurrentOnHeapAllocatedMemory() { - return currentOnHeapAllocatedMemory; + public AtomicLong getCurrentOnHeapAllocatedMemoryInBytes() { + return currentOnHeapAllocatedMemoryInBytes; } - public AtomicLong getCurrentOffHeapAllocatedMemory() { - return currentOffHeapAllocatedMemory; + public AtomicLong getCurrentOffHeapAllocatedMemoryInBytes() { + return currentOffHeapAllocatedMemoryInBytes; } private static class MemoryManagerHolder { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java index 579bb68829..fcfee75133 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java @@ -37,14 +37,16 @@ public NettyMemoryAllocator(MemoryManager memoryManager) { @Override public ByteBuf forceAllocate(long size) { + memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().addAndGet(size); return offHeapAllocator.directBuffer((int) size); } @Override public ByteBuf tryToAllocate(long size) { - if (memoryManager.getCurrentOnHeapAllocatedMemory().get() + - memoryManager.getCurrentOffHeapAllocatedMemory().get() + size < + if (memoryManager.getCurrentOnHeapAllocatedMemoryInBytes().get() + + memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().get() + size < MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES) { + memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().addAndGet(size); return offHeapAllocator.directBuffer((int) size); } return null; @@ -52,7 +54,7 @@ public ByteBuf tryToAllocate(long size) { @Override public void returnMemoryToManager(long size) { - memoryManager.getCurrentOffHeapAllocatedMemory().addAndGet(-size); + memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().addAndGet(-size); } @Override @@ -61,14 +63,6 @@ public void releaseMemoryBlock(Object memoryBlock) { throw new IllegalArgumentException("memoryBlock must be ByteBuf"); } ByteBuf buf = (ByteBuf) memoryBlock; - ReferenceCountUtil.safeRelease(buf, ReferenceCountUtil.refCnt(buf)); - } - - public static void main(String[] args) { - MemoryAllocator netty = new NettyMemoryAllocator(null); - ByteBuf buf = (ByteBuf) netty.forceAllocate(1024); - System.out.println(ReferenceCountUtil.refCnt(buf)); - netty.releaseMemoryBlock(buf); - System.out.println(ReferenceCountUtil.refCnt(buf)); + ReferenceCountUtil.safeRelease(buf); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java index cf5d57a9cd..9da832ad1b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java @@ -17,8 +17,9 @@ package org.apache.hugegraph.memory.allocator; +import java.util.concurrent.atomic.AtomicReference; + import org.apache.hugegraph.memory.MemoryManager; -import org.apache.hugegraph.util.Bytes; public class OnHeapMemoryStrategy implements MemoryAllocator { @@ -29,31 +30,31 @@ public OnHeapMemoryStrategy(MemoryManager memoryManager) { } @Override - public byte[] tryToAllocate(long size) { - if (memoryManager.getCurrentOnHeapAllocatedMemory().get() + - memoryManager.getCurrentOffHeapAllocatedMemory().get() + size < + public AtomicReference tryToAllocate(long size) { + if (memoryManager.getCurrentOnHeapAllocatedMemoryInBytes().get() + + memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().get() + size < MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES) { - int sizeOfByte = (int) (size / Bytes.BASE); - memoryManager.getCurrentOnHeapAllocatedMemory().addAndGet(sizeOfByte); - return new byte[sizeOfByte]; + memoryManager.getCurrentOnHeapAllocatedMemoryInBytes().addAndGet(size); + byte[] memoryBlock = new byte[(int) size]; + return new AtomicReference<>(memoryBlock); } return null; } @Override - public byte[] forceAllocate(long size) { - int sizeOfByte = (int) (size / Bytes.BASE); - memoryManager.getCurrentOnHeapAllocatedMemory().addAndGet(sizeOfByte); - return new byte[sizeOfByte]; + public AtomicReference forceAllocate(long size) { + memoryManager.getCurrentOnHeapAllocatedMemoryInBytes().addAndGet(size); + byte[] memoryBlock = new byte[(int) size]; + return new AtomicReference<>(memoryBlock); } @Override public void returnMemoryToManager(long size) { - memoryManager.getCurrentOnHeapAllocatedMemory().addAndGet(-size); + memoryManager.getCurrentOnHeapAllocatedMemoryInBytes().addAndGet(-size); } @Override public void releaseMemoryBlock(Object memoryBlock) { - memoryBlock = null; + ((AtomicReference) memoryBlock).set(null); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java index bb860750e0..aebbedc17e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java @@ -49,5 +49,5 @@ public interface MemoryConsumer { MemoryPool getOperatorMemoryPool(); - List getAllOffHeapByteBuf(); + List getAllMemoryBlock(); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java index 334257e988..51be29796a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java @@ -63,7 +63,7 @@ public MemoryPool getOperatorMemoryPool() { } @Override - public List getAllOffHeapByteBuf() { + public List getAllMemoryBlock() { return Collections.singletonList(bytesOffHeap); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java index a63c8c5c38..7380376ce2 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java @@ -144,7 +144,7 @@ public MemoryPool getOperatorMemoryPool() { } @Override - public List getAllOffHeapByteBuf() { + public List getAllMemoryBlock() { return Lists.newArrayList(this.sortValuesOffHeap, this.cacheOffHeap); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java index c0f1345460..eefa44bc73 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java @@ -78,7 +78,7 @@ public MemoryPool getOperatorMemoryPool() { } @Override - public List getAllOffHeapByteBuf() { + public List getAllMemoryBlock() { return Collections.singletonList(idOffHeap); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java index e6ff53c9fe..8097dbb736 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java @@ -66,7 +66,7 @@ public MemoryPool getOperatorMemoryPool() { } @Override - public List getAllOffHeapByteBuf() { + public List getAllMemoryBlock() { return Collections.singletonList(objectOffHeap); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java index 9f62e0c67c..d99fa4d66d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java @@ -72,7 +72,7 @@ public MemoryPool getOperatorMemoryPool() { } @Override - public List getAllOffHeapByteBuf() { + public List getAllMemoryBlock() { return Collections.singletonList(queryOffHeap); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java index 3501026963..dc57d17538 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java @@ -78,7 +78,7 @@ public MemoryPool getOperatorMemoryPool() { } @Override - public List getAllOffHeapByteBuf() { + public List getAllMemoryBlock() { return Collections.singletonList(idOffHeap); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java index 3b2ba7e372..4335adc87e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java @@ -90,7 +90,7 @@ public MemoryPool getOperatorMemoryPool() { } @Override - public List getAllOffHeapByteBuf() { + public List getAllMemoryBlock() { return Collections.singletonList(idOffHeap); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java index 9ed058fef3..2a53689f95 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java @@ -71,7 +71,7 @@ public MemoryPool getOperatorMemoryPool() { } @Override - public List getAllOffHeapByteBuf() { + public List getAllMemoryBlock() { return Collections.singletonList(valueOffHeap); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java index 7d6bd3a107..5796edb84a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java @@ -70,7 +70,7 @@ public MemoryPool getOperatorMemoryPool() { } @Override - public List getAllOffHeapByteBuf() { + public List getAllMemoryBlock() { return Collections.singletonList(valueOffHeap); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index 506e725c4e..b028393c30 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -52,7 +52,7 @@ public void bindMemoryConsumer(MemoryConsumer memoryConsumer) { public synchronized void releaseSelf(String reason) { this.memoryAllocator.returnMemoryToManager(getAllocatedBytes()); this.memoryConsumers.forEach(memoryConsumer -> { - memoryConsumer.getAllOffHeapByteBuf().forEach(memoryAllocator::releaseMemoryBlock); + memoryConsumer.getAllMemoryBlock().forEach(memoryAllocator::releaseMemoryBlock); }); this.memoryConsumers.clear(); super.releaseSelf(reason); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryAllocateTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryAllocateTest.java new file mode 100644 index 0000000000..520e19af6b --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryAllocateTest.java @@ -0,0 +1,121 @@ +/* + * 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.hugegraph.core.memory; + +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.hugegraph.memory.MemoryManager; +import org.apache.hugegraph.memory.allocator.MemoryAllocator; +import org.apache.hugegraph.memory.allocator.NettyMemoryAllocator; +import org.apache.hugegraph.memory.allocator.OnHeapMemoryStrategy; +import org.apache.hugegraph.util.Bytes; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import io.netty.buffer.ByteBuf; +import io.netty.util.IllegalReferenceCountException; +import io.netty.util.ReferenceCountUtil; + +public class MemoryAllocateTest { + + private static MemoryAllocator nettyAllocator; + private static MemoryAllocator onHeapAllocator; + private static MemoryManager memoryManager; + + @Before + public void setup() { + MemoryManager.getInstance().getCurrentOffHeapAllocatedMemoryInBytes().set(0); + MemoryManager.getInstance().getCurrentOnHeapAllocatedMemoryInBytes().set(0); + } + + @BeforeClass + public static void beforeClass() { + nettyAllocator = new NettyMemoryAllocator(MemoryManager.getInstance()); + onHeapAllocator = new OnHeapMemoryStrategy(MemoryManager.getInstance()); + memoryManager = MemoryManager.getInstance(); + } + + @Test + public void testNettyAllocate() { + ByteBuf memoryBlock1 = (ByteBuf) nettyAllocator.tryToAllocate(Bytes.KB); + ByteBuf memoryBlock2 = (ByteBuf) nettyAllocator.tryToAllocate(Bytes.MB); + Assert.assertNotNull(memoryBlock1); + Assert.assertEquals(Bytes.KB, memoryBlock1.capacity()); + Assert.assertNotNull(memoryBlock2); + Assert.assertEquals(Bytes.MB, memoryBlock2.capacity()); + Assert.assertEquals(Bytes.KB + Bytes.MB, + memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().get()); + ByteBuf memoryBlock3 = (ByteBuf) nettyAllocator.tryToAllocate(Bytes.GB); + Assert.assertNull(memoryBlock3); + memoryBlock3 = (ByteBuf) nettyAllocator.forceAllocate(Bytes.GB); + Assert.assertNotNull(memoryBlock3); + Assert.assertEquals(Bytes.GB, memoryBlock3.capacity()); + } + + @Test + public void testNettyDeallocate() { + ByteBuf buf = (ByteBuf) nettyAllocator.tryToAllocate(Bytes.KB); + Assert.assertNotNull(buf); + Assert.assertTrue(buf.isWritable()); + Assert.assertEquals(buf.capacity(), + memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().get()); + Assert.assertEquals(1, ReferenceCountUtil.refCnt(buf)); + nettyAllocator.releaseMemoryBlock(buf); + Assert.assertThrows(IllegalReferenceCountException.class, buf::memoryAddress); + Assert.assertEquals(0, ReferenceCountUtil.refCnt(buf)); + nettyAllocator.returnMemoryToManager(buf.capacity()); + Assert.assertEquals(0, + memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().get()); + } + + @Test + public void testOnHeapAllocate() { + AtomicReference memoryBlock1 = + (AtomicReference) onHeapAllocator.tryToAllocate(Bytes.KB); + AtomicReference memoryBlock2 = + (AtomicReference) onHeapAllocator.tryToAllocate(Bytes.MB); + Assert.assertNotNull(memoryBlock1); + Assert.assertEquals(Bytes.KB, memoryBlock1.get().length); + Assert.assertNotNull(memoryBlock2); + Assert.assertEquals(Bytes.MB, memoryBlock2.get().length); + Assert.assertEquals(Bytes.KB + Bytes.MB, + memoryManager.getCurrentOnHeapAllocatedMemoryInBytes().get()); + AtomicReference memoryBlock3 = + (AtomicReference) onHeapAllocator.tryToAllocate(Bytes.GB); + Assert.assertNull(memoryBlock3); + memoryBlock3 = (AtomicReference) onHeapAllocator.forceAllocate(Bytes.GB); + Assert.assertNotNull(memoryBlock3); + Assert.assertEquals(Bytes.GB, memoryBlock3.get().length); + } + + @Test + public void testOnHeapDeallocate() { + AtomicReference buf = + (AtomicReference) onHeapAllocator.tryToAllocate(Bytes.KB); + Assert.assertNotNull(buf); + Assert.assertEquals(buf.get().length, + memoryManager.getCurrentOnHeapAllocatedMemoryInBytes().get()); + onHeapAllocator.returnMemoryToManager(buf.get().length); + Assert.assertEquals(0, + memoryManager.getCurrentOnHeapAllocatedMemoryInBytes().get()); + onHeapAllocator.releaseMemoryBlock(buf); + Assert.assertNull(buf.get()); + } +} diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java new file mode 100644 index 0000000000..f1f6d5bda7 --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java @@ -0,0 +1,2 @@ +package org.apache.hugegraph.core.memory;public class MemoryConsumerTest { +} diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManagerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManagerTest.java new file mode 100644 index 0000000000..78c38ba4c5 --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManagerTest.java @@ -0,0 +1,2 @@ +package org.apache.hugegraph.core.memory;public class MemoryManagerTest { +} From 54d1fd80ec0eaaedf0972471a5257300d2de66d7 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Sun, 27 Oct 2024 21:56:02 +0800 Subject: [PATCH 24/48] fix some bugs: arbitration & suspend --- .../hugegraph/memory/MemoryManager.java | 25 +++- .../memory/arbitrator/MemoryArbitrator.java | 2 +- .../memory/pool/AbstractMemoryPool.java | 25 ++-- .../hugegraph/memory/pool/MemoryPool.java | 6 + .../memory/pool/impl/MemoryPoolStats.java | 4 + .../memory/pool/impl/OperatorMemoryPool.java | 31 +++-- .../memory/pool/impl/QueryMemoryPool.java | 20 ++- .../memory/pool/impl/TaskMemoryPool.java | 26 ++++ .../core/memory/MemoryConsumerTest.java | 22 +++- .../core/memory/MemoryManageTest.java | 117 ++++++++++++++++++ .../core/memory/MemoryManagerTest.java | 2 - 11 files changed, 256 insertions(+), 24 deletions(-) create mode 100644 hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java delete mode 100644 hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManagerTest.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index afb74e040f..84bd62aaf0 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -17,8 +17,10 @@ package org.apache.hugegraph.memory; +import java.util.Map; import java.util.PriorityQueue; import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; @@ -38,18 +40,22 @@ public class MemoryManager { private static final Logger LOG = LoggerFactory.getLogger(MemoryManager.class); + private static final int ARBITRATE_MEMORY_THREAD_NUM = 12; private static final String QUERY_MEMORY_POOL_NAME_PREFIX = "QueryMemoryPool"; private static final String ARBITRATE_MEMORY_POOL_NAME = "ArbitrateMemoryPool"; - private static final String DELIMINATOR = "_"; - private static final int ARBITRATE_MEMORY_THREAD_NUM = 12; + public static final String DELIMINATOR = "_"; + // TODO: read it from conf, current 1G public static final long MAX_MEMORY_CAPACITY_IN_BYTES = Bytes.GB; private final AtomicLong currentAvailableMemoryInBytes = new AtomicLong(MAX_MEMORY_CAPACITY_IN_BYTES); private final AtomicLong currentOffHeapAllocatedMemoryInBytes = new AtomicLong(0); private final AtomicLong currentOnHeapAllocatedMemoryInBytes = new AtomicLong(0); + private final Queue queryMemoryPools = new PriorityQueue<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); + private final Map threadName2TaskMemoryPoolMap = new ConcurrentHashMap<>(); + private final MemoryArbitrator memoryArbitrator; private final ExecutorService arbitrateExecutor; @@ -128,6 +134,21 @@ public synchronized long handleRequestFromQueryPool(long size) { return size; } + /** + * Used by task thread to find its memory pool to release self's memory resource when exiting. + */ + public MemoryPool getCorrespondingTaskMemoryPool(String threadName) { + return threadName2TaskMemoryPoolMap.getOrDefault(threadName, null); + } + + public void bindCorrespondingTaskMemoryPool(String threadName, MemoryPool memoryPool) { + threadName2TaskMemoryPoolMap.computeIfAbsent(threadName, key -> memoryPool); + } + + public void removeCorrespondingTaskMemoryPool(String threadName) { + threadName2TaskMemoryPoolMap.remove(threadName); + } + public Queue getCurrentQueryMemoryPools() { return new PriorityQueue<>(queryMemoryPools); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java index 45a43799e0..e93ed0a414 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java @@ -21,7 +21,7 @@ public interface MemoryArbitrator { - long MAX_WAIT_TIME_FOR_LOCAL_RECLAIM = 1000; + long MAX_WAIT_TIME_FOR_LOCAL_RECLAIM = 2000; long MAX_WAIT_TIME_FOR_GLOBAL_RECLAIM = 5000; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 9c193702dc..75a845002f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -27,17 +27,19 @@ import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.consumer.MemoryConsumer; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; +import org.jetbrains.annotations.TestOnly; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class AbstractMemoryPool implements MemoryPool { private static final Logger LOG = LoggerFactory.getLogger(AbstractMemoryPool.class); - private final Queue children = + protected final Queue children = new PriorityQueue<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); protected final MemoryManager memoryManager; - protected final ReentrantLock arbitrationLock = new ReentrantLock(); - protected final Condition condition = arbitrationLock.newCondition(); + // Allocation, deAllocation, arbitration must be serial which is controlled by this lock. + protected final ReentrantLock memoryActionLock = new ReentrantLock(); + protected final Condition condition = memoryActionLock.newCondition(); protected final AtomicBoolean isBeingArbitrated = new AtomicBoolean(false); protected final MemoryPoolStats stats; protected boolean isClosed = false; @@ -60,7 +62,7 @@ public long tryToReclaimLocalMemory(long neededBytes) { long totalReclaimedBytes = 0; long currentNeededBytes = neededBytes; try { - this.arbitrationLock.lock(); + this.memoryActionLock.lock(); this.isBeingArbitrated.set(true); for (MemoryPool child : this.children) { long reclaimedMemory = child.tryToReclaimLocalMemory(currentNeededBytes); @@ -79,12 +81,14 @@ public long tryToReclaimLocalMemory(long neededBytes) { totalReclaimedBytes, neededBytes); return totalReclaimedBytes; } finally { - this.stats.setNumShrinks(this.stats.getNumShrinks() + 1); + if (totalReclaimedBytes > 0) { + this.stats.setNumShrinks(this.stats.getNumShrinks() + 1); + } this.stats.setAllocatedBytes( this.stats.getAllocatedBytes() - totalReclaimedBytes); this.isBeingArbitrated.set(false); - this.arbitrationLock.unlock(); this.condition.signalAll(); + this.memoryActionLock.unlock(); } } @@ -92,7 +96,8 @@ public long tryToReclaimLocalMemory(long neededBytes) { * called when one layer pool is successfully executed and exited. */ @Override - public synchronized void releaseSelf(String reason) { + public void releaseSelf(String reason) { + this.memoryActionLock.lock(); try { if (this.isBeingArbitrated.get()) { this.condition.await(); @@ -109,6 +114,7 @@ public synchronized void releaseSelf(String reason) { LOG.error("Failed to release self because ", e); Thread.currentThread().interrupt(); } finally { + this.memoryActionLock.unlock(); // Make these objs be GCed by JVM quickly. this.parent = null; this.children.clear(); @@ -198,4 +204,9 @@ public MemoryPool findRootQueryPool() { } return getParentPool().findRootQueryPool(); } + + @TestOnly + public int getChildrenCount() { + return this.children.size(); + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index c928008941..703e8ab567 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -20,6 +20,7 @@ import org.apache.hugegraph.memory.consumer.MemoryConsumer; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; import org.apache.hugegraph.memory.util.QueryOutOfMemoryException; +import org.jetbrains.annotations.TestOnly; public interface MemoryPool { @@ -51,5 +52,10 @@ public interface MemoryPool { MemoryPool findRootQueryPool(); + MemoryPool addChildPool(); + void bindMemoryConsumer(MemoryConsumer memoryConsumer); + + @TestOnly + int getChildrenCount(); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java index c5de6b7e3d..045499f4d2 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java @@ -22,10 +22,14 @@ public class MemoryPoolStats { private final String memoryPoolName; private long maxCapacity; private long usedBytes; + // it represents the cumulative used bytes. private long cumulativeBytes; private long allocatedBytes; + // it represents the shrinking num of allocatedBytes private long numShrinks; + // for query pool, it represents the enlarging num of maxCapacity; for other pools, it + // represents the enlarging num of allocatedBytes private long numExpands; private long numAborts; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index b028393c30..4cb00cb6f2 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -43,20 +43,27 @@ public OperatorMemoryPool(MemoryPool parent, String poolName, this.memoryConsumers = new HashSet<>(); } + @Override + public MemoryPool addChildPool() { + throw new UnsupportedOperationException(); + } + @Override public void bindMemoryConsumer(MemoryConsumer memoryConsumer) { this.memoryConsumers.add(memoryConsumer); } @Override - public synchronized void releaseSelf(String reason) { + public void releaseSelf(String reason) { + super.releaseSelf(reason); + // since it is already closed, its stats will not be updated. so here we can use its + // stats out of memoryActionLock. this.memoryAllocator.returnMemoryToManager(getAllocatedBytes()); + // release memory consumer, release byte buffer. this.memoryConsumers.forEach(memoryConsumer -> { memoryConsumer.getAllMemoryBlock().forEach(memoryAllocator::releaseMemoryBlock); }); this.memoryConsumers.clear(); - super.releaseSelf(reason); - // TODO: release memory consumer, release byte buffer. } @Override @@ -66,11 +73,12 @@ public long tryToReclaimLocalMemory(long neededBytes) { return 0; } LOG.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); + long reclaimableBytes = 0; try { - this.arbitrationLock.lock(); + this.memoryActionLock.lock(); this.isBeingArbitrated.set(true); // 1. try to reclaim self free memory - long reclaimableBytes = getFreeBytes(); + reclaimableBytes = getFreeBytes(); // try its best to reclaim memory if (reclaimableBytes <= neededBytes) { // 2. update stats @@ -93,9 +101,12 @@ public long tryToReclaimLocalMemory(long neededBytes) { return neededBytes; } finally { + if (reclaimableBytes > 0) { + this.stats.setNumShrinks(this.stats.getNumShrinks() + 1); + } this.isBeingArbitrated.set(false); - this.arbitrationLock.unlock(); this.condition.signalAll(); + this.memoryActionLock.unlock(); } } @@ -106,9 +117,9 @@ public long tryToReclaimLocalMemory(long neededBytes) { public Object requireMemory(long bytes) { try { // use lock to ensure the atomicity of the two-step operation - this.arbitrationLock.lock(); - long realBytes = requestMemoryInternal(bytes); - return tryToAcquireMemoryInternal(realBytes); + this.memoryActionLock.lock(); + long ignoredRealAllocatedBytes = requestMemoryInternal(bytes); + return tryToAcquireMemoryInternal(bytes); } catch (QueryOutOfMemoryException e) { // Abort this query LOG.warn("[{}] detected an OOM exception when request memory, will ABORT this " + @@ -117,7 +128,7 @@ public Object requireMemory(long bytes) { findRootQueryPool().releaseSelf(String.format(e.getMessage())); return null; } finally { - this.arbitrationLock.unlock(); + this.memoryActionLock.unlock(); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index be08827d86..27426be1a9 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -17,8 +17,11 @@ package org.apache.hugegraph.memory.pool.impl; +import static org.apache.hugegraph.memory.MemoryManager.DELIMINATOR; + import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; +import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.util.MemoryManageUtils; import org.apache.hugegraph.util.Bytes; import org.slf4j.Logger; @@ -27,6 +30,7 @@ public class QueryMemoryPool extends AbstractMemoryPool { private static final Logger LOG = LoggerFactory.getLogger(QueryMemoryPool.class); + private static final String TASK_MEMORY_POOL_NAME_PREFIX = "TaskMemoryPool"; // TODO: read from conf private static final long QUERY_POOL_MAX_CAPACITY = Bytes.MB * 100; @@ -35,6 +39,18 @@ public QueryMemoryPool(String poolName, MemoryManager memoryManager) { this.stats.setMaxCapacity(QUERY_POOL_MAX_CAPACITY); } + @Override + public MemoryPool addChildPool() { + int count = this.children.size(); + String poolName = + TASK_MEMORY_POOL_NAME_PREFIX + DELIMINATOR + count + DELIMINATOR + + System.currentTimeMillis(); + MemoryPool taskMemoryPool = new TaskMemoryPool(this, poolName, this.memoryManager); + this.children.add(taskMemoryPool); + LOG.info("QueryPool-{} added task memory pool {}", this, taskMemoryPool); + return taskMemoryPool; + } + @Override public long requestMemoryInternal(long bytes) { if (this.isClosed) { @@ -83,8 +99,10 @@ private long tryToExpandSelfCapacity(long size) { private long requestMemoryThroughArbitration(long bytes) { LOG.info("[{}] try to request memory from manager through arbitration: size={}", this, bytes); - this.stats.setNumExpands(this.stats.getNumExpands() + 1); long reclaimedBytes = this.memoryManager.triggerLocalArbitration(this, bytes); + if (reclaimedBytes > 0) { + this.stats.setNumExpands(this.stats.getNumExpands() + 1); + } // 1. if arbitrate successes, update stats and return success if (reclaimedBytes - bytes >= 0) { // here we don't update capacity & reserved & allocated, because memory is diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index 39489e458d..b7c1f8d19a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -17,7 +17,10 @@ package org.apache.hugegraph.memory.pool.impl; +import static org.apache.hugegraph.memory.MemoryManager.DELIMINATOR; + import org.apache.hugegraph.memory.MemoryManager; +import org.apache.hugegraph.memory.allocator.NettyMemoryAllocator; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.util.QueryOutOfMemoryException; @@ -27,11 +30,33 @@ public class TaskMemoryPool extends AbstractMemoryPool { private static final Logger LOG = LoggerFactory.getLogger(TaskMemoryPool.class); + private static final String OPERATOR_MEMORY_POOL_NAME_PREFIX = "OperatorMemoryPool"; public TaskMemoryPool(MemoryPool parent, String poolName, MemoryManager memoryManager) { super(parent, poolName, memoryManager); } + @Override + public synchronized void releaseSelf(String reason) { + this.memoryManager.removeCorrespondingTaskMemoryPool(Thread.currentThread().getName()); + super.releaseSelf(reason); + } + + @Override + public MemoryPool addChildPool() { + int count = this.children.size(); + String poolName = + OPERATOR_MEMORY_POOL_NAME_PREFIX + DELIMINATOR + count + DELIMINATOR + + System.currentTimeMillis(); + MemoryPool operatorPool = + new OperatorMemoryPool(this, poolName, + new NettyMemoryAllocator(this.memoryManager), + this.memoryManager); + this.children.add(operatorPool); + LOG.info("TaskPool-{} added operator memory pool {}", this, operatorPool); + return operatorPool; + } + @Override public long requestMemoryInternal(long bytes) throws QueryOutOfMemoryException { if (this.isClosed) { @@ -45,6 +70,7 @@ public long requestMemoryInternal(long bytes) throws QueryOutOfMemoryException { long parentRes = getParentPool().requestMemoryInternal(bytes); if (parentRes > 0) { this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + parentRes); + this.stats.setNumExpands(this.stats.getNumExpands() + 1); } return parentRes; } catch (InterruptedException e) { diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java index f1f6d5bda7..ed946d12e0 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java @@ -1,2 +1,22 @@ -package org.apache.hugegraph.core.memory;public class MemoryConsumerTest { +/* + * 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.hugegraph.core.memory; + +public class MemoryConsumerTest extends MemoryManageTest { + } diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java new file mode 100644 index 0000000000..cef1afff6a --- /dev/null +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java @@ -0,0 +1,117 @@ +/* + * 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.hugegraph.core.memory; + +import org.apache.hugegraph.memory.MemoryManager; +import org.apache.hugegraph.memory.pool.MemoryPool; +import org.apache.hugegraph.testutil.Assert; +import org.apache.hugegraph.util.Bytes; +import org.junit.BeforeClass; +import org.junit.Test; + +import io.netty.buffer.ByteBuf; + +/** + * This test will construct a query context with 2 query for testing memory management + *

+ * query1 + * | + * --> task1 + * | + * ----> operator1 + * | + * ----> operator2 + * | + * --> task2 + * | + * ----> operator1 + *

+ * query2 + * | + * --> task1 + * | + * ----> operator1 + */ +public class MemoryManageTest { + + protected static MemoryManager memoryManager; + protected static MemoryPool query1MemoryPool; + protected static MemoryPool query1Task1MemoryPool; + protected static String QUERY1_TASK1_THREAD_NAME = "QUERY1-THREAD-1"; + protected static MemoryPool query1Task2MemoryPool; + protected static String QUERY1_TASK2_THREAD_NAME = "QUERY1-THREAD-2"; + protected static MemoryPool query1Task1Operator1MemoryPool; + protected static MemoryPool query1Task1Operator2MemoryPool; + protected static MemoryPool query1Task2Operator1MemoryPool; + + protected static MemoryPool query2MemoryPool; + protected static MemoryPool query2Task1MemoryPool; + protected static String QUERY2_TASK1_THREAD_NAME = "QUERY2-THREAD-1"; + protected static MemoryPool query2Task1Operator1MemoryPool; + + @BeforeClass + public static void setUp() { + memoryManager = MemoryManager.getInstance(); + query1MemoryPool = memoryManager.addQueryMemoryPool(); + query2MemoryPool = memoryManager.addQueryMemoryPool(); + + query1Task1MemoryPool = query1MemoryPool.addChildPool(); + memoryManager.bindCorrespondingTaskMemoryPool(QUERY1_TASK1_THREAD_NAME, + query1Task1MemoryPool); + query1Task1Operator1MemoryPool = query1Task1MemoryPool.addChildPool(); + query1Task1Operator2MemoryPool = query1Task1MemoryPool.addChildPool(); + + query1Task2MemoryPool = query1MemoryPool.addChildPool(); + memoryManager.bindCorrespondingTaskMemoryPool(QUERY1_TASK2_THREAD_NAME, + query1Task2MemoryPool); + query1Task2Operator1MemoryPool = query1Task2MemoryPool.addChildPool(); + + query2Task1MemoryPool = query2MemoryPool.addChildPool(); + memoryManager.bindCorrespondingTaskMemoryPool(QUERY2_TASK1_THREAD_NAME, + query2Task1MemoryPool); + query2Task1Operator1MemoryPool = query2Task1MemoryPool.addChildPool(); + } + + @Test + public void testMemoryPoolStructure() { + Assert.assertEquals(2, memoryManager.getCurrentQueryMemoryPools().size()); + Assert.assertEquals(2, query1MemoryPool.getChildrenCount()); + Assert.assertEquals(2, query1Task1MemoryPool.getChildrenCount()); + Assert.assertEquals(1, query1Task2MemoryPool.getChildrenCount()); + Assert.assertEquals(0, query1Task1Operator1MemoryPool.getChildrenCount()); + + Assert.assertEquals(1, query2MemoryPool.getChildrenCount()); + Assert.assertEquals(1, query2Task1MemoryPool.getChildrenCount()); + Assert.assertEquals(0, query2Task1Operator1MemoryPool.getChildrenCount()); + } + + @Test + public void testRequiringMemory() { + long requireBytes = Bytes.KB; + ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + Assert.assertNotNull(memoryBlock); + Assert.assertEquals(requireBytes, memoryBlock.capacity()); + } + + @Test + public void testOOM() { + long requireBytes = Bytes.GB * 2; + ByteBuf memoryBlock = (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes); + Assert.assertNull(memoryBlock); + } +} diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManagerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManagerTest.java deleted file mode 100644 index 78c38ba4c5..0000000000 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManagerTest.java +++ /dev/null @@ -1,2 +0,0 @@ -package org.apache.hugegraph.core.memory;public class MemoryManagerTest { -} From bfe75c0e466c3d0bf3400c2e0d186283c0478019 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Sun, 27 Oct 2024 22:14:58 +0800 Subject: [PATCH 25/48] complete OOM UT and fix bugs --- .../hugegraph/memory/MemoryManager.java | 2 +- .../memory/pool/AbstractMemoryPool.java | 26 ++++++++++++------- .../hugegraph/memory/pool/MemoryPool.java | 19 +++++++++++--- .../memory/pool/impl/OperatorMemoryPool.java | 6 ++--- .../memory/pool/impl/TaskMemoryPool.java | 4 +-- .../core/memory/MemoryManageTest.java | 15 +++++++++++ 6 files changed, 53 insertions(+), 19 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index 84bd62aaf0..13e09c1b7a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -80,7 +80,7 @@ public void gcQueryMemoryPool(MemoryPool pool) { LOG.info("Manager gc query memory pool {}", pool); queryMemoryPools.remove(pool); long reclaimedMemory = pool.getAllocatedBytes(); - pool.releaseSelf(String.format("GC query memory pool %s", pool)); + pool.releaseSelf(String.format("GC query memory pool %s", pool), false); currentAvailableMemoryInBytes.addAndGet(reclaimedMemory); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 75a845002f..e4ea807763 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -96,25 +96,31 @@ public long tryToReclaimLocalMemory(long neededBytes) { * called when one layer pool is successfully executed and exited. */ @Override - public void releaseSelf(String reason) { - this.memoryActionLock.lock(); + public void releaseSelf(String reason, boolean isTriggeredInternal) { try { - if (this.isBeingArbitrated.get()) { - this.condition.await(); + if (!isTriggeredInternal) { + this.memoryActionLock.lock(); + if (this.isBeingArbitrated.get()) { + this.condition.await(); + } } LOG.info("[{}] starts to releaseSelf because of {}", this, reason); this.isClosed = true; - // update father - Optional.ofNullable(this.parent).ifPresent(parent -> parent.gcChildPool(this, false)); + // gc self from father + Optional.ofNullable(this.parent).ifPresent(parent -> parent.gcChildPool(this, false, + isTriggeredInternal)); + // gc all children for (MemoryPool child : this.children) { - gcChildPool(child, true); + gcChildPool(child, true, isTriggeredInternal); } LOG.info("[{}] finishes to releaseSelf", this); } catch (InterruptedException e) { LOG.error("Failed to release self because ", e); Thread.currentThread().interrupt(); } finally { - this.memoryActionLock.unlock(); + if (!isTriggeredInternal) { + this.memoryActionLock.unlock(); + } // Make these objs be GCed by JVM quickly. this.parent = null; this.children.clear(); @@ -122,9 +128,9 @@ public void releaseSelf(String reason) { } @Override - public void gcChildPool(MemoryPool child, boolean force) { + public void gcChildPool(MemoryPool child, boolean force, boolean isTriggeredInternal) { if (force) { - child.releaseSelf(String.format("[%s] releaseChildPool", this)); + child.releaseSelf(String.format("[%s] releaseChildPool", this), isTriggeredInternal); } // reclaim child's memory and update stats this.stats.setAllocatedBytes( diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index 703e8ab567..61f297cf4f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -34,9 +34,22 @@ public interface MemoryPool { Object tryToAcquireMemoryInternal(long bytes); - void releaseSelf(String reason); - - void gcChildPool(MemoryPool child, boolean force); + /** + * Release all self's resources. Called by user or called automatically by itself when OOM. + * + * @param reason: release reason, for logging. + * @param isTriggeredInternal: if true, it is called automatically. if false, called by user. + */ + void releaseSelf(String reason, boolean isTriggeredInternal); + + /** + * Called by `releaseSelf` to release children's resource. + * + * @param child: child pool + * @param force: if false, called to gc self from father + * @param isTriggeredInternal: passed from upper caller `releaseSelf` + */ + void gcChildPool(MemoryPool child, boolean force, boolean isTriggeredInternal); long getAllocatedBytes(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index 4cb00cb6f2..afb6e9bf2a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -54,8 +54,8 @@ public void bindMemoryConsumer(MemoryConsumer memoryConsumer) { } @Override - public void releaseSelf(String reason) { - super.releaseSelf(reason); + public void releaseSelf(String reason, boolean isTriggeredInternal) { + super.releaseSelf(reason, isTriggeredInternal); // since it is already closed, its stats will not be updated. so here we can use its // stats out of memoryActionLock. this.memoryAllocator.returnMemoryToManager(getAllocatedBytes()); @@ -125,7 +125,7 @@ public Object requireMemory(long bytes) { LOG.warn("[{}] detected an OOM exception when request memory, will ABORT this " + "query and release corresponding memory...", this); - findRootQueryPool().releaseSelf(String.format(e.getMessage())); + findRootQueryPool().releaseSelf(String.format(e.getMessage()), true); return null; } finally { this.memoryActionLock.unlock(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index b7c1f8d19a..f6bc122acf 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -37,9 +37,9 @@ public TaskMemoryPool(MemoryPool parent, String poolName, MemoryManager memoryMa } @Override - public synchronized void releaseSelf(String reason) { + public void releaseSelf(String reason, boolean isTriggeredInternal) { + super.releaseSelf(reason, isTriggeredInternal); this.memoryManager.removeCorrespondingTaskMemoryPool(Thread.currentThread().getName()); - super.releaseSelf(reason); } @Override diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java index cef1afff6a..7d05a8cf73 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java @@ -114,4 +114,19 @@ public void testOOM() { ByteBuf memoryBlock = (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes); Assert.assertNull(memoryBlock); } + + @Test + public void testReleaseMemory() { + + } + + @Test + public void testLocalArbitration() { + + } + + @Test + public void testGlobalArbitration() { + + } } From ab1bcde031772eec626af9e8d9a140c97ae13807 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Mon, 28 Oct 2024 00:56:20 +0800 Subject: [PATCH 26/48] complete memory management framework UT and fix all bugs --- .../hugegraph/memory/MemoryManager.java | 32 +++-- .../memory/pool/AbstractMemoryPool.java | 7 +- .../hugegraph/memory/pool/MemoryPool.java | 2 + .../memory/pool/impl/OperatorMemoryPool.java | 51 ++++--- .../memory/pool/impl/QueryMemoryPool.java | 39 ++++-- .../memory/pool/impl/TaskMemoryPool.java | 6 + .../core/memory/MemoryManageTest.java | 126 +++++++++++++++++- 7 files changed, 209 insertions(+), 54 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index 13e09c1b7a..75e09b600c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -34,6 +34,7 @@ import org.apache.hugegraph.memory.pool.impl.QueryMemoryPool; import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.ExecutorUtil; +import org.jetbrains.annotations.TestOnly; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,6 +48,7 @@ public class MemoryManager { // TODO: read it from conf, current 1G public static final long MAX_MEMORY_CAPACITY_IN_BYTES = Bytes.GB; + // Current available memory = MAX_MEMORY_CAPACITY - sum(allocated bytes) private final AtomicLong currentAvailableMemoryInBytes = new AtomicLong(MAX_MEMORY_CAPACITY_IN_BYTES); private final AtomicLong currentOffHeapAllocatedMemoryInBytes = new AtomicLong(0); @@ -79,9 +81,15 @@ public MemoryPool addQueryMemoryPool() { public void gcQueryMemoryPool(MemoryPool pool) { LOG.info("Manager gc query memory pool {}", pool); queryMemoryPools.remove(pool); - long reclaimedMemory = pool.getAllocatedBytes(); pool.releaseSelf(String.format("GC query memory pool %s", pool), false); - currentAvailableMemoryInBytes.addAndGet(reclaimedMemory); + } + + public void returnReclaimedTaskMemory(long bytes) { + currentAvailableMemoryInBytes.addAndGet(bytes); + } + + public void consumeAvailableMemory(long size) { + currentAvailableMemoryInBytes.addAndGet(-size); } public long triggerLocalArbitration(MemoryPool targetPool, long neededBytes) { @@ -119,18 +127,13 @@ public long triggerGlobalArbitration(MemoryPool requestPool, long neededBytes) { return 0; } - public synchronized long handleRequestFromQueryPool(long size) { - // 1. check whole memory capacity. + public synchronized long handleRequestFromQueryPool(long size, String action) { if (currentAvailableMemoryInBytes.get() < size) { - LOG.info("There isn't enough memory for query pool to expand itself: " + - "requestSize={}, remainingCapacity={}", size, + LOG.info("There isn't enough memory for query pool to {}: " + + "requestSize={}, remainingCapacity={}", size, action, currentAvailableMemoryInBytes.get()); return -1; } - currentAvailableMemoryInBytes.addAndGet(-size); - LOG.info("Expand query pool successfully: " + - "requestSize={}, afterThisExpandingRemainingCapacity={}", size, - currentAvailableMemoryInBytes.get()); return size; } @@ -153,10 +156,6 @@ public Queue getCurrentQueryMemoryPools() { return new PriorityQueue<>(queryMemoryPools); } - public void consumeAvailableMemory(long size) { - currentAvailableMemoryInBytes.addAndGet(-size); - } - public AtomicLong getCurrentOnHeapAllocatedMemoryInBytes() { return currentOnHeapAllocatedMemoryInBytes; } @@ -165,6 +164,11 @@ public AtomicLong getCurrentOffHeapAllocatedMemoryInBytes() { return currentOffHeapAllocatedMemoryInBytes; } + @TestOnly + public AtomicLong getCurrentAvailableMemoryInBytes() { + return currentAvailableMemoryInBytes; + } + private static class MemoryManagerHolder { private static final MemoryManager INSTANCE = new MemoryManager(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index e4ea807763..a620e2aabf 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -131,12 +131,12 @@ public void releaseSelf(String reason, boolean isTriggeredInternal) { public void gcChildPool(MemoryPool child, boolean force, boolean isTriggeredInternal) { if (force) { child.releaseSelf(String.format("[%s] releaseChildPool", this), isTriggeredInternal); + return; } // reclaim child's memory and update stats this.stats.setAllocatedBytes( stats.getAllocatedBytes() - child.getAllocatedBytes()); this.stats.setUsedBytes(this.stats.getUsedBytes() - child.getUsedBytes()); - memoryManager.consumeAvailableMemory(-child.getAllocatedBytes()); this.children.remove(child); } @@ -211,6 +211,11 @@ public MemoryPool findRootQueryPool() { return getParentPool().findRootQueryPool(); } + @Override + public void setMaxCapacityBytes(long maxCapacityBytes) { + this.stats.setMaxCapacity(maxCapacityBytes); + } + @TestOnly public int getChildrenCount() { return this.children.size(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index 61f297cf4f..ff89043a35 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -69,6 +69,8 @@ public interface MemoryPool { void bindMemoryConsumer(MemoryConsumer memoryConsumer); + void setMaxCapacityBytes(long maxCapacityBytes); + @TestOnly int getChildrenCount(); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index afb6e9bf2a..f3279b7b62 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -58,12 +58,14 @@ public void releaseSelf(String reason, boolean isTriggeredInternal) { super.releaseSelf(reason, isTriggeredInternal); // since it is already closed, its stats will not be updated. so here we can use its // stats out of memoryActionLock. - this.memoryAllocator.returnMemoryToManager(getAllocatedBytes()); + this.memoryAllocator.returnMemoryToManager(getUsedBytes()); + this.memoryManager.returnReclaimedTaskMemory(getAllocatedBytes()); // release memory consumer, release byte buffer. this.memoryConsumers.forEach(memoryConsumer -> { memoryConsumer.getAllMemoryBlock().forEach(memoryAllocator::releaseMemoryBlock); }); this.memoryConsumers.clear(); + this.resetStats(); } @Override @@ -118,7 +120,14 @@ public Object requireMemory(long bytes) { try { // use lock to ensure the atomicity of the two-step operation this.memoryActionLock.lock(); - long ignoredRealAllocatedBytes = requestMemoryInternal(bytes); + // if free memory is enough, use free memory directly. + if (getFreeBytes() >= bytes) { + this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() - bytes); + } else { + // if free memory is not enough, try to request delta + long delta = bytes - getFreeBytes(); + long ignoredRealAllocatedBytes = requestMemoryInternal(delta); + } return tryToAcquireMemoryInternal(bytes); } catch (QueryOutOfMemoryException e) { // Abort this query @@ -133,21 +142,27 @@ public Object requireMemory(long bytes) { } /** - * Operator need `size` bytes, operator pool will try to reserve some memory for it + * This method will update `used` and `cumulative` stats. */ @Override public Object tryToAcquireMemoryInternal(long size) { if (this.isClosed) { LOG.warn("[{}] is already closed, will abort this allocate", this); - return 0; + return null; } LOG.info("[{}] tryToAcquireMemory: size={}", this, size); // 1. update statistic super.tryToAcquireMemoryInternal(size); - // 2. allocate memory, currently use off-heap mode. + // 2. call parent to update statistic + getParentPool().tryToAcquireMemoryInternal(size); + // 3. allocate memory, currently use off-heap mode. return this.memoryAllocator.tryToAllocate(size); } + /** + * Operator need `size` bytes, operator pool will try to reserve some memory for it. + * This method will update `allocated` and `expand` stats. + */ @Override public long requestMemoryInternal(long size) throws QueryOutOfMemoryException { if (this.isClosed) { @@ -163,9 +178,6 @@ public long requestMemoryInternal(long size) throws QueryOutOfMemoryException { long alignedSize = MemoryManageUtils.sizeAlign(size); // 2. reserve(round) long neededMemorySize = calculateReserveMemoryDelta(alignedSize); - if (neededMemorySize <= 0) { - return 0; - } // 3. call father long fatherRes = getParentPool().requestMemoryInternal(neededMemorySize); if (fatherRes < 0) { @@ -188,17 +200,16 @@ public long requestMemoryInternal(long size) throws QueryOutOfMemoryException { } } - /** - * This method should be synchronized. - */ - private synchronized long calculateReserveMemoryDelta(long size) { - // 1. check whether you need to acquire memory or not - long neededSize = size - (getFreeBytes()); - // 2. if not needed, return 0 - if (neededSize <= 0) { - return 0; - } - // 3. if needed, calculate rounded size and return it - return MemoryManageUtils.roundDelta(getAllocatedBytes(), neededSize); + private long calculateReserveMemoryDelta(long size) { + return MemoryManageUtils.roundDelta(getAllocatedBytes(), size); + } + + private void resetStats() { + this.stats.setNumAborts(0); + this.stats.setNumExpands(0); + this.stats.setNumShrinks(0); + this.stats.setAllocatedBytes(0); + this.stats.setUsedBytes(0); + this.stats.setCumulativeBytes(0); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 27426be1a9..9f27cfc28b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -31,6 +31,8 @@ public class QueryMemoryPool extends AbstractMemoryPool { private static final Logger LOG = LoggerFactory.getLogger(QueryMemoryPool.class); private static final String TASK_MEMORY_POOL_NAME_PREFIX = "TaskMemoryPool"; + private static final String EXPAND_SELF = "expand self's max capacity"; + private static final String REQUEST_MEMORY = "request to allocate memory"; // TODO: read from conf private static final long QUERY_POOL_MAX_CAPACITY = Bytes.MB * 100; @@ -57,6 +59,8 @@ public long requestMemoryInternal(long bytes) { LOG.warn("[{}] is already closed, will abort this request", this); return 0; } + long requestedMemoryFromManager = 0; + long requestedMemoryFromArbitration = 0; try { if (this.isBeingArbitrated.get()) { this.condition.await(); @@ -64,25 +68,36 @@ public long requestMemoryInternal(long bytes) { // 1. check whether self capacity is enough if (getMaxCapacityBytes() - stats.getAllocatedBytes() < bytes) { // 2.1 if not, first try to acquire memory from manager - long managerReturnedMemoryInBytes = tryToExpandSelfCapacity(bytes); + long neededDelta = bytes - (getMaxCapacityBytes() - stats.getAllocatedBytes()); + long managerReturnedMemoryInBytes = tryToExpandSelfCapacity(neededDelta); if (managerReturnedMemoryInBytes > 0) { this.stats.setMaxCapacity(getMaxCapacityBytes() + managerReturnedMemoryInBytes); this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + bytes); this.stats.setNumExpands(this.stats.getNumExpands() + 1); - this.memoryManager.consumeAvailableMemory(bytes); - return bytes; + requestedMemoryFromManager = bytes; + } else { + // 2.2 if requiring memory from manager failed, call manager to invoke arbitrate + requestedMemoryFromArbitration = requestMemoryThroughArbitration(bytes); } - // 2.2 if requiring memory from manager failed, call manager to invoke arbitrate - // locally - return requestMemoryThroughArbitration(bytes); } else { - // 3. if capacity is enough, return success - this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + bytes); + // 3. if capacity is enough, check whether manager has enough memory. + if (this.memoryManager.handleRequestFromQueryPool(bytes, REQUEST_MEMORY) < 0) { + // 3.1 if memory manager doesn't have enough memory, call manager to invoke + // arbitrate + requestedMemoryFromArbitration = requestMemoryThroughArbitration(bytes); + } else { + // 3.2 if memory manager has enough memory, return success + this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + bytes); + requestedMemoryFromManager = bytes; + } + } + if (requestedMemoryFromManager > 0) { this.memoryManager.consumeAvailableMemory(bytes); - return bytes; } + return requestedMemoryFromManager == 0 ? requestedMemoryFromArbitration : + requestedMemoryFromManager; } catch (InterruptedException e) { - LOG.error("Failed to release self because ", e); + LOG.error("[{}] Failed to request memory because ", this, e); Thread.currentThread().interrupt(); return 0; } @@ -93,7 +108,7 @@ private long tryToExpandSelfCapacity(long size) { long alignedSize = MemoryManageUtils.sizeAlign(size); long realNeededSize = MemoryManageUtils.roundDelta(getAllocatedBytes(), alignedSize); - return this.memoryManager.handleRequestFromQueryPool(realNeededSize); + return this.memoryManager.handleRequestFromQueryPool(realNeededSize, EXPAND_SELF); } private long requestMemoryThroughArbitration(long bytes) { @@ -107,7 +122,6 @@ private long requestMemoryThroughArbitration(long bytes) { if (reclaimedBytes - bytes >= 0) { // here we don't update capacity & reserved & allocated, because memory is // reclaimed from queryPool itself. - this.memoryManager.consumeAvailableMemory(bytes); return bytes; } else { // 2. if still not enough, try to reclaim globally @@ -121,7 +135,6 @@ private long requestMemoryThroughArbitration(long bytes) { this.stats.setMaxCapacity(this.stats.getMaxCapacity() + globalReclaimedBytes); this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + bytes); this.stats.setNumExpands(this.stats.getNumExpands() + 1); - this.memoryManager.consumeAvailableMemory(bytes); return bytes; } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index f6bc122acf..d6ddb1d6e6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -57,6 +57,12 @@ public MemoryPool addChildPool() { return operatorPool; } + @Override + public Object tryToAcquireMemoryInternal(long bytes) { + getParentPool().tryToAcquireMemoryInternal(bytes); + return super.tryToAcquireMemoryInternal(bytes); + } + @Override public long requestMemoryInternal(long bytes) throws QueryOutOfMemoryException { if (this.isClosed) { diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java index 7d05a8cf73..59877ac525 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java @@ -21,7 +21,8 @@ import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.util.Bytes; -import org.junit.BeforeClass; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import io.netty.buffer.ByteBuf; @@ -64,8 +65,8 @@ public class MemoryManageTest { protected static String QUERY2_TASK1_THREAD_NAME = "QUERY2-THREAD-1"; protected static MemoryPool query2Task1Operator1MemoryPool; - @BeforeClass - public static void setUp() { + @Before + public void setUp() { memoryManager = MemoryManager.getInstance(); query1MemoryPool = memoryManager.addQueryMemoryPool(); query2MemoryPool = memoryManager.addQueryMemoryPool(); @@ -87,6 +88,19 @@ public static void setUp() { query2Task1Operator1MemoryPool = query2Task1MemoryPool.addChildPool(); } + @After + public void after() { + memoryManager.gcQueryMemoryPool(query1MemoryPool); + memoryManager.gcQueryMemoryPool(query2MemoryPool); + memoryManager.getCurrentAvailableMemoryInBytes() + .set(MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES); + Assert.assertEquals(0, memoryManager.getCurrentQueryMemoryPools().size()); + Assert.assertEquals(0, query1MemoryPool.getAllocatedBytes()); + Assert.assertEquals(0, query2MemoryPool.getAllocatedBytes()); + Assert.assertEquals(0, query1Task1Operator2MemoryPool.getAllocatedBytes()); + Assert.assertEquals(0, memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().get()); + } + @Test public void testMemoryPoolStructure() { Assert.assertEquals(2, memoryManager.getCurrentQueryMemoryPools().size()); @@ -106,6 +120,20 @@ public void testRequiringMemory() { ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); Assert.assertNotNull(memoryBlock); Assert.assertEquals(requireBytes, memoryBlock.capacity()); + Assert.assertEquals(requireBytes, + memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().get()); + Assert.assertEquals( + MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES - query1MemoryPool.getAllocatedBytes(), + memoryManager.getCurrentAvailableMemoryInBytes().get()); + // will use reserved memory, not requiring memory through manager + ByteBuf memoryBlock2 = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + Assert.assertNotNull(memoryBlock2); + Assert.assertEquals(requireBytes, memoryBlock2.capacity()); + Assert.assertEquals(requireBytes * 2, + memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().get()); + Assert.assertEquals( + MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES - query1MemoryPool.getAllocatedBytes(), + memoryManager.getCurrentAvailableMemoryInBytes().get()); } @Test @@ -116,17 +144,103 @@ public void testOOM() { } @Test - public void testReleaseMemory() { + public void testReleaseMemoryWithTask() { + long requireBytes = Bytes.KB; + ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + Assert.assertNotNull(memoryBlock); + Assert.assertEquals(requireBytes, memoryBlock.capacity()); + query1Task1MemoryPool.releaseSelf("Test release by hand", false); + Assert.assertEquals(1, query1MemoryPool.getChildrenCount()); + Assert.assertEquals(0, query1MemoryPool.getAllocatedBytes()); + Assert.assertEquals(0, query1MemoryPool.getUsedBytes()); + Assert.assertEquals(0, query1Task1MemoryPool.getAllocatedBytes()); + Assert.assertEquals(0, query1Task1MemoryPool.getUsedBytes()); + Assert.assertEquals(0, memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().get()); + Assert.assertEquals(MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES, + memoryManager.getCurrentAvailableMemoryInBytes().get()); + } + @Test + public void testReleaseMemoryWithQuery() { + long requireBytes = Bytes.KB; + ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + Assert.assertNotNull(memoryBlock); + Assert.assertEquals(requireBytes, memoryBlock.capacity()); + query1MemoryPool.releaseSelf("Test release by hand", true); + Assert.assertEquals(0, query1MemoryPool.getChildrenCount()); + Assert.assertEquals(0, query1MemoryPool.getAllocatedBytes()); + Assert.assertEquals(0, query1MemoryPool.getUsedBytes()); + Assert.assertEquals(0, memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().get()); + Assert.assertEquals(MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES, + memoryManager.getCurrentAvailableMemoryInBytes().get()); } @Test - public void testLocalArbitration() { + public void testExpandCapacity() { + long requireBytes = Bytes.KB; + ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + Assert.assertNotNull(memoryBlock); + Assert.assertEquals(requireBytes, memoryBlock.capacity()); + long maxCapacity = Bytes.KB * 100; + query2MemoryPool.setMaxCapacityBytes(maxCapacity); + long requireBytes2 = maxCapacity * 2; + ByteBuf memoryBlock2 = + (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes2); + Assert.assertNotNull(memoryBlock2); + Assert.assertEquals(requireBytes2, memoryBlock2.capacity()); + Assert.assertEquals(requireBytes2 + requireBytes, + memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().get()); + Assert.assertEquals( + MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES - query1MemoryPool.getAllocatedBytes() - + query2MemoryPool.getAllocatedBytes(), + memoryManager.getCurrentAvailableMemoryInBytes().get()); } @Test - public void testGlobalArbitration() { + public void testLocalArbitrationFail() { + long totalMemory = 2 * Bytes.MB + Bytes.KB; + memoryManager.getCurrentAvailableMemoryInBytes().set(totalMemory); + long requireBytes = Bytes.KB; + // will allocate 2MB + ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + long requireBytes2 = Bytes.MB; + ByteBuf memoryBlock2 = + (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes2); + Assert.assertEquals(Bytes.MB * 2, query1MemoryPool.getAllocatedBytes()); + // query1 remaining 1023KB + Assert.assertEquals(Bytes.MB * 2 - requireBytes2 - requireBytes, + query1MemoryPool.getFreeBytes()); + // totally remaining 1KB + Assert.assertEquals(totalMemory - 2 * Bytes.MB, + memoryManager.getCurrentAvailableMemoryInBytes().get()); + // will try to allocate 1MB and trigger arbitration, which will fail and result in OOM + ByteBuf memoryBlock3 = (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes); + Assert.assertNull(memoryBlock3); + Assert.assertEquals(0, query2MemoryPool.getAllocatedBytes()); + } + @Test + public void testGlobalArbitration() { + long totalMemory = 20 * Bytes.MB + Bytes.KB; + memoryManager.getCurrentAvailableMemoryInBytes().set(totalMemory); + long requireBytes = Bytes.MB * 17; + // will allocate 20MB + ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + Assert.assertEquals(Bytes.MB * 20, query1MemoryPool.getAllocatedBytes()); + // query1 remaining 3MB + Assert.assertEquals(Bytes.MB * 3, + query1MemoryPool.getFreeBytes()); + // totally remaining 1KB + Assert.assertEquals(Bytes.KB, memoryManager.getCurrentAvailableMemoryInBytes().get()); + // will try to allocate 1MB and trigger arbitration, which will success + long requireBytes2 = Bytes.KB; + ByteBuf memoryBlock2 = + (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes2); + Assert.assertNotNull(memoryBlock2); + Assert.assertEquals(Bytes.MB, query2MemoryPool.getAllocatedBytes()); + Assert.assertEquals(Bytes.KB, memoryBlock2.capacity()); + // totally still remain 1KB + Assert.assertEquals(Bytes.KB, memoryManager.getCurrentAvailableMemoryInBytes().get()); } } From 91df57a942f2b94bb32c13c959d9f3cd27fe424b Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Mon, 28 Oct 2024 01:00:37 +0800 Subject: [PATCH 27/48] fix ut --- .../org/apache/hugegraph/core/memory/MemoryManageTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java index 59877ac525..3f1e770df8 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java @@ -53,7 +53,7 @@ public class MemoryManageTest { protected static MemoryManager memoryManager; protected static MemoryPool query1MemoryPool; protected static MemoryPool query1Task1MemoryPool; - protected static String QUERY1_TASK1_THREAD_NAME = "QUERY1-THREAD-1"; + protected static String QUERY1_TASK1_THREAD_NAME = "main"; protected static MemoryPool query1Task2MemoryPool; protected static String QUERY1_TASK2_THREAD_NAME = "QUERY1-THREAD-2"; protected static MemoryPool query1Task1Operator1MemoryPool; @@ -149,7 +149,9 @@ public void testReleaseMemoryWithTask() { ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); Assert.assertNotNull(memoryBlock); Assert.assertEquals(requireBytes, memoryBlock.capacity()); - query1Task1MemoryPool.releaseSelf("Test release by hand", false); + memoryManager.getCorrespondingTaskMemoryPool(QUERY1_TASK1_THREAD_NAME) + .releaseSelf("Test release by hand", false); + Assert.assertNull(memoryManager.getCorrespondingTaskMemoryPool(QUERY1_TASK1_THREAD_NAME)); Assert.assertEquals(1, query1MemoryPool.getChildrenCount()); Assert.assertEquals(0, query1MemoryPool.getAllocatedBytes()); Assert.assertEquals(0, query1MemoryPool.getUsedBytes()); From 52ca7aff9996d87f5ec5dd2c838535438108b6f7 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Mon, 28 Oct 2024 11:59:18 +0800 Subject: [PATCH 28/48] keep format consistent with original version --- .../hugegraph/backend/serializer/BinaryBackendEntry.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryBackendEntry.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryBackendEntry.java index 9dfb8b4e5c..61f4545cf1 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryBackendEntry.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinaryBackendEntry.java @@ -49,8 +49,7 @@ public BinaryBackendEntry(HugeType type, byte[] bytes, boolean enablePartition) } // FIXME: `enablePartition` is unused here - public BinaryBackendEntry(HugeType type, byte[] bytes, boolean enablePartition, - boolean isOlap) { + public BinaryBackendEntry(HugeType type, byte[] bytes, boolean enablePartition, boolean isOlap) { this(type, BytesBuffer.wrap(bytes).parseOlapId(type, isOlap)); } From ee8e1259e3c9c78e58d485e1883384b780f4f849 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Mon, 28 Oct 2024 12:02:55 +0800 Subject: [PATCH 29/48] fix review --- ...rategy.java => OnHeapMemoryAllocator.java} | 4 +- ...MemoryConsumer.java => OffHeapObject.java} | 15 +++-- .../consumer/impl/id/BinaryIdOffHeap.java | 23 +++----- .../consumer/impl/id/EdgeIdOffHeap.java | 59 +++++++++---------- .../consumer/impl/id/LongIdOffHeap.java | 25 +++----- .../consumer/impl/id/ObjectIdOffHeap.java | 30 ++++------ .../consumer/impl/id/QueryIdOffHeap.java | 19 ++---- .../consumer/impl/id/StringIdOffHeap.java | 24 +++----- .../consumer/impl/id/UuidIdOffHeap.java | 37 +++++------- .../property/HugeEdgePropertyOffHeap.java | 27 ++++----- .../property/HugeVertexPropertyOffHeap.java | 27 ++++----- .../memory/pool/AbstractMemoryPool.java | 4 +- .../hugegraph/memory/pool/MemoryPool.java | 8 +-- .../memory/pool/impl/OperatorMemoryPool.java | 32 +++++----- .../memory/pool/impl/QueryMemoryPool.java | 6 +- .../memory/pool/impl/TaskMemoryPool.java | 4 +- ...nUtils.java => FurySerializationUtil.java} | 2 +- ...moryAccess.java => OffHeapMemoryUtil.java} | 4 +- ...ception.java => OutOfMemoryException.java} | 15 +++-- ...{MemoryManageUtils.java => RoundUtil.java} | 2 +- .../core/memory/MemoryAllocateTest.java | 4 +- .../core/memory/MemoryConsumerTest.java | 5 ++ 22 files changed, 160 insertions(+), 216 deletions(-) rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/{OnHeapMemoryStrategy.java => OnHeapMemoryAllocator.java} (94%) rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/{MemoryConsumer.java => OffHeapObject.java} (79%) rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/{FurySerializationUtils.java => FurySerializationUtil.java} (97%) rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/{OffHeapMemoryAccess.java => OffHeapMemoryUtil.java} (98%) rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/{QueryOutOfMemoryException.java => OutOfMemoryException.java} (66%) rename hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/{MemoryManageUtils.java => RoundUtil.java} (98%) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryAllocator.java similarity index 94% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java rename to hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryAllocator.java index 9da832ad1b..3ed229b417 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryStrategy.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/OnHeapMemoryAllocator.java @@ -21,11 +21,11 @@ import org.apache.hugegraph.memory.MemoryManager; -public class OnHeapMemoryStrategy implements MemoryAllocator { +public class OnHeapMemoryAllocator implements MemoryAllocator { private final MemoryManager memoryManager; - public OnHeapMemoryStrategy(MemoryManager memoryManager) { + public OnHeapMemoryAllocator(MemoryManager memoryManager) { this.memoryManager = memoryManager; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/OffHeapObject.java similarity index 79% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java rename to hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/OffHeapObject.java index aebbedc17e..6af72abe88 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/MemoryConsumer.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/OffHeapObject.java @@ -26,10 +26,10 @@ /** * This interface is used by immutable, memory-heavy objects which will be stored in off heap. */ -public interface MemoryConsumer { +public interface OffHeapObject { /** - * This method will read Off heap ByteBuf storing binary data of self. + * This method will read from off-heap ByteBuf storing binary data of self. * * @return self value */ @@ -39,15 +39,18 @@ public interface MemoryConsumer { * Serialize to DataOutputStream in stack first, then request an off heap ByteBuf from * OperatorMemoryPool based on size of DataOutputStream. Finally, serializing it to ByteBuf. */ - void serializeSelfToByteBuf(); + void serializeSelfToByteBuf(MemoryPool memoryPool); /** * Called after serializingSelfToByteBuf, pointing all self's on heap vars to null, in order * to let GC release all its on heap memory. */ - void releaseOriginalOnHeapVars(); - - MemoryPool getOperatorMemoryPool(); + void releaseOriginalVarsOnHeap(); + /** + * Called by memoryPool to release all its holding memory block when memoryPool release self. + * + * @return all holding memory block allocated by memoryPool + */ List getAllMemoryBlock(); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java index 51be29796a..830003b16b 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java @@ -22,7 +22,7 @@ import org.apache.hugegraph.backend.id.Id; import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.E; @@ -30,22 +30,20 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -public class BinaryIdOffHeap extends BinaryBackendEntry.BinaryId implements MemoryConsumer { +public class BinaryIdOffHeap extends BinaryBackendEntry.BinaryId implements OffHeapObject { - private final MemoryPool memoryPool; - private final MemoryConsumer originId; + private final OffHeapObject originId; private ByteBuf bytesOffHeap; - public BinaryIdOffHeap(byte[] bytes, Id id, MemoryPool memoryPool, MemoryConsumer originId) { + public BinaryIdOffHeap(byte[] bytes, Id id, MemoryPool memoryPool, OffHeapObject originId) { super(bytes, id); - this.memoryPool = memoryPool; this.originId = originId; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } @Override - public void serializeSelfToByteBuf() { + public void serializeSelfToByteBuf(MemoryPool memoryPool) { this.bytesOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); this.bytesOffHeap.markReaderIndex(); this.bytesOffHeap.writeBytes(bytes); @@ -57,18 +55,13 @@ public BinaryBackendEntry.BinaryId zeroCopyReadFromByteBuf() { (Id) originId.zeroCopyReadFromByteBuf()); } - @Override - public MemoryPool getOperatorMemoryPool() { - return this.memoryPool; - } - @Override public List getAllMemoryBlock() { return Collections.singletonList(bytesOffHeap); } @Override - public void releaseOriginalOnHeapVars() { + public void releaseOriginalVarsOnHeap() { this.bytes = null; this.id = null; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java index 7380376ce2..a1467e8640 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java @@ -25,7 +25,7 @@ import org.apache.hugegraph.backend.id.Id; import org.apache.hugegraph.backend.id.IdUtil; import org.apache.hugegraph.backend.id.SplicingIdGenerator; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.type.define.Directions; @@ -35,13 +35,13 @@ import io.netty.buffer.ByteBuf; // TODO: rewrite static method in EdgeId -public class EdgeIdOffHeap extends EdgeId implements MemoryConsumer { +public class EdgeIdOffHeap extends EdgeId implements OffHeapObject { private final MemoryPool memoryPool; - private final MemoryConsumer ownerVertexIdOffHeap; - private final MemoryConsumer edgeLabelIdOffHeap; - private final MemoryConsumer subLabelIdOffHeap; - private final MemoryConsumer otherVertexIdOffHeap; + private final OffHeapObject ownerVertexIdOffHeap; + private final OffHeapObject edgeLabelIdOffHeap; + private final OffHeapObject subLabelIdOffHeap; + private final OffHeapObject otherVertexIdOffHeap; private ByteBuf sortValuesOffHeap; private ByteBuf cacheOffHeap; @@ -52,18 +52,18 @@ public EdgeIdOffHeap(HugeVertex ownerVertex, String sortValues, HugeVertex otherVertex, MemoryPool memoryPool, - MemoryConsumer ownerVertexIdOffHeap, - MemoryConsumer edgeLabelIdOffHeap, - MemoryConsumer subLabelIdOffHeap, - MemoryConsumer otherVertexIdOffHeap) { + OffHeapObject ownerVertexIdOffHeap, + OffHeapObject edgeLabelIdOffHeap, + OffHeapObject subLabelIdOffHeap, + OffHeapObject otherVertexIdOffHeap) { super(ownerVertex, direction, edgeLabelId, subLabelId, sortValues, otherVertex); this.memoryPool = memoryPool; this.ownerVertexIdOffHeap = ownerVertexIdOffHeap; this.edgeLabelIdOffHeap = edgeLabelIdOffHeap; this.subLabelIdOffHeap = subLabelIdOffHeap; this.otherVertexIdOffHeap = otherVertexIdOffHeap; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } public EdgeIdOffHeap(Id ownerVertexId, @@ -73,10 +73,10 @@ public EdgeIdOffHeap(Id ownerVertexId, String sortValues, Id otherVertexId, MemoryPool memoryPool, - MemoryConsumer ownerVertexIdOffHeap, - MemoryConsumer edgeLabelIdOffHeap, - MemoryConsumer subLabelIdOffHeap, - MemoryConsumer otherVertexIdOffHeap) { + OffHeapObject ownerVertexIdOffHeap, + OffHeapObject edgeLabelIdOffHeap, + OffHeapObject subLabelIdOffHeap, + OffHeapObject otherVertexIdOffHeap) { super(ownerVertexId, direction, edgeLabelId, subLabelId, sortValues, otherVertexId, false); this.memoryPool = memoryPool; @@ -84,8 +84,8 @@ public EdgeIdOffHeap(Id ownerVertexId, this.edgeLabelIdOffHeap = edgeLabelIdOffHeap; this.subLabelIdOffHeap = subLabelIdOffHeap; this.otherVertexIdOffHeap = otherVertexIdOffHeap; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } public EdgeIdOffHeap(Id ownerVertexId, @@ -96,10 +96,10 @@ public EdgeIdOffHeap(Id ownerVertexId, Id otherVertexId, boolean directed, MemoryPool memoryPool, - MemoryConsumer ownerVertexIdOffHeap, - MemoryConsumer edgeLabelIdOffHeap, - MemoryConsumer subLabelIdOffHeap, - MemoryConsumer otherVertexIdOffHeap) { + OffHeapObject ownerVertexIdOffHeap, + OffHeapObject edgeLabelIdOffHeap, + OffHeapObject subLabelIdOffHeap, + OffHeapObject otherVertexIdOffHeap) { super(ownerVertexId, direction, edgeLabelId, subLabelId, sortValues, otherVertexId, directed); this.memoryPool = memoryPool; @@ -107,8 +107,8 @@ public EdgeIdOffHeap(Id ownerVertexId, this.edgeLabelIdOffHeap = edgeLabelIdOffHeap; this.subLabelIdOffHeap = subLabelIdOffHeap; this.otherVertexIdOffHeap = otherVertexIdOffHeap; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } @Override @@ -126,23 +126,18 @@ public Object zeroCopyReadFromByteBuf() { } @Override - public void serializeSelfToByteBuf() { + public void serializeSelfToByteBuf(MemoryPool memoryPool) { byte[] stringBytes = sortValues.getBytes((StandardCharsets.UTF_8)); - this.sortValuesOffHeap = (ByteBuf) memoryPool.requireMemory(stringBytes.length); + this.sortValuesOffHeap = (ByteBuf) this.memoryPool.requireMemory(stringBytes.length); this.sortValuesOffHeap.markReaderIndex(); this.sortValuesOffHeap.writeBytes(stringBytes); } @Override - public void releaseOriginalOnHeapVars() { + public void releaseOriginalVarsOnHeap() { this.sortValues = null; } - @Override - public MemoryPool getOperatorMemoryPool() { - return memoryPool; - } - @Override public List getAllMemoryBlock() { return Lists.newArrayList(this.sortValuesOffHeap, this.cacheOffHeap); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java index eefa44bc73..9ebb01140e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java @@ -25,29 +25,26 @@ import org.apache.hugegraph.backend.id.Id; import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.util.NumericUtil; import io.netty.buffer.ByteBuf; -public class LongIdOffHeap extends IdGenerator.LongId implements MemoryConsumer { +public class LongIdOffHeap extends IdGenerator.LongId implements OffHeapObject { - private final MemoryPool memoryPool; private ByteBuf idOffHeap; public LongIdOffHeap(MemoryPool memoryPool, long id) { super(id); - this.memoryPool = memoryPool; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } public LongIdOffHeap(MemoryPool memoryPool, byte[] bytes) { super(bytes); - this.memoryPool = memoryPool; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } @Override @@ -57,26 +54,20 @@ public Object zeroCopyReadFromByteBuf() { } finally { idOffHeap.resetReaderIndex(); } - } @Override - public void serializeSelfToByteBuf() { + public void serializeSelfToByteBuf(MemoryPool memoryPool) { this.idOffHeap = (ByteBuf) memoryPool.requireMemory(Long.BYTES); this.idOffHeap.markReaderIndex(); this.idOffHeap.writeLong(id); } @Override - public void releaseOriginalOnHeapVars() { + public void releaseOriginalVarsOnHeap() { this.id = null; } - @Override - public MemoryPool getOperatorMemoryPool() { - return memoryPool; - } - @Override public List getAllMemoryBlock() { return Collections.singletonList(idOffHeap); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java index 8097dbb736..b1bcba67a7 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java @@ -22,49 +22,42 @@ import java.util.Objects; import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; -import org.apache.hugegraph.memory.util.FurySerializationUtils; +import org.apache.hugegraph.memory.util.FurySerializationUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -public class ObjectIdOffHeap extends IdGenerator.ObjectId implements MemoryConsumer { +public class ObjectIdOffHeap extends IdGenerator.ObjectId implements OffHeapObject { - private final MemoryPool memoryPool; private ByteBuf objectOffHeap; public ObjectIdOffHeap(Object object, MemoryPool memoryPool) { super(object); - this.memoryPool = memoryPool; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } @Override public Object zeroCopyReadFromByteBuf() { - return new IdGenerator.ObjectId(FurySerializationUtils.FURY.deserialize( + return new IdGenerator.ObjectId(FurySerializationUtil.FURY.deserialize( ByteBufUtil.getBytes(this.objectOffHeap))); } @Override - public void serializeSelfToByteBuf() { - byte[] bytes = FurySerializationUtils.FURY.serialize(object); + public void serializeSelfToByteBuf(MemoryPool memoryPool) { + byte[] bytes = FurySerializationUtil.FURY.serialize(object); this.objectOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); this.objectOffHeap.markReaderIndex(); this.objectOffHeap.writeBytes(bytes); } @Override - public void releaseOriginalOnHeapVars() { + public void releaseOriginalVarsOnHeap() { this.object = null; } - @Override - public MemoryPool getOperatorMemoryPool() { - return memoryPool; - } - @Override public List getAllMemoryBlock() { return Collections.singletonList(objectOffHeap); @@ -72,7 +65,7 @@ public List getAllMemoryBlock() { @Override public Object asObject() { - return FurySerializationUtils.FURY.deserialize(ByteBufUtil.getBytes(objectOffHeap)); + return FurySerializationUtil.FURY.deserialize(ByteBufUtil.getBytes(objectOffHeap)); } @Override @@ -93,6 +86,3 @@ public String toString() { return super.toString(); } } - - - diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java index d99fa4d66d..8209468d7f 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java @@ -24,22 +24,20 @@ import org.apache.hugegraph.backend.cache.CachedBackendStore; import org.apache.hugegraph.backend.id.Id; import org.apache.hugegraph.backend.query.Query; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -public class QueryIdOffHeap extends CachedBackendStore.QueryId implements MemoryConsumer { +public class QueryIdOffHeap extends CachedBackendStore.QueryId implements OffHeapObject { - private final MemoryPool memoryPool; private ByteBuf queryOffHeap; public QueryIdOffHeap(MemoryPool memoryPool, Query q) { super(q); - this.memoryPool = memoryPool; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } @Override @@ -54,7 +52,7 @@ public Object zeroCopyReadFromByteBuf() { } @Override - public void serializeSelfToByteBuf() { + public void serializeSelfToByteBuf(MemoryPool memoryPool) { byte[] stringBytes = query.getBytes((StandardCharsets.UTF_8)); this.queryOffHeap = (ByteBuf) memoryPool.requireMemory(stringBytes.length); this.queryOffHeap.markReaderIndex(); @@ -62,15 +60,10 @@ public void serializeSelfToByteBuf() { } @Override - public void releaseOriginalOnHeapVars() { + public void releaseOriginalVarsOnHeap() { this.query = null; } - @Override - public MemoryPool getOperatorMemoryPool() { - return memoryPool; - } - @Override public List getAllMemoryBlock() { return Collections.singletonList(queryOffHeap); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java index dc57d17538..5862910a76 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java @@ -25,29 +25,26 @@ import org.apache.hugegraph.backend.id.Id; import org.apache.hugegraph.backend.id.IdGenerator; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -public class StringIdOffHeap extends IdGenerator.StringId implements MemoryConsumer { +public class StringIdOffHeap extends IdGenerator.StringId implements OffHeapObject { - private final MemoryPool memoryPool; private ByteBuf idOffHeap; public StringIdOffHeap(MemoryPool memoryPool, String id) { super(id); - this.memoryPool = memoryPool; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } public StringIdOffHeap(MemoryPool memoryPool, byte[] bytes) { super(bytes); - this.memoryPool = memoryPool; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } @Override @@ -60,7 +57,7 @@ public Object zeroCopyReadFromByteBuf() { } @Override - public void serializeSelfToByteBuf() { + public void serializeSelfToByteBuf(MemoryPool memoryPool) { byte[] stringBytes = id.getBytes((StandardCharsets.UTF_8)); this.idOffHeap = (ByteBuf) memoryPool.requireMemory(stringBytes.length); this.idOffHeap.markReaderIndex(); @@ -68,15 +65,10 @@ public void serializeSelfToByteBuf() { } @Override - public void releaseOriginalOnHeapVars() { + public void releaseOriginalVarsOnHeap() { this.id = null; } - @Override - public MemoryPool getOperatorMemoryPool() { - return memoryPool; - } - @Override public List getAllMemoryBlock() { return Collections.singletonList(idOffHeap); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java index 4335adc87e..db67f92bd9 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java @@ -27,9 +27,9 @@ import org.apache.hugegraph.backend.id.Id; import org.apache.hugegraph.backend.id.IdGenerator; import org.apache.hugegraph.backend.serializer.BytesBuffer; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; -import org.apache.hugegraph.memory.util.FurySerializationUtils; +import org.apache.hugegraph.memory.util.FurySerializationUtil; import org.apache.hugegraph.memory.util.SerializationRuntimeException; import org.apache.hugegraph.util.E; import org.slf4j.Logger; @@ -38,57 +38,48 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -public class UuidIdOffHeap extends IdGenerator.UuidId implements MemoryConsumer { +public class UuidIdOffHeap extends IdGenerator.UuidId implements OffHeapObject { private static final Logger LOG = LoggerFactory.getLogger(UuidIdOffHeap.class); - private final MemoryPool memoryPool; private ByteBuf idOffHeap; public UuidIdOffHeap(MemoryPool memoryPool, String string) { super(string); - this.memoryPool = memoryPool; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } public UuidIdOffHeap(MemoryPool memoryPool, byte[] bytes) { super(bytes); - this.memoryPool = memoryPool; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } public UuidIdOffHeap(MemoryPool memoryPool, UUID uuid) { super(uuid); - this.memoryPool = memoryPool; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } @Override public Object zeroCopyReadFromByteBuf() { - return new IdGenerator.UuidId((UUID) FurySerializationUtils.FURY.deserialize( + return new IdGenerator.UuidId((UUID) FurySerializationUtil.FURY.deserialize( ByteBufUtil.getBytes(this.idOffHeap))); } @Override - public void serializeSelfToByteBuf() { - byte[] bytes = FurySerializationUtils.FURY.serialize(uuid); + public void serializeSelfToByteBuf(MemoryPool memoryPool) { + byte[] bytes = FurySerializationUtil.FURY.serialize(uuid); this.idOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); this.idOffHeap.markReaderIndex(); this.idOffHeap.writeBytes(bytes); } @Override - public void releaseOriginalOnHeapVars() { + public void releaseOriginalVarsOnHeap() { this.uuid = null; } - @Override - public MemoryPool getOperatorMemoryPool() { - return memoryPool; - } - @Override public List getAllMemoryBlock() { return Collections.singletonList(idOffHeap); @@ -96,7 +87,7 @@ public List getAllMemoryBlock() { @Override public Object asObject() { - return FurySerializationUtils.FURY.deserialize( + return FurySerializationUtil.FURY.deserialize( ByteBufUtil.getBytes(this.idOffHeap)); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java index 2a53689f95..9c3ae2543d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java @@ -21,9 +21,9 @@ import java.util.List; import java.util.NoSuchElementException; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; -import org.apache.hugegraph.memory.util.FurySerializationUtils; +import org.apache.hugegraph.memory.util.FurySerializationUtil; import org.apache.hugegraph.schema.PropertyKey; import org.apache.hugegraph.structure.HugeEdge; import org.apache.hugegraph.structure.HugeEdgeProperty; @@ -32,44 +32,37 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -public class HugeEdgePropertyOffHeap extends HugeEdgeProperty implements MemoryConsumer { +public class HugeEdgePropertyOffHeap extends HugeEdgeProperty implements OffHeapObject { - private final MemoryPool memoryPool; private ByteBuf valueOffHeap; public HugeEdgePropertyOffHeap(MemoryPool memoryPool, HugeElement owner, PropertyKey key, V value) { super(owner, key, value); - this.memoryPool = memoryPool; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } @Override public Object zeroCopyReadFromByteBuf() { return new HugeEdgeProperty<>(this.owner, this.pkey, - FurySerializationUtils.FURY.deserialize( + FurySerializationUtil.FURY.deserialize( ByteBufUtil.getBytes(this.valueOffHeap))); } @Override - public void serializeSelfToByteBuf() { - byte[] bytes = FurySerializationUtils.FURY.serialize(this.value); + public void serializeSelfToByteBuf(MemoryPool memoryPool) { + byte[] bytes = FurySerializationUtil.FURY.serialize(this.value); this.valueOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); this.valueOffHeap.markReaderIndex(); this.valueOffHeap.writeBytes(bytes); } @Override - public void releaseOriginalOnHeapVars() { + public void releaseOriginalVarsOnHeap() { this.value = null; } - @Override - public MemoryPool getOperatorMemoryPool() { - return memoryPool; - } - @Override public List getAllMemoryBlock() { return Collections.singletonList(valueOffHeap); @@ -94,7 +87,7 @@ public boolean isPresent() { @Override public V value() throws NoSuchElementException { - return (V) FurySerializationUtils.FURY.deserialize( + return (V) FurySerializationUtil.FURY.deserialize( ByteBufUtil.getBytes(this.valueOffHeap)); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java index 5796edb84a..8afed48a77 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java @@ -21,9 +21,9 @@ import java.util.List; import java.util.NoSuchElementException; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; -import org.apache.hugegraph.memory.util.FurySerializationUtils; +import org.apache.hugegraph.memory.util.FurySerializationUtil; import org.apache.hugegraph.schema.PropertyKey; import org.apache.hugegraph.structure.HugeElement; import org.apache.hugegraph.structure.HugeVertexProperty; @@ -31,44 +31,37 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -public class HugeVertexPropertyOffHeap extends HugeVertexProperty implements MemoryConsumer { +public class HugeVertexPropertyOffHeap extends HugeVertexProperty implements OffHeapObject { - private final MemoryPool memoryPool; private ByteBuf valueOffHeap; public HugeVertexPropertyOffHeap(MemoryPool memoryPool, HugeElement owner, PropertyKey key, V value) { super(owner, key, value); - this.memoryPool = memoryPool; - serializeSelfToByteBuf(); - releaseOriginalOnHeapVars(); + serializeSelfToByteBuf(memoryPool); + releaseOriginalVarsOnHeap(); } @Override public Object zeroCopyReadFromByteBuf() { return new HugeVertexProperty<>(this.owner, this.pkey, - FurySerializationUtils.FURY.deserialize( + FurySerializationUtil.FURY.deserialize( ByteBufUtil.getBytes(this.valueOffHeap))); } @Override - public void serializeSelfToByteBuf() { - byte[] bytes = FurySerializationUtils.FURY.serialize(this.value); + public void serializeSelfToByteBuf(MemoryPool memoryPool) { + byte[] bytes = FurySerializationUtil.FURY.serialize(this.value); this.valueOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); this.valueOffHeap.markReaderIndex(); this.valueOffHeap.writeBytes(bytes); } @Override - public void releaseOriginalOnHeapVars() { + public void releaseOriginalVarsOnHeap() { this.value = null; } - @Override - public MemoryPool getOperatorMemoryPool() { - return memoryPool; - } - @Override public List getAllMemoryBlock() { return Collections.singletonList(valueOffHeap); @@ -86,7 +79,7 @@ public boolean isPresent() { @Override public V value() throws NoSuchElementException { - return (V) FurySerializationUtils.FURY.deserialize( + return (V) FurySerializationUtil.FURY.deserialize( ByteBufUtil.getBytes(this.valueOffHeap)); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index a620e2aabf..c7498b3572 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -25,7 +25,7 @@ import java.util.concurrent.locks.ReentrantLock; import org.apache.hugegraph.memory.MemoryManager; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; import org.jetbrains.annotations.TestOnly; import org.slf4j.Logger; @@ -153,7 +153,7 @@ public Object tryToAcquireMemoryInternal(long bytes) { } @Override - public void bindMemoryConsumer(MemoryConsumer memoryConsumer) { + public void bindMemoryConsumer(OffHeapObject offHeapObject) { // default do nothing } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index ff89043a35..905defc933 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -17,9 +17,9 @@ package org.apache.hugegraph.memory.pool; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.impl.MemoryPoolStats; -import org.apache.hugegraph.memory.util.QueryOutOfMemoryException; +import org.apache.hugegraph.memory.util.OutOfMemoryException; import org.jetbrains.annotations.TestOnly; public interface MemoryPool { @@ -30,7 +30,7 @@ public interface MemoryPool { Object requireMemory(long bytes); - long requestMemoryInternal(long bytes) throws QueryOutOfMemoryException; + long requestMemoryInternal(long bytes) throws OutOfMemoryException; Object tryToAcquireMemoryInternal(long bytes); @@ -67,7 +67,7 @@ public interface MemoryPool { MemoryPool addChildPool(); - void bindMemoryConsumer(MemoryConsumer memoryConsumer); + void bindMemoryConsumer(OffHeapObject offHeapObject); void setMaxCapacityBytes(long maxCapacityBytes); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index f3279b7b62..bca7312320 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -22,11 +22,11 @@ import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.allocator.MemoryAllocator; -import org.apache.hugegraph.memory.consumer.MemoryConsumer; +import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; import org.apache.hugegraph.memory.pool.MemoryPool; -import org.apache.hugegraph.memory.util.MemoryManageUtils; -import org.apache.hugegraph.memory.util.QueryOutOfMemoryException; +import org.apache.hugegraph.memory.util.OutOfMemoryException; +import org.apache.hugegraph.memory.util.RoundUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,13 +34,13 @@ public class OperatorMemoryPool extends AbstractMemoryPool { private static final Logger LOG = LoggerFactory.getLogger(OperatorMemoryPool.class); private final MemoryAllocator memoryAllocator; - private final Set memoryConsumers; + private final Set offHeapObjects; public OperatorMemoryPool(MemoryPool parent, String poolName, MemoryAllocator memoryAllocator, MemoryManager memoryManager) { super(parent, poolName, memoryManager); this.memoryAllocator = memoryAllocator; - this.memoryConsumers = new HashSet<>(); + this.offHeapObjects = new HashSet<>(); } @Override @@ -49,8 +49,8 @@ public MemoryPool addChildPool() { } @Override - public void bindMemoryConsumer(MemoryConsumer memoryConsumer) { - this.memoryConsumers.add(memoryConsumer); + public void bindMemoryConsumer(OffHeapObject offHeapObject) { + this.offHeapObjects.add(offHeapObject); } @Override @@ -61,10 +61,10 @@ public void releaseSelf(String reason, boolean isTriggeredInternal) { this.memoryAllocator.returnMemoryToManager(getUsedBytes()); this.memoryManager.returnReclaimedTaskMemory(getAllocatedBytes()); // release memory consumer, release byte buffer. - this.memoryConsumers.forEach(memoryConsumer -> { + this.offHeapObjects.forEach(memoryConsumer -> { memoryConsumer.getAllMemoryBlock().forEach(memoryAllocator::releaseMemoryBlock); }); - this.memoryConsumers.clear(); + this.offHeapObjects.clear(); this.resetStats(); } @@ -129,7 +129,7 @@ public Object requireMemory(long bytes) { long ignoredRealAllocatedBytes = requestMemoryInternal(delta); } return tryToAcquireMemoryInternal(bytes); - } catch (QueryOutOfMemoryException e) { + } catch (OutOfMemoryException e) { // Abort this query LOG.warn("[{}] detected an OOM exception when request memory, will ABORT this " + "query and release corresponding memory...", @@ -164,7 +164,7 @@ public Object tryToAcquireMemoryInternal(long size) { * This method will update `allocated` and `expand` stats. */ @Override - public long requestMemoryInternal(long size) throws QueryOutOfMemoryException { + public long requestMemoryInternal(long size) throws OutOfMemoryException { if (this.isClosed) { LOG.warn("[{}] is already closed, will abort this request", this); return 0; @@ -175,7 +175,7 @@ public long requestMemoryInternal(long size) throws QueryOutOfMemoryException { } LOG.info("[{}] requestMemory: request size={}", this, size); // 1. align size - long alignedSize = MemoryManageUtils.sizeAlign(size); + long alignedSize = RoundUtil.sizeAlign(size); // 2. reserve(round) long neededMemorySize = calculateReserveMemoryDelta(alignedSize); // 3. call father @@ -184,9 +184,9 @@ public long requestMemoryInternal(long size) throws QueryOutOfMemoryException { LOG.error("[{}] requestMemory failed because of OOM, request size={}", this, size); this.stats.setNumAborts(this.stats.getNumAborts() + 1); - throw new QueryOutOfMemoryException(String.format("%s requestMemory failed " + - "because of OOM, request " + - "size=%s", this, size)); + throw new OutOfMemoryException(String.format("%s requestMemory failed " + + "because of OOM, request " + + "size=%s", this, size)); } // 4. update stats this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + neededMemorySize); @@ -201,7 +201,7 @@ public long requestMemoryInternal(long size) throws QueryOutOfMemoryException { } private long calculateReserveMemoryDelta(long size) { - return MemoryManageUtils.roundDelta(getAllocatedBytes(), size); + return RoundUtil.roundDelta(getAllocatedBytes(), size); } private void resetStats() { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 9f27cfc28b..9b9270243c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -22,7 +22,7 @@ import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; import org.apache.hugegraph.memory.pool.MemoryPool; -import org.apache.hugegraph.memory.util.MemoryManageUtils; +import org.apache.hugegraph.memory.util.RoundUtil; import org.apache.hugegraph.util.Bytes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -105,9 +105,9 @@ public long requestMemoryInternal(long bytes) { private long tryToExpandSelfCapacity(long size) { LOG.info("[{}] try to expand its capacity: size={}", this, size); - long alignedSize = MemoryManageUtils.sizeAlign(size); + long alignedSize = RoundUtil.sizeAlign(size); long realNeededSize = - MemoryManageUtils.roundDelta(getAllocatedBytes(), alignedSize); + RoundUtil.roundDelta(getAllocatedBytes(), alignedSize); return this.memoryManager.handleRequestFromQueryPool(realNeededSize, EXPAND_SELF); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index d6ddb1d6e6..5d5bab5942 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -23,7 +23,7 @@ import org.apache.hugegraph.memory.allocator.NettyMemoryAllocator; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; import org.apache.hugegraph.memory.pool.MemoryPool; -import org.apache.hugegraph.memory.util.QueryOutOfMemoryException; +import org.apache.hugegraph.memory.util.OutOfMemoryException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,7 +64,7 @@ public Object tryToAcquireMemoryInternal(long bytes) { } @Override - public long requestMemoryInternal(long bytes) throws QueryOutOfMemoryException { + public long requestMemoryInternal(long bytes) throws OutOfMemoryException { if (this.isClosed) { LOG.warn("[{}] is already closed, will abort this request", this); return 0; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/FurySerializationUtils.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/FurySerializationUtil.java similarity index 97% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/FurySerializationUtils.java rename to hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/FurySerializationUtil.java index c8388747da..ff56caad7c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/FurySerializationUtils.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/FurySerializationUtil.java @@ -22,7 +22,7 @@ import org.apache.fury.Fury; import org.apache.fury.config.Language; -public class FurySerializationUtils { +public class FurySerializationUtil { public static final Fury FURY = Fury.builder().withLanguage(Language.JAVA) // not mandatory to register all class diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryAccess.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryUtil.java similarity index 98% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryAccess.java rename to hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryUtil.java index 345716243b..a63ddc91b7 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryAccess.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OffHeapMemoryUtil.java @@ -26,9 +26,9 @@ import sun.misc.Unsafe; // NOTE: due to different layout of klass in various versions of JDK, this class may easily crash! -public class OffHeapMemoryAccess { +public class OffHeapMemoryUtil { - private static final Logger LOG = LoggerFactory.getLogger(OffHeapMemoryAccess.class); + private static final Logger LOG = LoggerFactory.getLogger(OffHeapMemoryUtil.class); private static final Unsafe UNSAFE; static { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/QueryOutOfMemoryException.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OutOfMemoryException.java similarity index 66% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/QueryOutOfMemoryException.java rename to hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OutOfMemoryException.java index 0accda9168..c770752626 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/QueryOutOfMemoryException.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/OutOfMemoryException.java @@ -16,18 +16,23 @@ */ package org.apache.hugegraph.memory.util; -public class QueryOutOfMemoryException extends Exception { +import org.apache.hugegraph.HugeException; - public QueryOutOfMemoryException(String message) { +public class OutOfMemoryException extends HugeException { + + public OutOfMemoryException(String message) { super(message); } - public QueryOutOfMemoryException(String message, Throwable cause) { + public OutOfMemoryException(String message, Throwable cause) { super(message, cause); } - public QueryOutOfMemoryException(Exception e) { - super(e); + public OutOfMemoryException(String message, Object... args) { + super(String.format(message, args)); } + public OutOfMemoryException(String message, Throwable cause, Object... args) { + super(String.format(message, args), cause); + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryManageUtils.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/RoundUtil.java similarity index 98% rename from hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryManageUtils.java rename to hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/RoundUtil.java index bf5b79a6a9..b81cd42849 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/MemoryManageUtils.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/RoundUtil.java @@ -16,7 +16,7 @@ */ package org.apache.hugegraph.memory.util; -public class MemoryManageUtils { +public class RoundUtil { // TODO: configurable private static final long ALIGNMENT = 8; diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryAllocateTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryAllocateTest.java index 520e19af6b..1c8df5bba2 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryAllocateTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryAllocateTest.java @@ -22,7 +22,7 @@ import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.allocator.MemoryAllocator; import org.apache.hugegraph.memory.allocator.NettyMemoryAllocator; -import org.apache.hugegraph.memory.allocator.OnHeapMemoryStrategy; +import org.apache.hugegraph.memory.allocator.OnHeapMemoryAllocator; import org.apache.hugegraph.util.Bytes; import org.junit.Assert; import org.junit.Before; @@ -48,7 +48,7 @@ public void setup() { @BeforeClass public static void beforeClass() { nettyAllocator = new NettyMemoryAllocator(MemoryManager.getInstance()); - onHeapAllocator = new OnHeapMemoryStrategy(MemoryManager.getInstance()); + onHeapAllocator = new OnHeapMemoryAllocator(MemoryManager.getInstance()); memoryManager = MemoryManager.getInstance(); } diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java index ed946d12e0..53497ab1aa 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java @@ -17,6 +17,11 @@ package org.apache.hugegraph.core.memory; +import org.junit.Test; + public class MemoryConsumerTest extends MemoryManageTest { + @Test + public void test() { + } } From de9d7a19551fe94f8d891360e89c887106e384c5 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 00:53:14 +0800 Subject: [PATCH 30/48] wip: adoption to query chain & introduce factory --- .../hugegraph/memory/MemoryManager.java | 45 ++++++++++- .../memory/consumer/factory/IdFactory.java | 22 ++++++ .../consumer/factory/PropertyFactory.java | 65 ++++++++++++++++ .../memory/pool/AbstractMemoryPool.java | 4 +- .../hugegraph/memory/pool/MemoryPool.java | 2 +- .../memory/pool/impl/MemoryPoolStats.java | 49 ++++++++++-- .../memory/pool/impl/OperatorMemoryPool.java | 4 +- .../memory/pool/impl/QueryMemoryPool.java | 8 +- .../memory/pool/impl/TaskMemoryPool.java | 17 +++- .../core/memory/MemoryConsumerTest.java | 77 ++++++++++++++++++- .../core/memory/MemoryManageTest.java | 22 +++--- 11 files changed, 281 insertions(+), 34 deletions(-) create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java create mode 100644 hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index 75e09b600c..cb456bb483 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -32,6 +32,7 @@ import org.apache.hugegraph.memory.arbitrator.MemoryArbitratorImpl; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.pool.impl.QueryMemoryPool; +import org.apache.hugegraph.memory.pool.impl.TaskMemoryPool; import org.apache.hugegraph.util.Bytes; import org.apache.hugegraph.util.ExecutorUtil; import org.jetbrains.annotations.TestOnly; @@ -41,7 +42,7 @@ public class MemoryManager { private static final Logger LOG = LoggerFactory.getLogger(MemoryManager.class); - private static final int ARBITRATE_MEMORY_THREAD_NUM = 12; + private static final int ARBITRATE_MEMORY_THREAD_NUM = 1; private static final String QUERY_MEMORY_POOL_NAME_PREFIX = "QueryMemoryPool"; private static final String ARBITRATE_MEMORY_POOL_NAME = "ArbitrateMemoryPool"; public static final String DELIMINATOR = "_"; @@ -56,13 +57,16 @@ public class MemoryManager { private final Queue queryMemoryPools = new PriorityQueue<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); - private final Map threadName2TaskMemoryPoolMap = new ConcurrentHashMap<>(); + private final Map threadName2TaskMemoryPoolMap = new ConcurrentHashMap<>(); private final MemoryArbitrator memoryArbitrator; private final ExecutorService arbitrateExecutor; + private MemoryMode memoryMode; + private MemoryManager() { this.memoryArbitrator = new MemoryArbitratorImpl(this); + // There should be only at most one arbitration task in any time. this.arbitrateExecutor = ExecutorUtil.newFixedThreadPool(ARBITRATE_MEMORY_THREAD_NUM, ARBITRATE_MEMORY_POOL_NAME); } @@ -144,7 +148,7 @@ public MemoryPool getCorrespondingTaskMemoryPool(String threadName) { return threadName2TaskMemoryPoolMap.getOrDefault(threadName, null); } - public void bindCorrespondingTaskMemoryPool(String threadName, MemoryPool memoryPool) { + public void bindCorrespondingTaskMemoryPool(String threadName, TaskMemoryPool memoryPool) { threadName2TaskMemoryPoolMap.computeIfAbsent(threadName, key -> memoryPool); } @@ -164,6 +168,15 @@ public AtomicLong getCurrentOffHeapAllocatedMemoryInBytes() { return currentOffHeapAllocatedMemoryInBytes; } + // TODO: read it from conf + public void setMemoryMode(MemoryMode conf) { + memoryMode = conf; + } + + public MemoryMode getMemoryMode() { + return memoryMode; + } + @TestOnly public AtomicLong getCurrentAvailableMemoryInBytes() { return currentAvailableMemoryInBytes; @@ -181,4 +194,30 @@ private MemoryManagerHolder() { public static MemoryManager getInstance() { return MemoryManagerHolder.INSTANCE; } + + public enum MemoryMode { + ENABLE_OFF_HEAP_MANAGEMENT("off-heap"), + ENABLE_ON_HEAP_MANAGEMENT("on-heap"), + DISABLE_MEMORY_MANAGEMENT("disable"); + + private final String value; + + MemoryMode(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static MemoryMode fromValue(String value) { + if (value.equalsIgnoreCase(ENABLE_ON_HEAP_MANAGEMENT.getValue())) { + return ENABLE_ON_HEAP_MANAGEMENT; + } else if (value.equalsIgnoreCase(ENABLE_OFF_HEAP_MANAGEMENT.getValue())) { + return ENABLE_OFF_HEAP_MANAGEMENT; + } + // return DISABLE by default + return DISABLE_MEMORY_MANAGEMENT; + } + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java new file mode 100644 index 0000000000..d2f96e22d0 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java @@ -0,0 +1,22 @@ +/* + * 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.hugegraph.memory.consumer.factory; + +public class IdFactory { + +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java new file mode 100644 index 0000000000..4ea023d3d5 --- /dev/null +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java @@ -0,0 +1,65 @@ +/* + * 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.hugegraph.memory.consumer.factory; + +import org.apache.hugegraph.memory.MemoryManager; +import org.apache.hugegraph.memory.consumer.impl.property.HugeEdgePropertyOffHeap; +import org.apache.hugegraph.memory.pool.impl.TaskMemoryPool; +import org.apache.hugegraph.schema.PropertyKey; +import org.apache.hugegraph.structure.HugeEdgeProperty; +import org.apache.hugegraph.structure.HugeElement; + +public class PropertyFactory { + + private MemoryManager.MemoryMode memoryMode; + + public HugeEdgeProperty newHugeEdgeProperty(HugeElement owner, PropertyKey key, + V value) { + switch (memoryMode) { + + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new HugeEdgePropertyOffHeap<>( + taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), owner, key, value); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new HugeEdgeProperty<>(owner, key, value); + } + } + + public void setMemoryMode(MemoryManager.MemoryMode memoryMode) { + this.memoryMode = memoryMode; + } + + private static class PropertyFactoryHolder { + + private static final PropertyFactory INSTANCE = new PropertyFactory<>(); + + private PropertyFactoryHolder() { + // empty constructor + } + } + + public static PropertyFactory getInstance() { + return PropertyFactory.PropertyFactoryHolder.INSTANCE; + } +} diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index c7498b3572..8c7511aca1 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -46,9 +46,9 @@ public abstract class AbstractMemoryPool implements MemoryPool { private MemoryPool parent; public AbstractMemoryPool(MemoryPool parent, String memoryPoolName, - MemoryManager memoryManager) { + MemoryPoolStats.MemoryPoolType type, MemoryManager memoryManager) { this.parent = parent; - this.stats = new MemoryPoolStats(memoryPoolName); + this.stats = new MemoryPoolStats(memoryPoolName, type); this.memoryManager = memoryManager; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index 905defc933..38842f9e06 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -65,7 +65,7 @@ public interface MemoryPool { MemoryPool findRootQueryPool(); - MemoryPool addChildPool(); + MemoryPool addChildPool(String name); void bindMemoryConsumer(OffHeapObject offHeapObject); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java index 045499f4d2..0409a05a65 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/MemoryPoolStats.java @@ -20,6 +20,7 @@ public class MemoryPoolStats { private final String memoryPoolName; + private final MemoryPoolType memoryPoolType; private long maxCapacity; private long usedBytes; // it represents the cumulative used bytes. @@ -33,18 +34,35 @@ public class MemoryPoolStats { private long numExpands; private long numAborts; - public MemoryPoolStats(String MemoryPoolName) { + public MemoryPoolStats(String MemoryPoolName, MemoryPoolType memoryPoolType) { this.memoryPoolName = MemoryPoolName; + this.memoryPoolType = memoryPoolType; } @Override public String toString() { - return String.format("MemoryPool-%s: {maxCapacity[%d], usedBytes[%d]," + - "cumulativeBytes[%d], allocatedBytes[%d], numShrinks[%d], " + - "numExpands[%d], numAborts[%d]}.", memoryPoolName, maxCapacity, - usedBytes, - cumulativeBytes, allocatedBytes, numShrinks, numExpands, - numAborts); + switch (memoryPoolType) { + case TASK: + return String.format("%s: {usedBytes[%d], cumulativeBytes[%d], " + + "allocatedBytes[%d], numShrinks[%d], numAborts[%d]}.", + memoryPoolName, usedBytes, cumulativeBytes, allocatedBytes, + numShrinks, numAborts); + case OPERATOR: + return String.format("%s: {usedBytes[%d], cumulativeBytes[%d], " + + "allocatedBytes[%d], numShrinks[%d], numExpands[%d], " + + "numAborts[%d]}.", + memoryPoolName, usedBytes, cumulativeBytes, allocatedBytes, + numShrinks, numExpands, numAborts); + case QUERY: + default: + return String.format("%s: {maxCapacity[%d], usedBytes[%d]," + + "cumulativeBytes[%d], allocatedBytes[%d], numShrinks[%d], " + + "numExpands[%d], numAborts[%d]}.", memoryPoolName, maxCapacity, + usedBytes, + cumulativeBytes, allocatedBytes, numShrinks, numExpands, + numAborts); + } + } public String getMemoryPoolName() { @@ -106,4 +124,21 @@ public long getMaxCapacity() { public void setMaxCapacity(long maxCapacity) { this.maxCapacity = maxCapacity; } + + public enum MemoryPoolType { + QUERY(0), + TASK(1), + OPERATOR(2), + UNKNOWN(3); + + private final int code; + + MemoryPoolType(int code) { + this.code = code; + } + + public int getCode() { + return this.code; + } + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index bca7312320..b9b167ea1d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -38,13 +38,13 @@ public class OperatorMemoryPool extends AbstractMemoryPool { public OperatorMemoryPool(MemoryPool parent, String poolName, MemoryAllocator memoryAllocator, MemoryManager memoryManager) { - super(parent, poolName, memoryManager); + super(parent, poolName, MemoryPoolStats.MemoryPoolType.OPERATOR, memoryManager); this.memoryAllocator = memoryAllocator; this.offHeapObjects = new HashSet<>(); } @Override - public MemoryPool addChildPool() { + public MemoryPool addChildPool(String name) { throw new UnsupportedOperationException(); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 9b9270243c..a8ac429dcb 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -37,16 +37,16 @@ public class QueryMemoryPool extends AbstractMemoryPool { private static final long QUERY_POOL_MAX_CAPACITY = Bytes.MB * 100; public QueryMemoryPool(String poolName, MemoryManager memoryManager) { - super(null, poolName, memoryManager); + super(null, poolName, MemoryPoolStats.MemoryPoolType.QUERY, memoryManager); this.stats.setMaxCapacity(QUERY_POOL_MAX_CAPACITY); } @Override - public MemoryPool addChildPool() { + public MemoryPool addChildPool(String name) { int count = this.children.size(); String poolName = - TASK_MEMORY_POOL_NAME_PREFIX + DELIMINATOR + count + DELIMINATOR + - System.currentTimeMillis(); + TASK_MEMORY_POOL_NAME_PREFIX + DELIMINATOR + name + DELIMINATOR + count + + DELIMINATOR + System.currentTimeMillis(); MemoryPool taskMemoryPool = new TaskMemoryPool(this, poolName, this.memoryManager); this.children.add(taskMemoryPool); LOG.info("QueryPool-{} added task memory pool {}", this, taskMemoryPool); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index 5d5bab5942..0a00c333a0 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -31,9 +31,17 @@ public class TaskMemoryPool extends AbstractMemoryPool { private static final Logger LOG = LoggerFactory.getLogger(TaskMemoryPool.class); private static final String OPERATOR_MEMORY_POOL_NAME_PREFIX = "OperatorMemoryPool"; + // One thread corresponds to one task memory pool. Since the execution flow within a single + // thread is serial, there is only one working Operator pool in the thread at each time. + // This variable helps the execution flow obtain the memory management context. + private MemoryPool CURRENT_WORKING_OPERATOR_MEMORY_POOL = null; public TaskMemoryPool(MemoryPool parent, String poolName, MemoryManager memoryManager) { - super(parent, poolName, memoryManager); + super(parent, poolName, MemoryPoolStats.MemoryPoolType.TASK, memoryManager); + } + + public MemoryPool getCurrentWorkingOperatorMemoryPool() { + return CURRENT_WORKING_OPERATOR_MEMORY_POOL; } @Override @@ -43,16 +51,17 @@ public void releaseSelf(String reason, boolean isTriggeredInternal) { } @Override - public MemoryPool addChildPool() { + public MemoryPool addChildPool(String name) { int count = this.children.size(); String poolName = - OPERATOR_MEMORY_POOL_NAME_PREFIX + DELIMINATOR + count + DELIMINATOR + - System.currentTimeMillis(); + OPERATOR_MEMORY_POOL_NAME_PREFIX + DELIMINATOR + name + DELIMINATOR + count + + DELIMINATOR + System.currentTimeMillis(); MemoryPool operatorPool = new OperatorMemoryPool(this, poolName, new NettyMemoryAllocator(this.memoryManager), this.memoryManager); this.children.add(operatorPool); + CURRENT_WORKING_OPERATOR_MEMORY_POOL = operatorPool; LOG.info("TaskPool-{} added operator memory pool {}", this, operatorPool); return operatorPool; } diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java index 53497ab1aa..6ff53b88db 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java @@ -17,11 +17,86 @@ package org.apache.hugegraph.core.memory; +import java.nio.file.Paths; + +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.ex.ConfigurationException; +import org.apache.commons.configuration2.io.FileHandler; +import org.apache.hugegraph.HugeGraph; +import org.apache.hugegraph.StandardHugeGraph; +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.config.HugeConfig; +import org.apache.hugegraph.dist.RegisterUtil; +import org.apache.hugegraph.masterelection.GlobalMasterInfo; +import org.apache.hugegraph.memory.consumer.impl.id.StringIdOffHeap; +import org.apache.hugegraph.schema.SchemaManager; +import org.apache.hugegraph.structure.HugeVertex; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; public class MemoryConsumerTest extends MemoryManageTest { + private static HugeGraph graph; + private static boolean registered = false; + + public static HugeGraph buildGraph() throws ConfigurationException { + String projectRoot = Paths.get("").toAbsolutePath().getParent().getParent().toString(); + String CONF = projectRoot + "/hugegraph-commons/hugegraph-common/src/test/java/org/apache" + + "/hugegraph/unit/config/test.conf"; + PropertiesConfiguration configuration = new PropertiesConfiguration(); + FileHandler fileHandler = new FileHandler(configuration); + fileHandler.load(CONF); + HugeConfig config = new HugeConfig(configuration); + return new StandardHugeGraph(config); + } + + @BeforeClass + public static void setup() throws ConfigurationException { + graph = buildGraph(); + graph.clearBackend(); + graph.initBackend(); + graph.serverStarted(GlobalMasterInfo.master("server-test")); + if (registered) { + return; + } + RegisterUtil.registerBackends(); + registered = true; + + SchemaManager schema = graph.schema(); + schema.propertyKey("name").asText().create(); + schema.vertexLabel("book") + .properties("name") + .primaryKeys("name") + .enableLabelIndex(false) + .create(); + } + + @AfterClass + public static void clear() throws Exception { + if (graph == null) { + return; + } + + try { + graph.clearBackend(); + } finally { + graph.close(); + graph = null; + } + } + @Test - public void test() { + public void testId() { + Id stringIdOffHeap = new StringIdOffHeap(query1Task1Operator1MemoryPool, "java"); + HugeVertex java = new HugeVertex(graph, stringIdOffHeap, graph.vertexLabel("book")); + Id edgeLableId = new StringIdOffHeap(query1Task1Operator1MemoryPool, "testEdgeLabel"); + Id subLableId = new StringIdOffHeap(query1Task1Operator1MemoryPool, "testSubLabel"); + // Id id = new EdgeIdOffHeap(java, Directions.OUT, edgeLableId, subLableId, "test", java); + } + + @Test + public void testProperty() { + } } diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java index 3f1e770df8..c8f246055e 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java @@ -19,6 +19,7 @@ import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.MemoryPool; +import org.apache.hugegraph.memory.pool.impl.TaskMemoryPool; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.util.Bytes; import org.junit.After; @@ -68,24 +69,25 @@ public class MemoryManageTest { @Before public void setUp() { memoryManager = MemoryManager.getInstance(); + memoryManager.setMemoryMode(MemoryManager.MemoryMode.ENABLE_OFF_HEAP_MANAGEMENT); query1MemoryPool = memoryManager.addQueryMemoryPool(); query2MemoryPool = memoryManager.addQueryMemoryPool(); - query1Task1MemoryPool = query1MemoryPool.addChildPool(); + query1Task1MemoryPool = query1MemoryPool.addChildPool("Task1"); memoryManager.bindCorrespondingTaskMemoryPool(QUERY1_TASK1_THREAD_NAME, - query1Task1MemoryPool); - query1Task1Operator1MemoryPool = query1Task1MemoryPool.addChildPool(); - query1Task1Operator2MemoryPool = query1Task1MemoryPool.addChildPool(); + (TaskMemoryPool) query1Task1MemoryPool); + query1Task1Operator1MemoryPool = query1Task1MemoryPool.addChildPool("Operator1"); + query1Task1Operator2MemoryPool = query1Task1MemoryPool.addChildPool("Operator2"); - query1Task2MemoryPool = query1MemoryPool.addChildPool(); + query1Task2MemoryPool = query1MemoryPool.addChildPool("Task2"); memoryManager.bindCorrespondingTaskMemoryPool(QUERY1_TASK2_THREAD_NAME, - query1Task2MemoryPool); - query1Task2Operator1MemoryPool = query1Task2MemoryPool.addChildPool(); + (TaskMemoryPool) query1Task2MemoryPool); + query1Task2Operator1MemoryPool = query1Task2MemoryPool.addChildPool("Operator1"); - query2Task1MemoryPool = query2MemoryPool.addChildPool(); + query2Task1MemoryPool = query2MemoryPool.addChildPool("Task1"); memoryManager.bindCorrespondingTaskMemoryPool(QUERY2_TASK1_THREAD_NAME, - query2Task1MemoryPool); - query2Task1Operator1MemoryPool = query2Task1MemoryPool.addChildPool(); + (TaskMemoryPool) query2Task1MemoryPool); + query2Task1Operator1MemoryPool = query2Task1MemoryPool.addChildPool("Operator1"); } @After From 46066eb608ffce40db9f334b6cdae8650c144b9f Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 10:33:08 +0800 Subject: [PATCH 31/48] fix concurrent bug when local arbitrate --- .../hugegraph/memory/MemoryManager.java | 8 +-- .../memory/arbitrator/MemoryArbitrator.java | 2 +- .../arbitrator/MemoryArbitratorImpl.java | 6 +- .../consumer/impl/id/BinaryIdOffHeap.java | 2 +- .../consumer/impl/id/EdgeIdOffHeap.java | 4 +- .../consumer/impl/id/LongIdOffHeap.java | 2 +- .../consumer/impl/id/ObjectIdOffHeap.java | 2 +- .../consumer/impl/id/QueryIdOffHeap.java | 2 +- .../consumer/impl/id/StringIdOffHeap.java | 2 +- .../consumer/impl/id/UuidIdOffHeap.java | 2 +- .../property/HugeEdgePropertyOffHeap.java | 2 +- .../property/HugeVertexPropertyOffHeap.java | 2 +- .../memory/pool/AbstractMemoryPool.java | 68 ++++++++++++------- .../hugegraph/memory/pool/MemoryPool.java | 6 +- .../memory/pool/impl/OperatorMemoryPool.java | 24 ++++--- .../memory/pool/impl/QueryMemoryPool.java | 25 +++++-- .../memory/pool/impl/TaskMemoryPool.java | 17 ++++- .../core/memory/MemoryManageTest.java | 38 +++++++---- 18 files changed, 140 insertions(+), 74 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index cb456bb483..3499ab165a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -42,7 +42,7 @@ public class MemoryManager { private static final Logger LOG = LoggerFactory.getLogger(MemoryManager.class); - private static final int ARBITRATE_MEMORY_THREAD_NUM = 1; + private static final int ARBITRATE_MEMORY_THREAD_NUM = 12; private static final String QUERY_MEMORY_POOL_NAME_PREFIX = "QueryMemoryPool"; private static final String ARBITRATE_MEMORY_POOL_NAME = "ArbitrateMemoryPool"; public static final String DELIMINATOR = "_"; @@ -66,7 +66,6 @@ public class MemoryManager { private MemoryManager() { this.memoryArbitrator = new MemoryArbitratorImpl(this); - // There should be only at most one arbitration task in any time. this.arbitrateExecutor = ExecutorUtil.newFixedThreadPool(ARBITRATE_MEMORY_THREAD_NUM, ARBITRATE_MEMORY_POOL_NAME); } @@ -96,11 +95,12 @@ public void consumeAvailableMemory(long size) { currentAvailableMemoryInBytes.addAndGet(-size); } - public long triggerLocalArbitration(MemoryPool targetPool, long neededBytes) { + public long triggerLocalArbitration(MemoryPool targetPool, long neededBytes, + MemoryPool requestPool) { LOG.info("LocalArbitration triggered by {}: needed bytes={}", targetPool, neededBytes); Future future = arbitrateExecutor.submit( - () -> memoryArbitrator.reclaimLocally(targetPool, neededBytes)); + () -> memoryArbitrator.reclaimLocally(targetPool, neededBytes, requestPool)); try { return future.get(MemoryArbitrator.MAX_WAIT_TIME_FOR_LOCAL_RECLAIM, TimeUnit.MILLISECONDS); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java index e93ed0a414..4cb2fe55a6 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitrator.java @@ -25,7 +25,7 @@ public interface MemoryArbitrator { long MAX_WAIT_TIME_FOR_GLOBAL_RECLAIM = 5000; - long reclaimLocally(MemoryPool queryPool, long neededBytes); + long reclaimLocally(MemoryPool queryPool, long neededBytes, MemoryPool requestingPool); long reclaimGlobally(MemoryPool queryPool, long neededBytes); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java index 67e33a5a8b..e5198c3638 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java @@ -34,9 +34,9 @@ public MemoryArbitratorImpl(MemoryManager memoryManager) { } @Override - public long reclaimLocally(MemoryPool queryPool, long neededBytes) { + public long reclaimLocally(MemoryPool queryPool, long neededBytes, MemoryPool requestingPool) { long startTime = System.currentTimeMillis(); - long res = queryPool.tryToReclaimLocalMemory(neededBytes); + long res = queryPool.tryToReclaimLocalMemory(neededBytes, requestingPool); LOG.info("[{}] reclaim local memory: {} bytes, took {} ms", Thread.currentThread().getName(), res, @@ -57,7 +57,7 @@ public long reclaimGlobally(MemoryPool queryPool, long neededBytes) { } LOG.info("Global reclaim triggerred by {} select {} to reclaim", queryPool, memoryPool); - long res = memoryPool.tryToReclaimLocalMemory(currentNeededBytes); + long res = memoryPool.tryToReclaimLocalMemory(currentNeededBytes, queryPool); totalReclaimedBytes += res; currentNeededBytes -= res; if (currentNeededBytes <= 0) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java index 830003b16b..3d78be8058 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java @@ -44,7 +44,7 @@ public BinaryIdOffHeap(byte[] bytes, Id id, MemoryPool memoryPool, OffHeapObject @Override public void serializeSelfToByteBuf(MemoryPool memoryPool) { - this.bytesOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); + this.bytesOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length, memoryPool); this.bytesOffHeap.markReaderIndex(); this.bytesOffHeap.writeBytes(bytes); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java index a1467e8640..9f7811c679 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java @@ -128,7 +128,7 @@ public Object zeroCopyReadFromByteBuf() { @Override public void serializeSelfToByteBuf(MemoryPool memoryPool) { byte[] stringBytes = sortValues.getBytes((StandardCharsets.UTF_8)); - this.sortValuesOffHeap = (ByteBuf) this.memoryPool.requireMemory(stringBytes.length); + this.sortValuesOffHeap = (ByteBuf) this.memoryPool.requireMemory(stringBytes.length, memoryPool); this.sortValuesOffHeap.markReaderIndex(); this.sortValuesOffHeap.writeBytes(stringBytes); } @@ -231,7 +231,7 @@ public String asString() { IdUtil.writeString((Id) this.otherVertexIdOffHeap.zeroCopyReadFromByteBuf())); } byte[] tmpCacheBytes = tmpCache.getBytes(StandardCharsets.UTF_8); - this.cacheOffHeap = (ByteBuf) memoryPool.requireMemory(tmpCacheBytes.length); + this.cacheOffHeap = (ByteBuf) memoryPool.requireMemory(tmpCacheBytes.length, memoryPool); this.cacheOffHeap.markReaderIndex(); this.cacheOffHeap.writeBytes(tmpCacheBytes); return tmpCache; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java index 9ebb01140e..9e2ae9729e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java @@ -58,7 +58,7 @@ public Object zeroCopyReadFromByteBuf() { @Override public void serializeSelfToByteBuf(MemoryPool memoryPool) { - this.idOffHeap = (ByteBuf) memoryPool.requireMemory(Long.BYTES); + this.idOffHeap = (ByteBuf) memoryPool.requireMemory(Long.BYTES, memoryPool); this.idOffHeap.markReaderIndex(); this.idOffHeap.writeLong(id); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java index b1bcba67a7..72938e5117 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java @@ -48,7 +48,7 @@ public Object zeroCopyReadFromByteBuf() { @Override public void serializeSelfToByteBuf(MemoryPool memoryPool) { byte[] bytes = FurySerializationUtil.FURY.serialize(object); - this.objectOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); + this.objectOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length, memoryPool); this.objectOffHeap.markReaderIndex(); this.objectOffHeap.writeBytes(bytes); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java index 8209468d7f..25a5a74266 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java @@ -54,7 +54,7 @@ public Object zeroCopyReadFromByteBuf() { @Override public void serializeSelfToByteBuf(MemoryPool memoryPool) { byte[] stringBytes = query.getBytes((StandardCharsets.UTF_8)); - this.queryOffHeap = (ByteBuf) memoryPool.requireMemory(stringBytes.length); + this.queryOffHeap = (ByteBuf) memoryPool.requireMemory(stringBytes.length, memoryPool); this.queryOffHeap.markReaderIndex(); this.queryOffHeap.writeBytes(stringBytes); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java index 5862910a76..cb64415a5d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java @@ -59,7 +59,7 @@ public Object zeroCopyReadFromByteBuf() { @Override public void serializeSelfToByteBuf(MemoryPool memoryPool) { byte[] stringBytes = id.getBytes((StandardCharsets.UTF_8)); - this.idOffHeap = (ByteBuf) memoryPool.requireMemory(stringBytes.length); + this.idOffHeap = (ByteBuf) memoryPool.requireMemory(stringBytes.length, memoryPool); this.idOffHeap.markReaderIndex(); this.idOffHeap.writeBytes(stringBytes); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java index db67f92bd9..b54c096c0e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java @@ -70,7 +70,7 @@ public Object zeroCopyReadFromByteBuf() { @Override public void serializeSelfToByteBuf(MemoryPool memoryPool) { byte[] bytes = FurySerializationUtil.FURY.serialize(uuid); - this.idOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); + this.idOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length, memoryPool); this.idOffHeap.markReaderIndex(); this.idOffHeap.writeBytes(bytes); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java index 9c3ae2543d..44b4848f4d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java @@ -53,7 +53,7 @@ public Object zeroCopyReadFromByteBuf() { @Override public void serializeSelfToByteBuf(MemoryPool memoryPool) { byte[] bytes = FurySerializationUtil.FURY.serialize(this.value); - this.valueOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); + this.valueOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length, memoryPool); this.valueOffHeap.markReaderIndex(); this.valueOffHeap.writeBytes(bytes); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java index 8afed48a77..60e426a1d8 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java @@ -52,7 +52,7 @@ public Object zeroCopyReadFromByteBuf() { @Override public void serializeSelfToByteBuf(MemoryPool memoryPool) { byte[] bytes = FurySerializationUtil.FURY.serialize(this.value); - this.valueOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length); + this.valueOffHeap = (ByteBuf) memoryPool.requireMemory(bytes.length, memoryPool); this.valueOffHeap.markReaderIndex(); this.valueOffHeap.writeBytes(bytes); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 8c7511aca1..172ac8d50a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -52,33 +52,27 @@ public AbstractMemoryPool(MemoryPool parent, String memoryPoolName, this.memoryManager = memoryManager; } - @Override - public long tryToReclaimLocalMemory(long neededBytes) { - if (isClosed) { - LOG.warn("[{}] is already closed, will abort this reclaim", this); - return 0; - } - LOG.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); + protected long tryToReclaimLocalMemoryWithoutLock(long neededBytes, MemoryPool requestingPool) { long totalReclaimedBytes = 0; - long currentNeededBytes = neededBytes; try { - this.memoryActionLock.lock(); - this.isBeingArbitrated.set(true); - for (MemoryPool child : this.children) { - long reclaimedMemory = child.tryToReclaimLocalMemory(currentNeededBytes); - if (reclaimedMemory > 0) { - currentNeededBytes -= reclaimedMemory; - totalReclaimedBytes += reclaimedMemory; - // Reclaim enough memory. - if (currentNeededBytes <= 0) { - break; - } - } + totalReclaimedBytes = reclaimChildren(neededBytes, requestingPool); + return totalReclaimedBytes; + } finally { + if (totalReclaimedBytes > 0) { + this.stats.setNumShrinks(this.stats.getNumShrinks() + 1); } - LOG.info("[{}] has finished to reclaim memory: totalReclaimedBytes={}, " + - "neededBytes={}", - this, - totalReclaimedBytes, neededBytes); + this.stats.setAllocatedBytes( + this.stats.getAllocatedBytes() - totalReclaimedBytes); + this.isBeingArbitrated.set(false); + } + } + + @Override + public long tryToReclaimLocalMemory(long neededBytes, MemoryPool requestingPool) { + this.memoryActionLock.lock(); + long totalReclaimedBytes = 0; + try { + totalReclaimedBytes = reclaimChildren(neededBytes, requestingPool); return totalReclaimedBytes; } finally { if (totalReclaimedBytes > 0) { @@ -92,6 +86,30 @@ public long tryToReclaimLocalMemory(long neededBytes) { } } + private long reclaimChildren(long neededBytes, MemoryPool requestingPool) { + LOG.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); + this.isBeingArbitrated.set(true); + long totalReclaimedBytes = 0; + long currentNeededBytes = neededBytes; + for (MemoryPool child : this.children) { + long reclaimedMemory = + child.tryToReclaimLocalMemory(currentNeededBytes, requestingPool); + if (reclaimedMemory > 0) { + currentNeededBytes -= reclaimedMemory; + totalReclaimedBytes += reclaimedMemory; + // Reclaim enough memory. + if (currentNeededBytes <= 0) { + break; + } + } + } + LOG.info("[{}] has finished to reclaim memory: totalReclaimedBytes={}, " + + "neededBytes={}", + this, + totalReclaimedBytes, neededBytes); + return totalReclaimedBytes; + } + /** * called when one layer pool is successfully executed and exited. */ @@ -158,7 +176,7 @@ public void bindMemoryConsumer(OffHeapObject offHeapObject) { } @Override - public Object requireMemory(long bytes) { + public Object requireMemory(long bytes, MemoryPool requestingPool) { return null; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index 38842f9e06..8c67cb27be 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -26,11 +26,11 @@ public interface MemoryPool { MemoryPoolStats getSnapShot(); - long tryToReclaimLocalMemory(long neededBytes); + long tryToReclaimLocalMemory(long neededBytes, MemoryPool requestingPool); - Object requireMemory(long bytes); + Object requireMemory(long bytes, MemoryPool requestingPool); - long requestMemoryInternal(long bytes) throws OutOfMemoryException; + long requestMemoryInternal(long bytes, MemoryPool requestingPool) throws OutOfMemoryException; Object tryToAcquireMemoryInternal(long bytes); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index b9b167ea1d..b98635b212 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -69,15 +69,17 @@ public void releaseSelf(String reason, boolean isTriggeredInternal) { } @Override - public long tryToReclaimLocalMemory(long neededBytes) { + public long tryToReclaimLocalMemory(long neededBytes, MemoryPool requestingPool) { if (this.isClosed) { LOG.warn("[{}] is already closed, will abort this reclaim", this); return 0; } - LOG.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); long reclaimableBytes = 0; try { - this.memoryActionLock.lock(); + if (!this.equals(requestingPool)) { + this.memoryActionLock.lock(); + } + LOG.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); this.isBeingArbitrated.set(true); // 1. try to reclaim self free memory reclaimableBytes = getFreeBytes(); @@ -107,8 +109,10 @@ public long tryToReclaimLocalMemory(long neededBytes) { this.stats.setNumShrinks(this.stats.getNumShrinks() + 1); } this.isBeingArbitrated.set(false); - this.condition.signalAll(); - this.memoryActionLock.unlock(); + if (!this.equals(requestingPool)) { + this.condition.signalAll(); + this.memoryActionLock.unlock(); + } } } @@ -116,7 +120,7 @@ public long tryToReclaimLocalMemory(long neededBytes) { * called by user */ @Override - public Object requireMemory(long bytes) { + public Object requireMemory(long bytes, MemoryPool requestingPool) { try { // use lock to ensure the atomicity of the two-step operation this.memoryActionLock.lock(); @@ -126,7 +130,7 @@ public Object requireMemory(long bytes) { } else { // if free memory is not enough, try to request delta long delta = bytes - getFreeBytes(); - long ignoredRealAllocatedBytes = requestMemoryInternal(delta); + long ignoredRealAllocatedBytes = requestMemoryInternal(delta, requestingPool); } return tryToAcquireMemoryInternal(bytes); } catch (OutOfMemoryException e) { @@ -164,7 +168,8 @@ public Object tryToAcquireMemoryInternal(long size) { * This method will update `allocated` and `expand` stats. */ @Override - public long requestMemoryInternal(long size) throws OutOfMemoryException { + public long requestMemoryInternal(long size, MemoryPool requestingPool) throws + OutOfMemoryException { if (this.isClosed) { LOG.warn("[{}] is already closed, will abort this request", this); return 0; @@ -179,7 +184,8 @@ public long requestMemoryInternal(long size) throws OutOfMemoryException { // 2. reserve(round) long neededMemorySize = calculateReserveMemoryDelta(alignedSize); // 3. call father - long fatherRes = getParentPool().requestMemoryInternal(neededMemorySize); + long fatherRes = + getParentPool().requestMemoryInternal(neededMemorySize, requestingPool); if (fatherRes < 0) { LOG.error("[{}] requestMemory failed because of OOM, request size={}", this, size); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index a8ac429dcb..8a036b4430 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -41,6 +41,18 @@ public QueryMemoryPool(String poolName, MemoryManager memoryManager) { this.stats.setMaxCapacity(QUERY_POOL_MAX_CAPACITY); } + @Override + public long tryToReclaimLocalMemory(long neededBytes, MemoryPool requestingPool) { + if (isClosed) { + LOG.warn("[{}] is already closed, will abort this reclaim", this); + return 0; + } + if (this.equals(requestingPool.findRootQueryPool())) { + return super.tryToReclaimLocalMemoryWithoutLock(neededBytes, requestingPool); + } + return super.tryToReclaimLocalMemory(neededBytes, requestingPool); + } + @Override public MemoryPool addChildPool(String name) { int count = this.children.size(); @@ -54,7 +66,7 @@ public MemoryPool addChildPool(String name) { } @Override - public long requestMemoryInternal(long bytes) { + public long requestMemoryInternal(long bytes, MemoryPool requestingPool) { if (this.isClosed) { LOG.warn("[{}] is already closed, will abort this request", this); return 0; @@ -77,14 +89,16 @@ public long requestMemoryInternal(long bytes) { requestedMemoryFromManager = bytes; } else { // 2.2 if requiring memory from manager failed, call manager to invoke arbitrate - requestedMemoryFromArbitration = requestMemoryThroughArbitration(bytes); + requestedMemoryFromArbitration = + requestMemoryThroughArbitration(bytes, requestingPool); } } else { // 3. if capacity is enough, check whether manager has enough memory. if (this.memoryManager.handleRequestFromQueryPool(bytes, REQUEST_MEMORY) < 0) { // 3.1 if memory manager doesn't have enough memory, call manager to invoke // arbitrate - requestedMemoryFromArbitration = requestMemoryThroughArbitration(bytes); + requestedMemoryFromArbitration = + requestMemoryThroughArbitration(bytes, requestingPool); } else { // 3.2 if memory manager has enough memory, return success this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + bytes); @@ -111,10 +125,11 @@ private long tryToExpandSelfCapacity(long size) { return this.memoryManager.handleRequestFromQueryPool(realNeededSize, EXPAND_SELF); } - private long requestMemoryThroughArbitration(long bytes) { + private long requestMemoryThroughArbitration(long bytes, MemoryPool requestingPool) { LOG.info("[{}] try to request memory from manager through arbitration: size={}", this, bytes); - long reclaimedBytes = this.memoryManager.triggerLocalArbitration(this, bytes); + long reclaimedBytes = + this.memoryManager.triggerLocalArbitration(this, bytes, requestingPool); if (reclaimedBytes > 0) { this.stats.setNumExpands(this.stats.getNumExpands() + 1); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index 0a00c333a0..ffc97de0f7 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -44,6 +44,18 @@ public MemoryPool getCurrentWorkingOperatorMemoryPool() { return CURRENT_WORKING_OPERATOR_MEMORY_POOL; } + @Override + public long tryToReclaimLocalMemory(long neededBytes, MemoryPool requestingPool) { + if (isClosed) { + LOG.warn("[{}] is already closed, will abort this reclaim", this); + return 0; + } + if (this.findRootQueryPool().equals(requestingPool.findRootQueryPool())) { + return super.tryToReclaimLocalMemoryWithoutLock(neededBytes, requestingPool); + } + return super.tryToReclaimLocalMemory(neededBytes, requestingPool); + } + @Override public void releaseSelf(String reason, boolean isTriggeredInternal) { super.releaseSelf(reason, isTriggeredInternal); @@ -73,7 +85,8 @@ public Object tryToAcquireMemoryInternal(long bytes) { } @Override - public long requestMemoryInternal(long bytes) throws OutOfMemoryException { + public long requestMemoryInternal(long bytes, MemoryPool requestingPool) throws + OutOfMemoryException { if (this.isClosed) { LOG.warn("[{}] is already closed, will abort this request", this); return 0; @@ -82,7 +95,7 @@ public long requestMemoryInternal(long bytes) throws OutOfMemoryException { if (this.isBeingArbitrated.get()) { this.condition.await(); } - long parentRes = getParentPool().requestMemoryInternal(bytes); + long parentRes = getParentPool().requestMemoryInternal(bytes, requestingPool); if (parentRes > 0) { this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + parentRes); this.stats.setNumExpands(this.stats.getNumExpands() + 1); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java index c8f246055e..fef8e60ff7 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java @@ -119,7 +119,8 @@ public void testMemoryPoolStructure() { @Test public void testRequiringMemory() { long requireBytes = Bytes.KB; - ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes + , query1Task1Operator1MemoryPool); Assert.assertNotNull(memoryBlock); Assert.assertEquals(requireBytes, memoryBlock.capacity()); Assert.assertEquals(requireBytes, @@ -128,7 +129,9 @@ public void testRequiringMemory() { MemoryManager.MAX_MEMORY_CAPACITY_IN_BYTES - query1MemoryPool.getAllocatedBytes(), memoryManager.getCurrentAvailableMemoryInBytes().get()); // will use reserved memory, not requiring memory through manager - ByteBuf memoryBlock2 = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + ByteBuf memoryBlock2 = + (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes, + query1Task1Operator1MemoryPool); Assert.assertNotNull(memoryBlock2); Assert.assertEquals(requireBytes, memoryBlock2.capacity()); Assert.assertEquals(requireBytes * 2, @@ -141,14 +144,16 @@ public void testRequiringMemory() { @Test public void testOOM() { long requireBytes = Bytes.GB * 2; - ByteBuf memoryBlock = (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes); + ByteBuf memoryBlock = (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes + , query2Task1Operator1MemoryPool); Assert.assertNull(memoryBlock); } @Test public void testReleaseMemoryWithTask() { long requireBytes = Bytes.KB; - ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes + , query1Task1Operator1MemoryPool); Assert.assertNotNull(memoryBlock); Assert.assertEquals(requireBytes, memoryBlock.capacity()); memoryManager.getCorrespondingTaskMemoryPool(QUERY1_TASK1_THREAD_NAME) @@ -167,7 +172,8 @@ public void testReleaseMemoryWithTask() { @Test public void testReleaseMemoryWithQuery() { long requireBytes = Bytes.KB; - ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes + , query1Task1Operator1MemoryPool); Assert.assertNotNull(memoryBlock); Assert.assertEquals(requireBytes, memoryBlock.capacity()); query1MemoryPool.releaseSelf("Test release by hand", true); @@ -182,14 +188,16 @@ public void testReleaseMemoryWithQuery() { @Test public void testExpandCapacity() { long requireBytes = Bytes.KB; - ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes + , query1Task1Operator1MemoryPool); Assert.assertNotNull(memoryBlock); Assert.assertEquals(requireBytes, memoryBlock.capacity()); long maxCapacity = Bytes.KB * 100; query2MemoryPool.setMaxCapacityBytes(maxCapacity); long requireBytes2 = maxCapacity * 2; ByteBuf memoryBlock2 = - (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes2); + (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes2, + query2Task1Operator1MemoryPool); Assert.assertNotNull(memoryBlock2); Assert.assertEquals(requireBytes2, memoryBlock2.capacity()); Assert.assertEquals(requireBytes2 + requireBytes, @@ -207,10 +215,12 @@ public void testLocalArbitrationFail() { memoryManager.getCurrentAvailableMemoryInBytes().set(totalMemory); long requireBytes = Bytes.KB; // will allocate 2MB - ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes + , query1Task1Operator1MemoryPool); long requireBytes2 = Bytes.MB; ByteBuf memoryBlock2 = - (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes2); + (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes2, + query1Task1Operator1MemoryPool); Assert.assertEquals(Bytes.MB * 2, query1MemoryPool.getAllocatedBytes()); // query1 remaining 1023KB Assert.assertEquals(Bytes.MB * 2 - requireBytes2 - requireBytes, @@ -219,7 +229,9 @@ public void testLocalArbitrationFail() { Assert.assertEquals(totalMemory - 2 * Bytes.MB, memoryManager.getCurrentAvailableMemoryInBytes().get()); // will try to allocate 1MB and trigger arbitration, which will fail and result in OOM - ByteBuf memoryBlock3 = (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes); + ByteBuf memoryBlock3 = + (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes, + query2Task1Operator1MemoryPool); Assert.assertNull(memoryBlock3); Assert.assertEquals(0, query2MemoryPool.getAllocatedBytes()); } @@ -230,7 +242,8 @@ public void testGlobalArbitration() { memoryManager.getCurrentAvailableMemoryInBytes().set(totalMemory); long requireBytes = Bytes.MB * 17; // will allocate 20MB - ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes); + ByteBuf memoryBlock = (ByteBuf) query1Task1Operator1MemoryPool.requireMemory(requireBytes + , query1Task1Operator1MemoryPool); Assert.assertEquals(Bytes.MB * 20, query1MemoryPool.getAllocatedBytes()); // query1 remaining 3MB Assert.assertEquals(Bytes.MB * 3, @@ -240,7 +253,8 @@ public void testGlobalArbitration() { // will try to allocate 1MB and trigger arbitration, which will success long requireBytes2 = Bytes.KB; ByteBuf memoryBlock2 = - (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes2); + (ByteBuf) query2Task1Operator1MemoryPool.requireMemory(requireBytes2, + query2Task1Operator1MemoryPool); Assert.assertNotNull(memoryBlock2); Assert.assertEquals(Bytes.MB, query2MemoryPool.getAllocatedBytes()); Assert.assertEquals(Bytes.KB, memoryBlock2.capacity()); From 4f1e96653104697704b11f7c72fe2f9db28383a8 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 10:46:17 +0800 Subject: [PATCH 32/48] add comments --- .../java/org/apache/hugegraph/memory/MemoryManager.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index 3499ab165a..d125ef47bb 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -57,7 +57,8 @@ public class MemoryManager { private final Queue queryMemoryPools = new PriorityQueue<>((o1, o2) -> (int) (o2.getFreeBytes() - o1.getFreeBytes())); - private final Map threadName2TaskMemoryPoolMap = new ConcurrentHashMap<>(); + private final Map threadName2TaskMemoryPoolMap = + new ConcurrentHashMap<>(); private final MemoryArbitrator memoryArbitrator; private final ExecutorService arbitrateExecutor; @@ -66,6 +67,9 @@ public class MemoryManager { private MemoryManager() { this.memoryArbitrator = new MemoryArbitratorImpl(this); + // Since there is always only 1 working operator pool for 1 query, It is not possible to + // run local arbitration or global arbitration in parallel within a query. The thread + // pool here is to allow parallel arbitration between queries this.arbitrateExecutor = ExecutorUtil.newFixedThreadPool(ARBITRATE_MEMORY_THREAD_NUM, ARBITRATE_MEMORY_POOL_NAME); } @@ -100,7 +104,8 @@ public long triggerLocalArbitration(MemoryPool targetPool, long neededBytes, LOG.info("LocalArbitration triggered by {}: needed bytes={}", targetPool, neededBytes); Future future = arbitrateExecutor.submit( - () -> memoryArbitrator.reclaimLocally(targetPool, neededBytes, requestPool)); + () -> memoryArbitrator.reclaimLocally(targetPool, neededBytes, + requestPool)); try { return future.get(MemoryArbitrator.MAX_WAIT_TIME_FOR_LOCAL_RECLAIM, TimeUnit.MILLISECONDS); From 231b64796f4ecfbfb9dba61fd2e42d62e5b49759 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 12:50:01 +0800 Subject: [PATCH 33/48] feat: off-heap object factory --- .../memory/consumer/factory/IdFactory.java | 302 ++++++++++++++++++ .../consumer/factory/PropertyFactory.java | 33 +- .../consumer/impl/id/ObjectIdOffHeap.java | 2 +- 3 files changed, 333 insertions(+), 4 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java index d2f96e22d0..c8bbe075ef 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java @@ -17,6 +17,308 @@ package org.apache.hugegraph.memory.consumer.factory; +import java.util.UUID; + +import org.apache.hugegraph.backend.cache.CachedBackendStore; +import org.apache.hugegraph.backend.id.EdgeId; +import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; +import org.apache.hugegraph.memory.MemoryManager; +import org.apache.hugegraph.memory.consumer.OffHeapObject; +import org.apache.hugegraph.memory.consumer.impl.id.BinaryIdOffHeap; +import org.apache.hugegraph.memory.consumer.impl.id.EdgeIdOffHeap; +import org.apache.hugegraph.memory.consumer.impl.id.LongIdOffHeap; +import org.apache.hugegraph.memory.consumer.impl.id.ObjectIdOffHeap; +import org.apache.hugegraph.memory.consumer.impl.id.QueryIdOffHeap; +import org.apache.hugegraph.memory.consumer.impl.id.StringIdOffHeap; +import org.apache.hugegraph.memory.consumer.impl.id.UuidIdOffHeap; +import org.apache.hugegraph.memory.pool.impl.TaskMemoryPool; +import org.apache.hugegraph.structure.HugeVertex; +import org.apache.hugegraph.type.define.Directions; + +// NOTE: current MemoryManager doesn't support on-heap management. public class IdFactory { + private MemoryManager.MemoryMode memoryMode; + + /** + * If using off-heap mode, param id must be OffHeapObject + */ + public BinaryBackendEntry.BinaryId newBinaryId(byte[] bytes, Id id) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new BinaryIdOffHeap(bytes, null, + taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + (OffHeapObject) id); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new BinaryBackendEntry.BinaryId(bytes, id); + } + } + + public IdGenerator.LongId newLongId(long id) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new LongIdOffHeap(taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + id); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new IdGenerator.LongId(id); + } + } + + public IdGenerator.LongId newLongId(byte[] bytes) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new LongIdOffHeap(taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + bytes); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new IdGenerator.LongId(bytes); + } + } + + public IdGenerator.ObjectId newObjectId(Object object) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new ObjectIdOffHeap(taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + object); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new IdGenerator.ObjectId(object); + } + } + + public CachedBackendStore.QueryId newQueryId(Query q) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new QueryIdOffHeap(taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + q); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new CachedBackendStore.QueryId(q); + } + } + + public IdGenerator.StringId newStringId(String id) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new StringIdOffHeap(taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + id); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new IdGenerator.StringId(id); + } + } + + public IdGenerator.StringId newStringId(byte[] bytes) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new StringIdOffHeap(taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + bytes); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new IdGenerator.StringId(bytes); + } + } + + public IdGenerator.UuidId newUuidId(String id) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new UuidIdOffHeap(taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + id); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new IdGenerator.UuidId(id); + } + } + + public IdGenerator.UuidId newUuidId(byte[] bytes) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new UuidIdOffHeap(taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + bytes); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new IdGenerator.UuidId(bytes); + } + } + + public IdGenerator.UuidId newUuidId(UUID id) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new UuidIdOffHeap(taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + id); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new IdGenerator.UuidId(id); + } + } + + public EdgeId newEdgeId(HugeVertex ownerVertex, + Directions direction, + Id edgeLabelId, + Id subLabelId, + String sortValues, + HugeVertex otherVertex) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new EdgeIdOffHeap(ownerVertex, + direction, + null, + null, + sortValues, + otherVertex, + taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + (OffHeapObject) ownerVertex.id(), + (OffHeapObject) edgeLabelId, + (OffHeapObject) subLabelId, + (OffHeapObject) otherVertex.id() + ); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new EdgeId(ownerVertex, direction, edgeLabelId, subLabelId, sortValues, + otherVertex); + } + } + + public EdgeId newEdgeId(Id ownerVertexId, + Directions direction, + Id edgeLabelId, + Id subLabelId, + String sortValues, + Id otherVertexId) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new EdgeIdOffHeap((Id) null, + direction, + null, + null, + sortValues, + null, + taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + (OffHeapObject) ownerVertexId, + (OffHeapObject) edgeLabelId, + (OffHeapObject) subLabelId, + (OffHeapObject) otherVertexId + ); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new EdgeId(ownerVertexId, direction, edgeLabelId, subLabelId, sortValues, + otherVertexId); + } + } + + public EdgeId newEdgeId(Id ownerVertexId, + Directions direction, + Id edgeLabelId, + Id subLabelId, + String sortValues, + Id otherVertexId, + boolean directed) { + switch (memoryMode) { + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new EdgeIdOffHeap(null, + direction, + null, + null, + sortValues, + null, + directed, + taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), + (OffHeapObject) ownerVertexId, + (OffHeapObject) edgeLabelId, + (OffHeapObject) subLabelId, + (OffHeapObject) otherVertexId + ); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new EdgeId(ownerVertexId, direction, edgeLabelId, subLabelId, sortValues, + otherVertexId, directed); + } + } + + public void setMemoryMode(MemoryManager.MemoryMode memoryMode) { + this.memoryMode = memoryMode; + } + + private static class IdFactoryHolder { + + private static final IdFactory INSTANCE = new IdFactory(); + + private IdFactoryHolder() { + // empty constructor + } + } + + public static IdFactory getInstance() { + return IdFactoryHolder.INSTANCE; + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java index 4ea023d3d5..96b915ac18 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java @@ -17,13 +17,19 @@ package org.apache.hugegraph.memory.consumer.factory; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.consumer.impl.property.HugeEdgePropertyOffHeap; +import org.apache.hugegraph.memory.consumer.impl.property.HugeVertexPropertyOffHeap; import org.apache.hugegraph.memory.pool.impl.TaskMemoryPool; import org.apache.hugegraph.schema.PropertyKey; import org.apache.hugegraph.structure.HugeEdgeProperty; import org.apache.hugegraph.structure.HugeElement; +import org.apache.hugegraph.structure.HugeVertexProperty; +// NOTE: current MemoryManager doesn't support on-heap management. public class PropertyFactory { private MemoryManager.MemoryMode memoryMode; @@ -46,20 +52,41 @@ public HugeEdgeProperty newHugeEdgeProperty(HugeElement owner, PropertyKey ke } } + public HugeVertexProperty newHugeVertexProperty(HugeElement owner, PropertyKey key, + V value) { + switch (memoryMode) { + + case ENABLE_ON_HEAP_MANAGEMENT: + case ENABLE_OFF_HEAP_MANAGEMENT: + TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() + .getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + return new HugeVertexPropertyOffHeap<>( + taskMemoryPool.getCurrentWorkingOperatorMemoryPool(), owner, key, value); + case DISABLE_MEMORY_MANAGEMENT: + default: + return new HugeVertexProperty<>(owner, key, value); + } + } + public void setMemoryMode(MemoryManager.MemoryMode memoryMode) { this.memoryMode = memoryMode; } private static class PropertyFactoryHolder { - private static final PropertyFactory INSTANCE = new PropertyFactory<>(); + private static final Map, PropertyFactory> FACTORIES_MAP = + new ConcurrentHashMap<>(); private PropertyFactoryHolder() { // empty constructor } } - public static PropertyFactory getInstance() { - return PropertyFactory.PropertyFactoryHolder.INSTANCE; + @SuppressWarnings("unchecked") + public static PropertyFactory getInstance(Class clazz) { + return (PropertyFactory) PropertyFactoryHolder.FACTORIES_MAP + .computeIfAbsent(clazz, k -> new PropertyFactory<>()); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java index 72938e5117..b615b3dbfe 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java @@ -33,7 +33,7 @@ public class ObjectIdOffHeap extends IdGenerator.ObjectId implements OffHeapObje private ByteBuf objectOffHeap; - public ObjectIdOffHeap(Object object, MemoryPool memoryPool) { + public ObjectIdOffHeap(MemoryPool memoryPool, Object object) { super(object); serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); From 865f1fb3e973b5e87647e97f503149e5603bc417 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 13:25:06 +0800 Subject: [PATCH 34/48] fix gc child bugs and add consumer test --- .../hugegraph/memory/MemoryManager.java | 15 ++++++++++++ .../memory/consumer/factory/IdFactory.java | 8 +++---- .../consumer/factory/PropertyFactory.java | 10 ++++---- .../memory/pool/AbstractMemoryPool.java | 8 ++++++- .../core/memory/MemoryConsumerTest.java | 24 +++++++++++++++---- .../core/memory/MemoryManageTest.java | 16 ++++++++++++- 6 files changed, 65 insertions(+), 16 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index d125ef47bb..74ce357e4a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -30,6 +30,7 @@ import org.apache.hugegraph.memory.arbitrator.MemoryArbitrator; import org.apache.hugegraph.memory.arbitrator.MemoryArbitratorImpl; +import org.apache.hugegraph.memory.consumer.factory.IdFactory; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.pool.impl.QueryMemoryPool; import org.apache.hugegraph.memory.pool.impl.TaskMemoryPool; @@ -39,6 +40,20 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * This class supports memory management for HugeGraph queries. + *

+ * Memory management is divided into three levels: query level, task (thread) level, and operator + * level. For each new query, the Manager's {@code addQueryMemoryPool} method is called to + * construct a new queryPool. During query execution, newTaskPool and newOperatorPool are + * required on demand. + *

+ * Where memory needs to be requested, use {@code getCorrespondingTaskMemoryPool} to get the + * current taskPool, and use {@code getCurrentWorkingOperatorMemoryPool} to get the working + * OperatorPool from the taskPool, and use OperatorPool to request memory + *

+ * Note: current MemoryManager doesn't support on-heap management. + */ public class MemoryManager { private static final Logger LOG = LoggerFactory.getLogger(MemoryManager.class); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java index c8bbe075ef..c3e67ddea1 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java @@ -305,10 +305,6 @@ public EdgeId newEdgeId(Id ownerVertexId, } } - public void setMemoryMode(MemoryManager.MemoryMode memoryMode) { - this.memoryMode = memoryMode; - } - private static class IdFactoryHolder { private static final IdFactory INSTANCE = new IdFactory(); @@ -319,6 +315,10 @@ private IdFactoryHolder() { } public static IdFactory getInstance() { + IdFactory instance = IdFactoryHolder.INSTANCE; + if (instance.memoryMode == null) { + instance.memoryMode = MemoryManager.getInstance().getMemoryMode(); + } return IdFactoryHolder.INSTANCE; } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java index 96b915ac18..dae672305a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java @@ -70,10 +70,6 @@ public HugeVertexProperty newHugeVertexProperty(HugeElement owner, PropertyKe } } - public void setMemoryMode(MemoryManager.MemoryMode memoryMode) { - this.memoryMode = memoryMode; - } - private static class PropertyFactoryHolder { private static final Map, PropertyFactory> FACTORIES_MAP = @@ -86,7 +82,11 @@ private PropertyFactoryHolder() { @SuppressWarnings("unchecked") public static PropertyFactory getInstance(Class clazz) { - return (PropertyFactory) PropertyFactoryHolder.FACTORIES_MAP + PropertyFactory instance = (PropertyFactory) PropertyFactoryHolder.FACTORIES_MAP .computeIfAbsent(clazz, k -> new PropertyFactory<>()); + if (instance.memoryMode == null) { + instance.memoryMode = MemoryManager.getInstance().getMemoryMode(); + } + return instance; } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 172ac8d50a..4f96c0ce8e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -17,9 +17,11 @@ package org.apache.hugegraph.memory.pool; +import java.util.HashSet; import java.util.Optional; import java.util.PriorityQueue; import java.util.Queue; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; @@ -128,9 +130,13 @@ public void releaseSelf(String reason, boolean isTriggeredInternal) { Optional.ofNullable(this.parent).ifPresent(parent -> parent.gcChildPool(this, false, isTriggeredInternal)); // gc all children - for (MemoryPool child : this.children) { + Set copiedChildren = new HashSet<>(this.children); + // since `gcChildPool` will remove elements from this.children, we need to traverse an + // immutable copy of this.children. + for (MemoryPool child : copiedChildren) { gcChildPool(child, true, isTriggeredInternal); } + copiedChildren.clear(); LOG.info("[{}] finishes to releaseSelf", this); } catch (InterruptedException e) { LOG.error("Failed to release self because ", e); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java index 6ff53b88db..eb5c13890f 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java @@ -25,12 +25,16 @@ import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.StandardHugeGraph; import org.apache.hugegraph.backend.id.Id; +import org.apache.hugegraph.backend.id.IdGenerator; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.dist.RegisterUtil; import org.apache.hugegraph.masterelection.GlobalMasterInfo; -import org.apache.hugegraph.memory.consumer.impl.id.StringIdOffHeap; +import org.apache.hugegraph.memory.consumer.OffHeapObject; +import org.apache.hugegraph.memory.consumer.factory.IdFactory; import org.apache.hugegraph.schema.SchemaManager; import org.apache.hugegraph.structure.HugeVertex; +import org.apache.hugegraph.testutil.Assert; +import org.apache.hugegraph.type.define.Directions; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -88,11 +92,21 @@ public static void clear() throws Exception { @Test public void testId() { - Id stringIdOffHeap = new StringIdOffHeap(query1Task1Operator1MemoryPool, "java"); + Id stringIdOffHeap = IdFactory.getInstance().newStringId("java"); + Id stringId = new IdGenerator.StringId("java"); + Assert.assertNotNull(stringIdOffHeap); + Assert.assertEquals("java", stringIdOffHeap.asString()); + Assert.assertEquals(stringId, ((OffHeapObject) stringIdOffHeap).zeroCopyReadFromByteBuf()); + } + + @Test + public void testComplexId() { + Id stringIdOffHeap = IdFactory.getInstance().newStringId("java"); HugeVertex java = new HugeVertex(graph, stringIdOffHeap, graph.vertexLabel("book")); - Id edgeLableId = new StringIdOffHeap(query1Task1Operator1MemoryPool, "testEdgeLabel"); - Id subLableId = new StringIdOffHeap(query1Task1Operator1MemoryPool, "testSubLabel"); - // Id id = new EdgeIdOffHeap(java, Directions.OUT, edgeLableId, subLableId, "test", java); + Id edgeLableId = IdFactory.getInstance().newStringId("testEdgeLabel"); + Id subLableId = IdFactory.getInstance().newStringId("testSubLabel"); + Id id = IdFactory.getInstance().newEdgeId(java, Directions.OUT, edgeLableId, subLableId, + "test", java); } @Test diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java index fef8e60ff7..3851e0e41a 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java @@ -99,10 +99,24 @@ public void after() { Assert.assertEquals(0, memoryManager.getCurrentQueryMemoryPools().size()); Assert.assertEquals(0, query1MemoryPool.getAllocatedBytes()); Assert.assertEquals(0, query2MemoryPool.getAllocatedBytes()); + Assert.assertEquals(0, query1Task1MemoryPool.getAllocatedBytes()); + Assert.assertEquals(0, query2Task1MemoryPool.getAllocatedBytes()); Assert.assertEquals(0, query1Task1Operator2MemoryPool.getAllocatedBytes()); + Assert.assertEquals(0, query1Task1Operator1MemoryPool.getAllocatedBytes()); + Assert.assertEquals(0, query2Task1Operator1MemoryPool.getAllocatedBytes()); Assert.assertEquals(0, memoryManager.getCurrentOffHeapAllocatedMemoryInBytes().get()); } + @Test + public void testCurrentWorkingMemoryPool() { + TaskMemoryPool taskMemoryPool = + (TaskMemoryPool) memoryManager.getCorrespondingTaskMemoryPool( + Thread.currentThread() + .getName()); + Assert.assertNotNull(taskMemoryPool); + Assert.assertNotNull(taskMemoryPool.getCurrentWorkingOperatorMemoryPool()); + } + @Test public void testMemoryPoolStructure() { Assert.assertEquals(2, memoryManager.getCurrentQueryMemoryPools().size()); @@ -210,7 +224,7 @@ public void testExpandCapacity() { } @Test - public void testLocalArbitrationFail() { + public void testLocalArbitration() { long totalMemory = 2 * Bytes.MB + Bytes.KB; memoryManager.getCurrentAvailableMemoryInBytes().set(totalMemory); long requireBytes = Bytes.KB; From f34e23389d0e66fdd8213fdbc0b4da5aee43ff9e Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 13:41:26 +0800 Subject: [PATCH 35/48] fix deallocate netty memory block bug & add complexId test --- .../allocator/NettyMemoryAllocator.java | 4 ++- .../consumer/impl/id/BinaryIdOffHeap.java | 1 + .../consumer/impl/id/EdgeIdOffHeap.java | 11 ++++++-- .../consumer/impl/id/LongIdOffHeap.java | 2 ++ .../consumer/impl/id/ObjectIdOffHeap.java | 1 + .../consumer/impl/id/QueryIdOffHeap.java | 1 + .../consumer/impl/id/StringIdOffHeap.java | 8 ++++++ .../consumer/impl/id/UuidIdOffHeap.java | 3 +++ .../property/HugeEdgePropertyOffHeap.java | 1 + .../property/HugeVertexPropertyOffHeap.java | 1 + .../core/memory/MemoryConsumerTest.java | 25 ++++++++++++++++--- 11 files changed, 52 insertions(+), 6 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java index fcfee75133..8a825ac159 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/allocator/NettyMemoryAllocator.java @@ -60,7 +60,9 @@ public void returnMemoryToManager(long size) { @Override public void releaseMemoryBlock(Object memoryBlock) { if (!(memoryBlock instanceof ByteBuf)) { - throw new IllegalArgumentException("memoryBlock must be ByteBuf"); + throw new IllegalArgumentException( + String.format("memoryBlock must be ByteBuf, current " + + "class: %s", memoryBlock.getClass())); } ByteBuf buf = (ByteBuf) memoryBlock; ReferenceCountUtil.safeRelease(buf); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java index 3d78be8058..e6444f3061 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/BinaryIdOffHeap.java @@ -40,6 +40,7 @@ public BinaryIdOffHeap(byte[] bytes, Id id, MemoryPool memoryPool, OffHeapObject this.originId = originId; serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java index 9f7811c679..4d3e7f57c5 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java @@ -18,6 +18,7 @@ package org.apache.hugegraph.memory.consumer.impl.id; import java.nio.charset.StandardCharsets; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -64,6 +65,7 @@ public EdgeIdOffHeap(HugeVertex ownerVertex, this.otherVertexIdOffHeap = otherVertexIdOffHeap; serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } public EdgeIdOffHeap(Id ownerVertexId, @@ -86,6 +88,7 @@ public EdgeIdOffHeap(Id ownerVertexId, this.otherVertexIdOffHeap = otherVertexIdOffHeap; serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } public EdgeIdOffHeap(Id ownerVertexId, @@ -109,6 +112,7 @@ public EdgeIdOffHeap(Id ownerVertexId, this.otherVertexIdOffHeap = otherVertexIdOffHeap; serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } @Override @@ -128,7 +132,8 @@ public Object zeroCopyReadFromByteBuf() { @Override public void serializeSelfToByteBuf(MemoryPool memoryPool) { byte[] stringBytes = sortValues.getBytes((StandardCharsets.UTF_8)); - this.sortValuesOffHeap = (ByteBuf) this.memoryPool.requireMemory(stringBytes.length, memoryPool); + this.sortValuesOffHeap = + (ByteBuf) this.memoryPool.requireMemory(stringBytes.length, memoryPool); this.sortValuesOffHeap.markReaderIndex(); this.sortValuesOffHeap.writeBytes(stringBytes); } @@ -140,7 +145,9 @@ public void releaseOriginalVarsOnHeap() { @Override public List getAllMemoryBlock() { - return Lists.newArrayList(this.sortValuesOffHeap, this.cacheOffHeap); + return this.cacheOffHeap == null ? Collections.singletonList(this.sortValuesOffHeap) : + Lists.newArrayList(this.sortValuesOffHeap, + this.cacheOffHeap); } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java index 9e2ae9729e..8d86f84a88 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/LongIdOffHeap.java @@ -39,12 +39,14 @@ public LongIdOffHeap(MemoryPool memoryPool, long id) { super(id); serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } public LongIdOffHeap(MemoryPool memoryPool, byte[] bytes) { super(bytes); serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java index b615b3dbfe..d47d955a4d 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/ObjectIdOffHeap.java @@ -37,6 +37,7 @@ public ObjectIdOffHeap(MemoryPool memoryPool, Object object) { super(object); serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java index 25a5a74266..8a8dd4d1ee 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/QueryIdOffHeap.java @@ -38,6 +38,7 @@ public QueryIdOffHeap(MemoryPool memoryPool, Query q) { super(q); serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java index cb64415a5d..be96c2c963 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/StringIdOffHeap.java @@ -27,6 +27,7 @@ import org.apache.hugegraph.backend.id.IdGenerator; import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.pool.MemoryPool; +import org.jetbrains.annotations.TestOnly; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; @@ -39,12 +40,14 @@ public StringIdOffHeap(MemoryPool memoryPool, String id) { super(id); serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } public StringIdOffHeap(MemoryPool memoryPool, byte[] bytes) { super(bytes); serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } @Override @@ -129,4 +132,9 @@ public boolean equals(Object other) { public String toString() { return this.asString(); } + + @TestOnly + public ByteBuf getIdOffHeap() { + return idOffHeap; + } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java index b54c096c0e..ed4b0399b5 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/UuidIdOffHeap.java @@ -47,18 +47,21 @@ public UuidIdOffHeap(MemoryPool memoryPool, String string) { super(string); serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } public UuidIdOffHeap(MemoryPool memoryPool, byte[] bytes) { super(bytes); serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } public UuidIdOffHeap(MemoryPool memoryPool, UUID uuid) { super(uuid); serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java index 44b4848f4d..d2f21a414c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeEdgePropertyOffHeap.java @@ -41,6 +41,7 @@ public HugeEdgePropertyOffHeap(MemoryPool memoryPool, HugeElement owner, Propert super(owner, key, value); serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java index 60e426a1d8..1beb759cf0 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/property/HugeVertexPropertyOffHeap.java @@ -40,6 +40,7 @@ public HugeVertexPropertyOffHeap(MemoryPool memoryPool, HugeElement owner, Prope super(owner, key, value); serializeSelfToByteBuf(memoryPool); releaseOriginalVarsOnHeap(); + memoryPool.bindMemoryConsumer(this); } @Override diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java index eb5c13890f..4db406bfa1 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java @@ -24,6 +24,7 @@ import org.apache.commons.configuration2.io.FileHandler; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.StandardHugeGraph; +import org.apache.hugegraph.backend.id.EdgeId; import org.apache.hugegraph.backend.id.Id; import org.apache.hugegraph.backend.id.IdGenerator; import org.apache.hugegraph.config.HugeConfig; @@ -31,6 +32,7 @@ import org.apache.hugegraph.masterelection.GlobalMasterInfo; import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.consumer.factory.IdFactory; +import org.apache.hugegraph.memory.consumer.impl.id.StringIdOffHeap; import org.apache.hugegraph.schema.SchemaManager; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.testutil.Assert; @@ -39,6 +41,8 @@ import org.junit.BeforeClass; import org.junit.Test; +import io.netty.util.IllegalReferenceCountException; + public class MemoryConsumerTest extends MemoryManageTest { private static HugeGraph graph; @@ -97,16 +101,31 @@ public void testId() { Assert.assertNotNull(stringIdOffHeap); Assert.assertEquals("java", stringIdOffHeap.asString()); Assert.assertEquals(stringId, ((OffHeapObject) stringIdOffHeap).zeroCopyReadFromByteBuf()); + // Test release memoryBlock + memoryManager.getCorrespondingTaskMemoryPool(Thread.currentThread().getName()) + .releaseSelf("test", false); + Assert.assertThrows(IllegalReferenceCountException.class, + ((StringIdOffHeap) stringIdOffHeap).getIdOffHeap()::memoryAddress); } @Test public void testComplexId() { Id stringIdOffHeap = IdFactory.getInstance().newStringId("java"); HugeVertex java = new HugeVertex(graph, stringIdOffHeap, graph.vertexLabel("book")); - Id edgeLableId = IdFactory.getInstance().newStringId("testEdgeLabel"); - Id subLableId = IdFactory.getInstance().newStringId("testSubLabel"); - Id id = IdFactory.getInstance().newEdgeId(java, Directions.OUT, edgeLableId, subLableId, + Id edgeLabelIdOffHeap = IdFactory.getInstance().newStringId("testEdgeLabel"); + Id subLabelIdOffHeap = IdFactory.getInstance().newStringId("testSubLabel"); + Id edgeIdOffHeap = + IdFactory.getInstance().newEdgeId(java, Directions.OUT, edgeLabelIdOffHeap, + subLabelIdOffHeap, "test", java); + Id edgeId = new EdgeId(java, + Directions.OUT, + (Id) ((OffHeapObject) edgeLabelIdOffHeap).zeroCopyReadFromByteBuf(), + (Id) ((OffHeapObject) subLabelIdOffHeap).zeroCopyReadFromByteBuf(), + "test", + java); + Assert.assertNotNull(edgeIdOffHeap); + Assert.assertEquals(edgeId, edgeIdOffHeap); } @Test From 879390b1b5252fe74514ad269677f12a1f2b4f19 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 14:53:43 +0800 Subject: [PATCH 36/48] complete all ut --- .../memory/consumer/OffHeapObject.java | 1 + .../consumer/impl/id/EdgeIdOffHeap.java | 4 +- .../memory/pool/AbstractMemoryPool.java | 6 +- .../memory/pool/impl/OperatorMemoryPool.java | 16 ++- .../memory/pool/impl/QueryMemoryPool.java | 2 +- .../core/memory/MemoryConsumerTest.java | 118 +++++++++++++++++- 6 files changed, 129 insertions(+), 18 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/OffHeapObject.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/OffHeapObject.java index 6af72abe88..d192e8d928 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/OffHeapObject.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/OffHeapObject.java @@ -30,6 +30,7 @@ public interface OffHeapObject { /** * This method will read from off-heap ByteBuf storing binary data of self. + * Note: need class cast by hand when using. * * @return self value */ diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java index 4d3e7f57c5..b77de337a8 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/impl/id/EdgeIdOffHeap.java @@ -118,12 +118,12 @@ public EdgeIdOffHeap(Id ownerVertexId, @Override public Object zeroCopyReadFromByteBuf() { try { - return new EdgeId((HugeVertex) this.ownerVertexIdOffHeap.zeroCopyReadFromByteBuf(), + return new EdgeId((Id) this.ownerVertexIdOffHeap.zeroCopyReadFromByteBuf(), this.direction, (Id) this.edgeLabelIdOffHeap.zeroCopyReadFromByteBuf(), (Id) this.subLabelIdOffHeap.zeroCopyReadFromByteBuf(), this.sortValuesOffHeap.toString(StandardCharsets.UTF_8), - (HugeVertex) this.otherVertexIdOffHeap.zeroCopyReadFromByteBuf()); + (Id) this.otherVertexIdOffHeap.zeroCopyReadFromByteBuf()); } finally { this.sortValuesOffHeap.resetReaderIndex(); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 4f96c0ce8e..0e06de8323 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -89,7 +89,7 @@ public long tryToReclaimLocalMemory(long neededBytes, MemoryPool requestingPool) } private long reclaimChildren(long neededBytes, MemoryPool requestingPool) { - LOG.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); + LOG.debug("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); this.isBeingArbitrated.set(true); long totalReclaimedBytes = 0; long currentNeededBytes = neededBytes; @@ -124,7 +124,7 @@ public void releaseSelf(String reason, boolean isTriggeredInternal) { this.condition.await(); } } - LOG.info("[{}] starts to releaseSelf because of {}", this, reason); + LOG.debug("[{}] starts to releaseSelf", this); this.isClosed = true; // gc self from father Optional.ofNullable(this.parent).ifPresent(parent -> parent.gcChildPool(this, false, @@ -137,7 +137,7 @@ public void releaseSelf(String reason, boolean isTriggeredInternal) { gcChildPool(child, true, isTriggeredInternal); } copiedChildren.clear(); - LOG.info("[{}] finishes to releaseSelf", this); + LOG.info("[{}] finishes to releaseSelf because of {}", this, reason); } catch (InterruptedException e) { LOG.error("Failed to release self because ", e); Thread.currentThread().interrupt(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index b98635b212..8b5119eb52 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -79,7 +79,7 @@ public long tryToReclaimLocalMemory(long neededBytes, MemoryPool requestingPool) if (!this.equals(requestingPool)) { this.memoryActionLock.lock(); } - LOG.info("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); + LOG.debug("[{}] tryToReclaimLocalMemory: neededBytes={}", this, neededBytes); this.isBeingArbitrated.set(true); // 1. try to reclaim self free memory reclaimableBytes = getFreeBytes(); @@ -125,8 +125,12 @@ public Object requireMemory(long bytes, MemoryPool requestingPool) { // use lock to ensure the atomicity of the two-step operation this.memoryActionLock.lock(); // if free memory is enough, use free memory directly. - if (getFreeBytes() >= bytes) { - this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() - bytes); + if (getFreeBytes() < bytes) { + LOG.debug("[{}] require {} bytes, there is enough free memory {} bytes, will " + + "require memory directly from self's free memory.", + this, + getFreeBytes(), + bytes); } else { // if free memory is not enough, try to request delta long delta = bytes - getFreeBytes(); @@ -154,7 +158,7 @@ public Object tryToAcquireMemoryInternal(long size) { LOG.warn("[{}] is already closed, will abort this allocate", this); return null; } - LOG.info("[{}] tryToAcquireMemory: size={}", this, size); + LOG.debug("[{}] tryToAcquireMemory: size={}", this, size); // 1. update statistic super.tryToAcquireMemoryInternal(size); // 2. call parent to update statistic @@ -178,7 +182,7 @@ public long requestMemoryInternal(long size, MemoryPool requestingPool) throws if (this.isBeingArbitrated.get()) { this.condition.await(); } - LOG.info("[{}] requestMemory: request size={}", this, size); + LOG.debug("[{}] requestMemory: request size={}", this, size); // 1. align size long alignedSize = RoundUtil.sizeAlign(size); // 2. reserve(round) @@ -197,7 +201,7 @@ public long requestMemoryInternal(long size, MemoryPool requestingPool) throws // 4. update stats this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + neededMemorySize); this.stats.setNumExpands(this.stats.getNumExpands() + 1); - LOG.info("[{}] requestMemory success: requestedMemorySize={}", this, fatherRes); + LOG.debug("[{}] requestMemory success: requestedMemorySize={}", this, fatherRes); return fatherRes; } catch (InterruptedException e) { LOG.error("Failed to release self because ", e); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 8a036b4430..291c978098 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -118,7 +118,7 @@ public long requestMemoryInternal(long bytes, MemoryPool requestingPool) { } private long tryToExpandSelfCapacity(long size) { - LOG.info("[{}] try to expand its capacity: size={}", this, size); + LOG.debug("[{}] try to expand its capacity: size={}", this, size); long alignedSize = RoundUtil.sizeAlign(size); long realNeededSize = RoundUtil.roundDelta(getAllocatedBytes(), alignedSize); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java index 4db406bfa1..b3a83d0e50 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java @@ -18,24 +18,35 @@ package org.apache.hugegraph.core.memory; import java.nio.file.Paths; +import java.util.UUID; import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; import org.apache.commons.configuration2.io.FileHandler; import org.apache.hugegraph.HugeGraph; import org.apache.hugegraph.StandardHugeGraph; +import org.apache.hugegraph.backend.cache.CachedBackendStore; import org.apache.hugegraph.backend.id.EdgeId; import org.apache.hugegraph.backend.id.Id; import org.apache.hugegraph.backend.id.IdGenerator; +import org.apache.hugegraph.backend.query.Query; +import org.apache.hugegraph.backend.serializer.BinaryBackendEntry; import org.apache.hugegraph.config.HugeConfig; import org.apache.hugegraph.dist.RegisterUtil; import org.apache.hugegraph.masterelection.GlobalMasterInfo; import org.apache.hugegraph.memory.consumer.OffHeapObject; import org.apache.hugegraph.memory.consumer.factory.IdFactory; +import org.apache.hugegraph.memory.consumer.factory.PropertyFactory; import org.apache.hugegraph.memory.consumer.impl.id.StringIdOffHeap; +import org.apache.hugegraph.schema.EdgeLabel; +import org.apache.hugegraph.schema.PropertyKey; import org.apache.hugegraph.schema.SchemaManager; +import org.apache.hugegraph.structure.HugeEdge; +import org.apache.hugegraph.structure.HugeEdgeProperty; +import org.apache.hugegraph.structure.HugeProperty; import org.apache.hugegraph.structure.HugeVertex; import org.apache.hugegraph.testutil.Assert; +import org.apache.hugegraph.type.HugeType; import org.apache.hugegraph.type.define.Directions; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -95,9 +106,9 @@ public static void clear() throws Exception { } @Test - public void testId() { + public void testStringId() { Id stringIdOffHeap = IdFactory.getInstance().newStringId("java"); - Id stringId = new IdGenerator.StringId("java"); + Id stringId = IdGenerator.of("java"); Assert.assertNotNull(stringIdOffHeap); Assert.assertEquals("java", stringIdOffHeap.asString()); Assert.assertEquals(stringId, ((OffHeapObject) stringIdOffHeap).zeroCopyReadFromByteBuf()); @@ -109,11 +120,65 @@ public void testId() { } @Test - public void testComplexId() { + public void testLongId() { + Id idOffHeap = IdFactory.getInstance().newLongId(1); + Id id = IdGenerator.of(1); + Assert.assertNotNull(idOffHeap); + Assert.assertEquals(1, idOffHeap.asLong()); + Assert.assertEquals(id, ((OffHeapObject) idOffHeap).zeroCopyReadFromByteBuf()); + } + + @Test + public void testUuidId() { + UUID uuidEncoding = UUID.randomUUID(); + Id idOffHeap = IdFactory.getInstance().newUuidId(uuidEncoding); + Id id = IdGenerator.of(uuidEncoding); + Assert.assertNotNull(idOffHeap); + Assert.assertArrayEquals(id.asBytes(), idOffHeap.asBytes()); + Assert.assertEquals(id, ((OffHeapObject) idOffHeap).zeroCopyReadFromByteBuf()); + } + + @Test + public void testBinaryId() { + Id stringIdOffHeap = IdFactory.getInstance().newStringId("java"); + Id idOffHeap = + IdFactory.getInstance().newBinaryId(stringIdOffHeap.asBytes(), stringIdOffHeap); + Id id = new BinaryBackendEntry.BinaryId(stringIdOffHeap.asBytes(), stringIdOffHeap); + Assert.assertNotNull(idOffHeap); + Assert.assertArrayEquals(stringIdOffHeap.asBytes(), idOffHeap.asBytes()); + Assert.assertEquals(id, ((OffHeapObject) idOffHeap).zeroCopyReadFromByteBuf()); + } + + @Test + public void testObjectId() { + TestObject object = new TestObject(); + object.x = 1; + object.y = "test"; + Id idOffHeap = + IdFactory.getInstance().newObjectId(object); + Id id = new IdGenerator.ObjectId(object); + Assert.assertNotNull(idOffHeap); + Assert.assertEquals(id.asObject(), idOffHeap.asObject()); + Assert.assertEquals(id, ((OffHeapObject) idOffHeap).zeroCopyReadFromByteBuf()); + } + + @Test + public void testQueryId() { + Query q = new Query(HugeType.VERTEX); + Id idOffHeap = + IdFactory.getInstance().newQueryId(q); + Id id = new CachedBackendStore.QueryId(q); + Assert.assertNotNull(idOffHeap); + Assert.assertEquals(id.toString(), idOffHeap.toString()); + Assert.assertEquals(id, ((OffHeapObject) idOffHeap).zeroCopyReadFromByteBuf()); + } + + @Test + public void testEdgeId() { Id stringIdOffHeap = IdFactory.getInstance().newStringId("java"); HugeVertex java = new HugeVertex(graph, stringIdOffHeap, graph.vertexLabel("book")); - Id edgeLabelIdOffHeap = IdFactory.getInstance().newStringId("testEdgeLabel"); - Id subLabelIdOffHeap = IdFactory.getInstance().newStringId("testSubLabel"); + Id edgeLabelIdOffHeap = IdFactory.getInstance().newLongId(1); + Id subLabelIdOffHeap = IdFactory.getInstance().newLongId(2); Id edgeIdOffHeap = IdFactory.getInstance().newEdgeId(java, Directions.OUT, edgeLabelIdOffHeap, subLabelIdOffHeap, @@ -125,11 +190,52 @@ public void testComplexId() { "test", java); Assert.assertNotNull(edgeIdOffHeap); - Assert.assertEquals(edgeId, edgeIdOffHeap); + // TODO: adopt equals method + Assert.assertEquals(edgeId.asString(), edgeIdOffHeap.asString()); } @Test public void testProperty() { + Id stringIdOffHeap = IdFactory.getInstance().newStringId("java"); + HugeVertex java = new HugeVertex(graph, stringIdOffHeap, graph.vertexLabel("book")); + Id edgeLabelIdOffHeap = IdFactory.getInstance().newLongId(1); + Id subLabelIdOffHeap = IdFactory.getInstance().newLongId(2); + Id edgeId = new EdgeId(java, + Directions.OUT, + (Id) ((OffHeapObject) edgeLabelIdOffHeap).zeroCopyReadFromByteBuf(), + (Id) ((OffHeapObject) subLabelIdOffHeap).zeroCopyReadFromByteBuf(), + "test", + java); + HugeEdge testEdge = new HugeEdge(graph, edgeId, EdgeLabel.NONE); + PropertyKey propertyKey = new PropertyKey(null, IdFactory.getInstance().newLongId(3), + "fake"); + + String propertyValue = "test"; + HugeProperty propertyOffHeap = + PropertyFactory.getInstance(String.class).newHugeEdgeProperty(testEdge, + propertyKey, + propertyValue); + HugeEdgeProperty property = new HugeEdgeProperty<>(testEdge, + propertyKey, + propertyValue); + Assert.assertNotNull(propertyOffHeap); + Assert.assertEquals(property.value(), propertyOffHeap.value()); + Assert.assertEquals(property, propertyOffHeap); + } + + static class TestObject { + + long x; + String y; + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TestObject)) { + return false; + } + TestObject other = (TestObject) obj; + return this.x == other.x && this.y.equals(other.y); + } } } From a96e9eea15ec4ac7551db28144564024158a9627 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 14:57:12 +0800 Subject: [PATCH 37/48] fix all bugs --- .../apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index 8b5119eb52..98da093156 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -125,7 +125,7 @@ public Object requireMemory(long bytes, MemoryPool requestingPool) { // use lock to ensure the atomicity of the two-step operation this.memoryActionLock.lock(); // if free memory is enough, use free memory directly. - if (getFreeBytes() < bytes) { + if (getFreeBytes() >= bytes) { LOG.debug("[{}] require {} bytes, there is enough free memory {} bytes, will " + "require memory directly from self's free memory.", this, From 7c86e84580f989bc9101a92abda089427f5dba12 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 15:22:09 +0800 Subject: [PATCH 38/48] dependency --- .../scripts/dependency/known-dependencies.txt | 32 ++++++++++++++++++- .../scripts/dependency/known-dependencies.txt | 29 +++++++++-------- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/hugegraph-commons/hugegraph-dist/scripts/dependency/known-dependencies.txt b/hugegraph-commons/hugegraph-dist/scripts/dependency/known-dependencies.txt index 9a421edcd4..5db5f373f8 100644 --- a/hugegraph-commons/hugegraph-dist/scripts/dependency/known-dependencies.txt +++ b/hugegraph-commons/hugegraph-dist/scripts/dependency/known-dependencies.txt @@ -1,4 +1,7 @@ +animal-sniffer-annotations-1.18.jar annotations-13.0.jar +annotations-4.1.1.4.jar +bolt-1.6.2.jar checker-qual-3.5.0.jar commons-beanutils-1.9.4.jar commons-codec-1.13.jar @@ -10,14 +13,25 @@ commons-lang-2.6.jar commons-lang3-3.12.0.jar commons-logging-1.1.1.jar commons-text-1.9.jar +disruptor-3.3.7.jar error_prone_annotations-2.3.4.jar failureaccess-1.0.1.jar +grpc-api-1.28.1.jar +grpc-context-1.28.1.jar +grpc-core-1.28.1.jar +grpc-netty-shaded-1.28.0.jar +grpc-protobuf-1.28.0.jar +grpc-protobuf-lite-1.28.0.jar +grpc-stub-1.28.0.jar +gson-2.8.6.jar guava-30.0-jre.jar hamcrest-core-1.3.jar +hessian-3.3.7.jar j2objc-annotations-1.3.jar jackson-annotations-2.14.0-rc1.jar jackson-core-2.14.0-rc1.jar jackson-databind-2.14.0-rc1.jar +jackson-dataformat-yaml-2.9.3.jar jackson-jaxrs-base-2.14.0-rc1.jar jackson-jaxrs-json-provider-2.14.0-rc1.jar jackson-module-jaxb-annotations-2.14.0-rc1.jar @@ -39,7 +53,23 @@ log4j-api-2.18.0.jar log4j-core-2.18.0.jar log4j-slf4j-impl-2.18.0.jar logging-interceptor-4.10.0.jar -lombok-1.18.8.jar +lookout-api-1.4.1.jar +netty-all-4.1.42.Final.jar okhttp-4.10.0.jar okio-jvm-3.0.0.jar +opentracing-api-0.22.0.jar +opentracing-mock-0.22.0.jar +opentracing-noop-0.22.0.jar +opentracing-util-0.22.0.jar +perfmark-api-0.19.0.jar +proto-google-common-protos-1.17.0.jar +protobuf-java-3.11.0.jar slf4j-api-1.7.25.jar +snakeyaml-1.18.jar +sofa-common-tools-1.0.12.jar +sofa-rpc-all-5.7.6.jar +swagger-annotations-1.5.18.jar +swagger-core-1.5.18.jar +swagger-models-1.5.18.jar +tracer-core-3.0.8.jar +validation-api-1.1.0.Final.jar diff --git a/install-dist/scripts/dependency/known-dependencies.txt b/install-dist/scripts/dependency/known-dependencies.txt index 02b5dda11a..36255a96eb 100644 --- a/install-dist/scripts/dependency/known-dependencies.txt +++ b/install-dist/scripts/dependency/known-dependencies.txt @@ -1,3 +1,7 @@ +HdrHistogram-2.1.12.jar +HdrHistogram-2.1.9.jar +LatencyUtils-2.0.3.jar +ST4-4.0.8.jar accessors-smart-1.2.jar airline-0.8.jar android-json-0.0.20131108.vaadin1.jar @@ -87,6 +91,7 @@ fastparse_2.12-2.0.4.jar fastutil-8.5.9.jar findbugs-annotations-1.3.9-1.jar front-end-9.0-9.0.20190305.jar +fury-core-0.9.0-SNAPSHOT.jar gremlin-console-3.5.1.jar gremlin-core-3.5.1.jar gremlin-driver-3.5.1.jar @@ -142,8 +147,6 @@ hamcrest-2.2.jar hamcrest-core-1.3.jar hanlp-portable-1.8.3.jar hbase-shaded-endpoint-2.0.6.jar -HdrHistogram-2.1.12.jar -HdrHistogram-2.1.9.jar hessian-3.3.6.jar hessian-3.3.7.jar hg-pd-client-1.5.0.jar @@ -214,12 +217,12 @@ javassist-3.21.0-GA.jar javassist-3.24.0-GA.jar javassist-3.28.0-GA.jar javatuples-1.2.jar +javax-websocket-client-impl-9.4.46.v20220331.jar +javax-websocket-server-impl-9.4.46.v20220331.jar javax.activation-api-1.2.0.jar javax.annotation-api-1.3.2.jar javax.inject-1.jar javax.json-1.0.jar -javax-websocket-client-impl-9.4.46.v20220331.jar -javax-websocket-server-impl-9.4.46.v20220331.jar jaxb-api-2.3.1.jar jaxb-core-3.0.2.jar jaxb-impl-3.0.2.jar @@ -262,8 +265,8 @@ jetty-util-9.4.46.v20220331.jar jetty-util-ajax-9.4.46.v20220331.jar jetty-webapp-9.4.46.v20220331.jar jetty-xml-9.4.46.v20220331.jar -jffi-1.2.16.jar jffi-1.2.16-native.jar +jffi-1.2.16.jar jflex-1.8.2.jar jieba-analysis-1.0.2.jar jjwt-api-0.11.5.jar @@ -280,10 +283,10 @@ jraft-core-1.3.11.jar jraft-core-1.3.13.jar jraft-core-1.3.9.jar json-20210307.jar -jsonassert-1.5.0.jar json-path-2.5.0.jar json-simple-1.1.jar json-smart-2.3.jar +jsonassert-1.5.0.jar jsr305-3.0.1.jar jsr305-3.0.2.jar jul-to-slf4j-1.7.36.jar @@ -314,7 +317,6 @@ kotlin-stdlib-1.6.20.jar kotlin-stdlib-common-1.5.31.jar kotlin-stdlib-jdk7-1.6.10.jar kotlin-stdlib-jdk8-1.6.10.jar -LatencyUtils-2.0.3.jar listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar log4j-api-2.15.0.jar log4j-api-2.17.0.jar @@ -364,10 +366,10 @@ netty-buffer-4.1.52.Final.jar netty-buffer-4.1.72.Final.jar netty-codec-4.1.52.Final.jar netty-codec-4.1.72.Final.jar -netty-codec-http2-4.1.52.Final.jar -netty-codec-http2-4.1.72.Final.jar netty-codec-http-4.1.52.Final.jar netty-codec-http-4.1.72.Final.jar +netty-codec-http2-4.1.52.Final.jar +netty-codec-http2-4.1.72.Final.jar netty-codec-socks-4.1.52.Final.jar netty-codec-socks-4.1.72.Final.jar netty-common-4.1.52.Final.jar @@ -415,20 +417,20 @@ powermock-module-junit4-2.0.0-RC.3.jar powermock-module-junit4-common-2.0.0-RC.3.jar powermock-module-junit4-rule-2.0.0-RC.3.jar powermock-reflect-2.0.0-RC.3.jar +proto-google-common-protos-1.17.0.jar +proto-google-common-protos-2.0.1.jar protobuf-java-3.11.0.jar protobuf-java-3.17.2.jar protobuf-java-3.21.7.jar protobuf-java-3.5.1.jar protobuf-java-util-3.17.2.jar -proto-google-common-protos-1.17.0.jar -proto-google-common-protos-2.0.1.jar protostuff-api-1.6.0.jar protostuff-collectionschema-1.6.0.jar protostuff-core-1.6.0.jar protostuff-runtime-1.6.0.jar psjava-0.1.19.jar -reporter-config3-3.0.3.jar reporter-config-base-3.0.3.jar +reporter-config3-3.0.3.jar rewriting-9.0-9.0.20190305.jar rocksdbjni-6.29.5.jar rocksdbjni-7.2.2.jar @@ -445,9 +447,9 @@ sjk-cli-0.22.jar sjk-core-0.14.jar sjk-core-0.22.jar sjk-hflame-0.22.jar +sjk-jfr-standalone-0.7.jar sjk-jfr5-0.5.jar sjk-jfr6-0.7.jar -sjk-jfr-standalone-0.7.jar sjk-json-0.14.jar sjk-json-0.22.jar sjk-nps-0.9.jar @@ -491,7 +493,6 @@ spring-expression-5.3.20.jar spring-jcl-5.3.20.jar spring-web-5.3.20.jar spring-webmvc-5.3.20.jar -ST4-4.0.8.jar stream-2.5.2.jar swagger-annotations-1.5.18.jar swagger-annotations-jakarta-2.2.18.jar From 5af2cb9e4dde7163fd1f5edff25b6ca469702336 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 15:56:55 +0800 Subject: [PATCH 39/48] add comments --- .../consumer/factory/PropertyFactory.java | 2 - .../memory/pool/AbstractMemoryPool.java | 10 ++--- .../hugegraph/memory/pool/MemoryPool.java | 39 +++++++++++++++++-- .../memory/pool/impl/OperatorMemoryPool.java | 12 +++--- .../memory/pool/impl/TaskMemoryPool.java | 4 +- 5 files changed, 49 insertions(+), 18 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java index dae672305a..7ac0431731 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java @@ -37,7 +37,6 @@ public class PropertyFactory { public HugeEdgeProperty newHugeEdgeProperty(HugeElement owner, PropertyKey key, V value) { switch (memoryMode) { - case ENABLE_ON_HEAP_MANAGEMENT: case ENABLE_OFF_HEAP_MANAGEMENT: TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() @@ -55,7 +54,6 @@ public HugeEdgeProperty newHugeEdgeProperty(HugeElement owner, PropertyKey ke public HugeVertexProperty newHugeVertexProperty(HugeElement owner, PropertyKey key, V value) { switch (memoryMode) { - case ENABLE_ON_HEAP_MANAGEMENT: case ENABLE_OFF_HEAP_MANAGEMENT: TaskMemoryPool taskMemoryPool = (TaskMemoryPool) MemoryManager.getInstance() diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 0e06de8323..006af6e5d8 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -116,9 +116,9 @@ private long reclaimChildren(long neededBytes, MemoryPool requestingPool) { * called when one layer pool is successfully executed and exited. */ @Override - public void releaseSelf(String reason, boolean isTriggeredInternal) { + public void releaseSelf(String reason, boolean isTriggeredByOOM) { try { - if (!isTriggeredInternal) { + if (!isTriggeredByOOM) { this.memoryActionLock.lock(); if (this.isBeingArbitrated.get()) { this.condition.await(); @@ -128,13 +128,13 @@ public void releaseSelf(String reason, boolean isTriggeredInternal) { this.isClosed = true; // gc self from father Optional.ofNullable(this.parent).ifPresent(parent -> parent.gcChildPool(this, false, - isTriggeredInternal)); + isTriggeredByOOM)); // gc all children Set copiedChildren = new HashSet<>(this.children); // since `gcChildPool` will remove elements from this.children, we need to traverse an // immutable copy of this.children. for (MemoryPool child : copiedChildren) { - gcChildPool(child, true, isTriggeredInternal); + gcChildPool(child, true, isTriggeredByOOM); } copiedChildren.clear(); LOG.info("[{}] finishes to releaseSelf because of {}", this, reason); @@ -142,7 +142,7 @@ public void releaseSelf(String reason, boolean isTriggeredInternal) { LOG.error("Failed to release self because ", e); Thread.currentThread().interrupt(); } finally { - if (!isTriggeredInternal) { + if (!isTriggeredByOOM) { this.memoryActionLock.unlock(); } // Make these objs be GCed by JVM quickly. diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index 8c67cb27be..1e8f68a131 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -26,21 +26,54 @@ public interface MemoryPool { MemoryPoolStats getSnapShot(); + /** + * Try to reclaim self's free memory, triggered by an arbitration. + * + * @param neededBytes reclaim goal, which means this reclaim will try to collect neededBytes. + * @param requestingPool the memoryPool that requests this arbitration. + * @return reclaimed memory in bytes. + */ long tryToReclaimLocalMemory(long neededBytes, MemoryPool requestingPool); + /** + * Require to be allocated with a memory block. This method contains two steps: + *

+ * 1. Request manager for a logic allocation. Throw OOM exception if memory exhausted. + * 2. Request allocator for a real allocation. Return real memory block. + * + * @param bytes needed bytes. + * @param requestingPool the memoryPool that requests this allocation. + * @return memory block. ByteBuf if using off-heap, byte[] if using on-heap. + */ Object requireMemory(long bytes, MemoryPool requestingPool); + /** + * Request MemoryManager for a logic allocation. This method is used internal in {@code + * requireMemory}. + * + * @param bytes needed bytes. + * @param requestingPool the memoryPool that requests this allocation. + * @return the memory size that upper manager can provide. + * @throws OutOfMemoryException if there isn't enough memory in manager. + */ long requestMemoryInternal(long bytes, MemoryPool requestingPool) throws OutOfMemoryException; + /** + * Request allocator for a real allocation. This method is used internal in {@code + * requireMemory}. + * + * @param bytes needed bytes. + * @return memory block. ByteBuf if using off-heap, byte[] if using on-heap. + */ Object tryToAcquireMemoryInternal(long bytes); /** * Release all self's resources. Called by user or called automatically by itself when OOM. * - * @param reason: release reason, for logging. - * @param isTriggeredInternal: if true, it is called automatically. if false, called by user. + * @param reason release reason, for logging. + * @param isTriggeredByOOM if true, it is called when OOM. if false, called by user. */ - void releaseSelf(String reason, boolean isTriggeredInternal); + void releaseSelf(String reason, boolean isTriggeredByOOM); /** * Called by `releaseSelf` to release children's resource. diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index 98da093156..472a231a15 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -54,8 +54,8 @@ public void bindMemoryConsumer(OffHeapObject offHeapObject) { } @Override - public void releaseSelf(String reason, boolean isTriggeredInternal) { - super.releaseSelf(reason, isTriggeredInternal); + public void releaseSelf(String reason, boolean isTriggeredByOOM) { + super.releaseSelf(reason, isTriggeredByOOM); // since it is already closed, its stats will not be updated. so here we can use its // stats out of memoryActionLock. this.memoryAllocator.returnMemoryToManager(getUsedBytes()); @@ -127,10 +127,10 @@ public Object requireMemory(long bytes, MemoryPool requestingPool) { // if free memory is enough, use free memory directly. if (getFreeBytes() >= bytes) { LOG.debug("[{}] require {} bytes, there is enough free memory {} bytes, will " + - "require memory directly from self's free memory.", - this, - getFreeBytes(), - bytes); + "require memory directly from self's free memory.", + this, + getFreeBytes(), + bytes); } else { // if free memory is not enough, try to request delta long delta = bytes - getFreeBytes(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index ffc97de0f7..3787e27444 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -57,8 +57,8 @@ public long tryToReclaimLocalMemory(long neededBytes, MemoryPool requestingPool) } @Override - public void releaseSelf(String reason, boolean isTriggeredInternal) { - super.releaseSelf(reason, isTriggeredInternal); + public void releaseSelf(String reason, boolean isTriggeredByOOM) { + super.releaseSelf(reason, isTriggeredByOOM); this.memoryManager.removeCorrespondingTaskMemoryPool(Thread.currentThread().getName()); } From 5e47bb0565ab3732d4461eb5f6506544dd0e2fef Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 16:39:56 +0800 Subject: [PATCH 40/48] add private constructor for singleton --- .../apache/hugegraph/memory/consumer/factory/IdFactory.java | 4 ++++ .../hugegraph/memory/consumer/factory/PropertyFactory.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java index c3e67ddea1..7bd4495a7c 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java @@ -43,6 +43,10 @@ public class IdFactory { private MemoryManager.MemoryMode memoryMode; + private IdFactory() { + // empty constructor + } + /** * If using off-heap mode, param id must be OffHeapObject */ diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java index 7ac0431731..a648e82b13 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java @@ -34,6 +34,10 @@ public class PropertyFactory { private MemoryManager.MemoryMode memoryMode; + private PropertyFactory() { + // empty constructor + } + public HugeEdgeProperty newHugeEdgeProperty(HugeElement owner, PropertyKey key, V value) { switch (memoryMode) { From b77346ba24821fdd0863ce9aab1b3962e8bca9da Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 17:05:36 +0800 Subject: [PATCH 41/48] add memory management config --- .../apache/hugegraph/StandardHugeGraph.java | 13 +++++++-- .../apache/hugegraph/config/CoreOptions.java | 29 +++++++++++++++++++ .../hugegraph/memory/MemoryManager.java | 24 +++++++++------ .../memory/consumer/factory/IdFactory.java | 2 +- .../consumer/factory/PropertyFactory.java | 2 +- .../memory/pool/impl/QueryMemoryPool.java | 5 ++-- .../hugegraph/memory/util/RoundUtil.java | 9 ++++-- .../static/conf/graphs/hugegraph.properties | 6 ++++ .../core/memory/MemoryConsumerTest.java | 5 ++++ .../core/memory/MemoryManageTest.java | 2 +- 10 files changed, 77 insertions(+), 20 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/StandardHugeGraph.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/StandardHugeGraph.java index 6480d7f288..eb991c0f68 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/StandardHugeGraph.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/StandardHugeGraph.java @@ -70,6 +70,8 @@ import org.apache.hugegraph.masterelection.RoleElectionStateMachine; import org.apache.hugegraph.masterelection.StandardClusterRoleStore; import org.apache.hugegraph.masterelection.StandardRoleElectionStateMachine; +import org.apache.hugegraph.memory.MemoryManager; +import org.apache.hugegraph.memory.util.RoundUtil; import org.apache.hugegraph.meta.MetaManager; import org.apache.hugegraph.perf.PerfUtil.Watched; import org.apache.hugegraph.rpc.RpcServiceConfig4Client; @@ -215,6 +217,13 @@ public StandardHugeGraph(HugeConfig config) { this.readMode = GraphReadMode.OLTP_ONLY; this.schedulerType = config.get(CoreOptions.SCHEDULER_TYPE); + MemoryManager.setMemoryMode( + MemoryManager.MemoryMode.fromValue(config.get(CoreOptions.MEMORY_MODE))); + MemoryManager.setMaxMemoryCapacityInBytes(config.get(CoreOptions.MAX_MEMORY_CAPACITY)); + MemoryManager.setMaxMemoryCapacityForOneQuery( + config.get(CoreOptions.ONE_QUERY_MAX_MEMORY_CAPACITY)); + RoundUtil.setAlignment(config.get(CoreOptions.MEMORY_ALIGNMENT)); + LockUtil.init(this.name); try { @@ -477,8 +486,8 @@ private ISchemaTransaction openSchemaTransaction() throws HugeException { try { if (isHstore()) { return new CachedSchemaTransactionV2( - MetaManager.instance().metaDriver(), - MetaManager.instance().cluster(), this.params); + MetaManager.instance().metaDriver(), + MetaManager.instance().cluster(), this.params); } return new CachedSchemaTransaction(this.params, loadSchemaStore()); } catch (BackendException e) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/config/CoreOptions.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/config/CoreOptions.java index 21054902c2..2bfbedd2ae 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/config/CoreOptions.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/config/CoreOptions.java @@ -20,6 +20,7 @@ import static org.apache.hugegraph.backend.tx.GraphTransaction.COMMIT_BATCH; import static org.apache.hugegraph.config.OptionChecker.allowValues; import static org.apache.hugegraph.config.OptionChecker.disallowEmpty; +import static org.apache.hugegraph.config.OptionChecker.nonNegativeInt; import static org.apache.hugegraph.config.OptionChecker.positiveInt; import static org.apache.hugegraph.config.OptionChecker.rangeInt; @@ -681,4 +682,32 @@ public static synchronized CoreOptions instance() { disallowEmpty(), "127.0.0.1:8686" ); + + public static final ConfigOption MEMORY_MODE = new ConfigOption<>( + "memory.mode", + "The memory mode used for query in HugeGraph.", + disallowEmpty(), + "off-heap" + ); + + public static final ConfigOption MAX_MEMORY_CAPACITY = new ConfigOption<>( + "memory.max_capacity", + "The maximum memory capacity that can be managed for all queries in HugeGraph.", + nonNegativeInt(), + Bytes.GB + ); + + public static final ConfigOption ONE_QUERY_MAX_MEMORY_CAPACITY = new ConfigOption<>( + "memory.one_query_max_capacity", + "The maximum memory capacity that can be managed for a query in HugeGraph.", + nonNegativeInt(), + Bytes.MB * 100 + ); + + public static final ConfigOption MEMORY_ALIGNMENT = new ConfigOption<>( + "memory.alignment", + "The alignment used for round memory size.", + nonNegativeInt(), + 8L + ); } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java index 74ce357e4a..b2ac195e3e 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/MemoryManager.java @@ -30,7 +30,6 @@ import org.apache.hugegraph.memory.arbitrator.MemoryArbitrator; import org.apache.hugegraph.memory.arbitrator.MemoryArbitratorImpl; -import org.apache.hugegraph.memory.consumer.factory.IdFactory; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.pool.impl.QueryMemoryPool; import org.apache.hugegraph.memory.pool.impl.TaskMemoryPool; @@ -62,8 +61,8 @@ public class MemoryManager { private static final String ARBITRATE_MEMORY_POOL_NAME = "ArbitrateMemoryPool"; public static final String DELIMINATOR = "_"; - // TODO: read it from conf, current 1G - public static final long MAX_MEMORY_CAPACITY_IN_BYTES = Bytes.GB; + public static long MAX_MEMORY_CAPACITY_IN_BYTES = Bytes.GB; + public static long MAX_MEMORY_CAPACITY_FOR_ONE_QUERY = Bytes.MB * 100; // Current available memory = MAX_MEMORY_CAPACITY - sum(allocated bytes) private final AtomicLong currentAvailableMemoryInBytes = new AtomicLong(MAX_MEMORY_CAPACITY_IN_BYTES); @@ -78,7 +77,7 @@ public class MemoryManager { private final MemoryArbitrator memoryArbitrator; private final ExecutorService arbitrateExecutor; - private MemoryMode memoryMode; + private static MemoryMode MEMORY_MODE = MemoryMode.ENABLE_OFF_HEAP_MANAGEMENT; private MemoryManager() { this.memoryArbitrator = new MemoryArbitratorImpl(this); @@ -188,13 +187,20 @@ public AtomicLong getCurrentOffHeapAllocatedMemoryInBytes() { return currentOffHeapAllocatedMemoryInBytes; } - // TODO: read it from conf - public void setMemoryMode(MemoryMode conf) { - memoryMode = conf; + public static void setMemoryMode(MemoryMode conf) { + MEMORY_MODE = conf; } - public MemoryMode getMemoryMode() { - return memoryMode; + public static MemoryMode getMemoryMode() { + return MEMORY_MODE; + } + + public static void setMaxMemoryCapacityInBytes(long maxMemoryCapacityInBytes) { + MAX_MEMORY_CAPACITY_IN_BYTES = maxMemoryCapacityInBytes; + } + + public static void setMaxMemoryCapacityForOneQuery(long maxMemoryCapacityForOneQuery) { + MAX_MEMORY_CAPACITY_FOR_ONE_QUERY = maxMemoryCapacityForOneQuery; } @TestOnly diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java index 7bd4495a7c..976b9cb373 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/IdFactory.java @@ -321,7 +321,7 @@ private IdFactoryHolder() { public static IdFactory getInstance() { IdFactory instance = IdFactoryHolder.INSTANCE; if (instance.memoryMode == null) { - instance.memoryMode = MemoryManager.getInstance().getMemoryMode(); + instance.memoryMode = MemoryManager.getMemoryMode(); } return IdFactoryHolder.INSTANCE; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java index a648e82b13..c628155eb1 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/consumer/factory/PropertyFactory.java @@ -87,7 +87,7 @@ public static PropertyFactory getInstance(Class clazz) { PropertyFactory instance = (PropertyFactory) PropertyFactoryHolder.FACTORIES_MAP .computeIfAbsent(clazz, k -> new PropertyFactory<>()); if (instance.memoryMode == null) { - instance.memoryMode = MemoryManager.getInstance().getMemoryMode(); + instance.memoryMode = MemoryManager.getMemoryMode(); } return instance; } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 291c978098..df14f1a738 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -18,6 +18,7 @@ package org.apache.hugegraph.memory.pool.impl; import static org.apache.hugegraph.memory.MemoryManager.DELIMINATOR; +import static org.apache.hugegraph.memory.MemoryManager.MAX_MEMORY_CAPACITY_FOR_ONE_QUERY; import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.AbstractMemoryPool; @@ -33,12 +34,10 @@ public class QueryMemoryPool extends AbstractMemoryPool { private static final String TASK_MEMORY_POOL_NAME_PREFIX = "TaskMemoryPool"; private static final String EXPAND_SELF = "expand self's max capacity"; private static final String REQUEST_MEMORY = "request to allocate memory"; - // TODO: read from conf - private static final long QUERY_POOL_MAX_CAPACITY = Bytes.MB * 100; public QueryMemoryPool(String poolName, MemoryManager memoryManager) { super(null, poolName, MemoryPoolStats.MemoryPoolType.QUERY, memoryManager); - this.stats.setMaxCapacity(QUERY_POOL_MAX_CAPACITY); + this.stats.setMaxCapacity(MAX_MEMORY_CAPACITY_FOR_ONE_QUERY); } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/RoundUtil.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/RoundUtil.java index b81cd42849..6f6b3aba82 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/RoundUtil.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/util/RoundUtil.java @@ -17,10 +17,13 @@ package org.apache.hugegraph.memory.util; public class RoundUtil { - - // TODO: configurable - private static final long ALIGNMENT = 8; + private static final long MB = 1 << 20; + private static long ALIGNMENT = 8; + + public static void setAlignment(long alignment) { + ALIGNMENT = alignment; + } public static long sizeAlign(long size) { long reminder = size % ALIGNMENT; diff --git a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties index 52c81bef1d..b879d190a4 100644 --- a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties +++ b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties @@ -88,3 +88,9 @@ cassandra.password= # WARNING: These raft configurations are deprecated, please use the latest version instead. # raft.mode=false + +# memory management config +#memory.mode=off-heap +#memory.max_capacity=1073741824 +#memory.one_query_max_capacity=104857600 +#memory.alignment=8 diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java index b3a83d0e50..89096c287e 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java @@ -105,6 +105,11 @@ public static void clear() throws Exception { } } + @Test + public void test() { + + } + @Test public void testStringId() { Id stringIdOffHeap = IdFactory.getInstance().newStringId("java"); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java index 3851e0e41a..a508d26e5e 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java @@ -69,7 +69,7 @@ public class MemoryManageTest { @Before public void setUp() { memoryManager = MemoryManager.getInstance(); - memoryManager.setMemoryMode(MemoryManager.MemoryMode.ENABLE_OFF_HEAP_MANAGEMENT); + MemoryManager.setMemoryMode(MemoryManager.MemoryMode.ENABLE_OFF_HEAP_MANAGEMENT); query1MemoryPool = memoryManager.addQueryMemoryPool(); query2MemoryPool = memoryManager.addQueryMemoryPool(); From d00a8dfb5cefcb9f01373b827a29718bd87cadd0 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 17:17:59 +0800 Subject: [PATCH 42/48] improve robustness --- .../org/apache/hugegraph/core/memory/MemoryManageTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java index a508d26e5e..4855c09582 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryManageTest.java @@ -20,6 +20,7 @@ import org.apache.hugegraph.memory.MemoryManager; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.pool.impl.TaskMemoryPool; +import org.apache.hugegraph.memory.util.RoundUtil; import org.apache.hugegraph.testutil.Assert; import org.apache.hugegraph.util.Bytes; import org.junit.After; @@ -70,6 +71,9 @@ public class MemoryManageTest { public void setUp() { memoryManager = MemoryManager.getInstance(); MemoryManager.setMemoryMode(MemoryManager.MemoryMode.ENABLE_OFF_HEAP_MANAGEMENT); + MemoryManager.setMaxMemoryCapacityInBytes(Bytes.GB); + MemoryManager.setMaxMemoryCapacityForOneQuery(Bytes.MB * 100); + RoundUtil.setAlignment(8); query1MemoryPool = memoryManager.addQueryMemoryPool(); query2MemoryPool = memoryManager.addQueryMemoryPool(); From fecc9095f9c4b84e9113d0860e4985f9856a030f Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 17:18:58 +0800 Subject: [PATCH 43/48] remove duplicate --- .../org/apache/hugegraph/core/memory/MemoryConsumerTest.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java index 89096c287e..b3a83d0e50 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/memory/MemoryConsumerTest.java @@ -105,11 +105,6 @@ public static void clear() throws Exception { } } - @Test - public void test() { - - } - @Test public void testStringId() { Id stringIdOffHeap = IdFactory.getInstance().newStringId("java"); From 31f1febc081ad7009c53b08bca82cd48c1a26ef1 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 21:50:17 +0800 Subject: [PATCH 44/48] improve condition usage --- .../apache/hugegraph/memory/pool/impl/QueryMemoryPool.java | 4 +++- .../org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index df14f1a738..482961825a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -24,7 +24,6 @@ import org.apache.hugegraph.memory.pool.AbstractMemoryPool; import org.apache.hugegraph.memory.pool.MemoryPool; import org.apache.hugegraph.memory.util.RoundUtil; -import org.apache.hugegraph.util.Bytes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,6 +71,7 @@ public long requestMemoryInternal(long bytes, MemoryPool requestingPool) { } long requestedMemoryFromManager = 0; long requestedMemoryFromArbitration = 0; + memoryActionLock.lock(); try { if (this.isBeingArbitrated.get()) { this.condition.await(); @@ -113,6 +113,8 @@ public long requestMemoryInternal(long bytes, MemoryPool requestingPool) { LOG.error("[{}] Failed to request memory because ", this, e); Thread.currentThread().interrupt(); return 0; + } finally { + memoryActionLock.unlock(); } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index 3787e27444..5c32d98755 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -91,6 +91,7 @@ public long requestMemoryInternal(long bytes, MemoryPool requestingPool) throws LOG.warn("[{}] is already closed, will abort this request", this); return 0; } + memoryActionLock.lock(); try { if (this.isBeingArbitrated.get()) { this.condition.await(); @@ -105,7 +106,8 @@ public long requestMemoryInternal(long bytes, MemoryPool requestingPool) throws LOG.error("Failed to release self because ", e); Thread.currentThread().interrupt(); return 0; + } finally { + memoryActionLock.unlock(); } - } } From d4035bdc17d5c4fd6175ae2774bf4a32f9826d6f Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 21:57:16 +0800 Subject: [PATCH 45/48] improve log --- .../hugegraph/memory/pool/AbstractMemoryPool.java | 6 +++--- .../memory/pool/impl/OperatorMemoryPool.java | 13 ++++++------- .../hugegraph/memory/pool/impl/QueryMemoryPool.java | 7 +++++-- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 006af6e5d8..8970f2af98 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -106,9 +106,9 @@ private long reclaimChildren(long neededBytes, MemoryPool requestingPool) { } } LOG.info("[{}] has finished to reclaim memory: totalReclaimedBytes={}, " + - "neededBytes={}", + "neededBytes={}, snapshot-[{}]", this, - totalReclaimedBytes, neededBytes); + totalReclaimedBytes, neededBytes, this.getSnapShot()); return totalReclaimedBytes; } @@ -224,7 +224,7 @@ public String getName() { @Override public String toString() { - return getSnapShot().toString(); + return this.getName(); } @Override diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index 472a231a15..d909536d58 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -90,19 +90,18 @@ public long tryToReclaimLocalMemory(long neededBytes, MemoryPool requestingPool) LOG.info("[{}] has tried its best to reclaim memory: " + "reclaimedBytes={}," + " " + - "neededBytes={}", + "neededBytes={}, snapshot-[{}]", this, - reclaimableBytes, neededBytes); + reclaimableBytes, neededBytes, this.getSnapShot()); return reclaimableBytes; } stats.setAllocatedBytes(stats.getAllocatedBytes() - neededBytes); LOG.info("[{}] has reclaim enough memory: " + "reclaimedBytes={}," + " " + - "neededBytes={}", + "neededBytes={}, snapshot-[{}]", this, - neededBytes, neededBytes); - + neededBytes, neededBytes, this.getSnapShot()); return neededBytes; } finally { if (reclaimableBytes > 0) { @@ -140,8 +139,8 @@ public Object requireMemory(long bytes, MemoryPool requestingPool) { } catch (OutOfMemoryException e) { // Abort this query LOG.warn("[{}] detected an OOM exception when request memory, will ABORT this " + - "query and release corresponding memory...", - this); + "query and release corresponding memory... snapshot-[{}]", + this, this.getSnapShot()); findRootQueryPool().releaseSelf(String.format(e.getMessage()), true); return null; } finally { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 482961825a..25181e18a2 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -127,8 +127,11 @@ private long tryToExpandSelfCapacity(long size) { } private long requestMemoryThroughArbitration(long bytes, MemoryPool requestingPool) { - LOG.info("[{}] try to request memory from manager through arbitration: size={}", this, - bytes); + LOG.info("[{}] try to request memory from manager through arbitration: size={}, " + + "snapshot-[{}]", + this, + bytes, + this.getSnapShot()); long reclaimedBytes = this.memoryManager.triggerLocalArbitration(this, bytes, requestingPool); if (reclaimedBytes > 0) { From d87388b8060ab696d0c32a90298b18f04ee34261 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Tue, 29 Oct 2024 22:41:19 +0800 Subject: [PATCH 46/48] fix memory conservation bug --- .../arbitrator/MemoryArbitratorImpl.java | 4 ++-- .../memory/pool/AbstractMemoryPool.java | 12 ++++++---- .../hugegraph/memory/pool/MemoryPool.java | 2 -- .../memory/pool/impl/OperatorMemoryPool.java | 11 +++++++-- .../memory/pool/impl/QueryMemoryPool.java | 24 +++++++++---------- .../memory/pool/impl/TaskMemoryPool.java | 6 +++++ 6 files changed, 36 insertions(+), 23 deletions(-) diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java index e5198c3638..d8ce73afde 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/arbitrator/MemoryArbitratorImpl.java @@ -38,7 +38,7 @@ public long reclaimLocally(MemoryPool queryPool, long neededBytes, MemoryPool re long startTime = System.currentTimeMillis(); long res = queryPool.tryToReclaimLocalMemory(neededBytes, requestingPool); LOG.info("[{}] reclaim local memory: {} bytes, took {} ms", - Thread.currentThread().getName(), + queryPool, res, System.currentTimeMillis() - startTime); return res; @@ -65,7 +65,7 @@ public long reclaimGlobally(MemoryPool queryPool, long neededBytes) { } } LOG.info("[{}] reclaim global memory: {} bytes, took {} ms", - Thread.currentThread().getName(), + queryPool, totalReclaimedBytes, System.currentTimeMillis() - startTime); return totalReclaimedBytes; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java index 8970f2af98..29b951c262 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/AbstractMemoryPool.java @@ -94,6 +94,9 @@ private long reclaimChildren(long neededBytes, MemoryPool requestingPool) { long totalReclaimedBytes = 0; long currentNeededBytes = neededBytes; for (MemoryPool child : this.children) { + if (child.equals(requestingPool)) { + continue; + } long reclaimedMemory = child.tryToReclaimLocalMemory(currentNeededBytes, requestingPool); if (reclaimedMemory > 0) { @@ -217,16 +220,15 @@ public MemoryPool getParentPool() { return this.parent; } - @Override - public String getName() { - return this.stats.getMemoryPoolName(); - } - @Override public String toString() { return this.getName(); } + public String getName() { + return this.stats.getMemoryPoolName(); + } + @Override public MemoryPool findRootQueryPool() { if (this.parent == null) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java index 1e8f68a131..74c364febb 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/MemoryPool.java @@ -92,8 +92,6 @@ public interface MemoryPool { long getMaxCapacityBytes(); - String getName(); - MemoryPool getParentPool(); MemoryPool findRootQueryPool(); diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java index d909536d58..af9121ee46 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/OperatorMemoryPool.java @@ -189,16 +189,23 @@ public long requestMemoryInternal(long size, MemoryPool requestingPool) throws // 3. call father long fatherRes = getParentPool().requestMemoryInternal(neededMemorySize, requestingPool); - if (fatherRes < 0) { + if (fatherRes <= 0) { LOG.error("[{}] requestMemory failed because of OOM, request size={}", this, size); + // if parentRes <= 0, indicating we don't get enough memory bytes. + // But we still need to allocate these memory bytes to operatorPool to ensure + // memory is conserved when parentRes < 0 + if (fatherRes < 0) { + this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() - fatherRes); + this.stats.setNumExpands(this.stats.getNumExpands() + 1); + } this.stats.setNumAborts(this.stats.getNumAborts() + 1); throw new OutOfMemoryException(String.format("%s requestMemory failed " + "because of OOM, request " + "size=%s", this, size)); } // 4. update stats - this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + neededMemorySize); + this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + fatherRes); this.stats.setNumExpands(this.stats.getNumExpands() + 1); LOG.debug("[{}] requestMemory success: requestedMemorySize={}", this, fatherRes); return fatherRes; diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java index 25181e18a2..4d6e492461 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/QueryMemoryPool.java @@ -105,7 +105,7 @@ public long requestMemoryInternal(long bytes, MemoryPool requestingPool) { } } if (requestedMemoryFromManager > 0) { - this.memoryManager.consumeAvailableMemory(bytes); + this.memoryManager.consumeAvailableMemory(requestedMemoryFromManager); } return requestedMemoryFromManager == 0 ? requestedMemoryFromArbitration : requestedMemoryFromManager; @@ -134,30 +134,30 @@ private long requestMemoryThroughArbitration(long bytes, MemoryPool requestingPo this.getSnapShot()); long reclaimedBytes = this.memoryManager.triggerLocalArbitration(this, bytes, requestingPool); - if (reclaimedBytes > 0) { - this.stats.setNumExpands(this.stats.getNumExpands() + 1); - } // 1. if arbitrate successes, update stats and return success if (reclaimedBytes - bytes >= 0) { // here we don't update capacity & reserved & allocated, because memory is // reclaimed from queryPool itself. - return bytes; + return reclaimedBytes; } else { // 2. if still not enough, try to reclaim globally long globalArbitrationNeededBytes = bytes - reclaimedBytes; long globalReclaimedBytes = this.memoryManager.triggerGlobalArbitration(this, globalArbitrationNeededBytes); reclaimedBytes += globalReclaimedBytes; - // 3. if memory is enough, update stats and return success - if (reclaimedBytes - bytes >= 0) { - // add capacity + // add capacity whether arbitration failed or not. + // NOTE: only bytes gained from global arbitration can be added to stats. + if (globalReclaimedBytes != 0) { this.stats.setMaxCapacity(this.stats.getMaxCapacity() + globalReclaimedBytes); - this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + bytes); + this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + globalReclaimedBytes); this.stats.setNumExpands(this.stats.getNumExpands() + 1); - return bytes; + } + // 3. if memory is enough, update stats and return success + if (reclaimedBytes - bytes >= 0) { + return reclaimedBytes; } } - // 4. if arbitrate fails, return -1, indicating that request failed. - return -1; + // 4. if arbitrate fails, return -reclaimedBytes, indicating that request failed. + return -reclaimedBytes; } } diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java index 5c32d98755..813f2820bc 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/memory/pool/impl/TaskMemoryPool.java @@ -100,6 +100,12 @@ public long requestMemoryInternal(long bytes, MemoryPool requestingPool) throws if (parentRes > 0) { this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() + parentRes); this.stats.setNumExpands(this.stats.getNumExpands() + 1); + } else if (parentRes < 0){ + // if parentRes < 0, indicating we don't get enough memory bytes. But we still + // need to allocate these memory bytes to operatorPool to ensure memory is + // conserved. + this.stats.setAllocatedBytes(this.stats.getAllocatedBytes() - parentRes); + this.stats.setNumExpands(this.stats.getNumExpands() + 1); } return parentRes; } catch (InterruptedException e) { From d25396dc778060fde3a3d665532bef3196c6e454 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Mon, 4 Nov 2024 19:48:16 +0800 Subject: [PATCH 47/48] Revert "dependency" This reverts commit 7c86e84580f989bc9101a92abda089427f5dba12. --- .../scripts/dependency/known-dependencies.txt | 32 +------------------ .../scripts/dependency/known-dependencies.txt | 29 ++++++++--------- 2 files changed, 15 insertions(+), 46 deletions(-) diff --git a/hugegraph-commons/hugegraph-dist/scripts/dependency/known-dependencies.txt b/hugegraph-commons/hugegraph-dist/scripts/dependency/known-dependencies.txt index 5db5f373f8..9a421edcd4 100644 --- a/hugegraph-commons/hugegraph-dist/scripts/dependency/known-dependencies.txt +++ b/hugegraph-commons/hugegraph-dist/scripts/dependency/known-dependencies.txt @@ -1,7 +1,4 @@ -animal-sniffer-annotations-1.18.jar annotations-13.0.jar -annotations-4.1.1.4.jar -bolt-1.6.2.jar checker-qual-3.5.0.jar commons-beanutils-1.9.4.jar commons-codec-1.13.jar @@ -13,25 +10,14 @@ commons-lang-2.6.jar commons-lang3-3.12.0.jar commons-logging-1.1.1.jar commons-text-1.9.jar -disruptor-3.3.7.jar error_prone_annotations-2.3.4.jar failureaccess-1.0.1.jar -grpc-api-1.28.1.jar -grpc-context-1.28.1.jar -grpc-core-1.28.1.jar -grpc-netty-shaded-1.28.0.jar -grpc-protobuf-1.28.0.jar -grpc-protobuf-lite-1.28.0.jar -grpc-stub-1.28.0.jar -gson-2.8.6.jar guava-30.0-jre.jar hamcrest-core-1.3.jar -hessian-3.3.7.jar j2objc-annotations-1.3.jar jackson-annotations-2.14.0-rc1.jar jackson-core-2.14.0-rc1.jar jackson-databind-2.14.0-rc1.jar -jackson-dataformat-yaml-2.9.3.jar jackson-jaxrs-base-2.14.0-rc1.jar jackson-jaxrs-json-provider-2.14.0-rc1.jar jackson-module-jaxb-annotations-2.14.0-rc1.jar @@ -53,23 +39,7 @@ log4j-api-2.18.0.jar log4j-core-2.18.0.jar log4j-slf4j-impl-2.18.0.jar logging-interceptor-4.10.0.jar -lookout-api-1.4.1.jar -netty-all-4.1.42.Final.jar +lombok-1.18.8.jar okhttp-4.10.0.jar okio-jvm-3.0.0.jar -opentracing-api-0.22.0.jar -opentracing-mock-0.22.0.jar -opentracing-noop-0.22.0.jar -opentracing-util-0.22.0.jar -perfmark-api-0.19.0.jar -proto-google-common-protos-1.17.0.jar -protobuf-java-3.11.0.jar slf4j-api-1.7.25.jar -snakeyaml-1.18.jar -sofa-common-tools-1.0.12.jar -sofa-rpc-all-5.7.6.jar -swagger-annotations-1.5.18.jar -swagger-core-1.5.18.jar -swagger-models-1.5.18.jar -tracer-core-3.0.8.jar -validation-api-1.1.0.Final.jar diff --git a/install-dist/scripts/dependency/known-dependencies.txt b/install-dist/scripts/dependency/known-dependencies.txt index 36255a96eb..02b5dda11a 100644 --- a/install-dist/scripts/dependency/known-dependencies.txt +++ b/install-dist/scripts/dependency/known-dependencies.txt @@ -1,7 +1,3 @@ -HdrHistogram-2.1.12.jar -HdrHistogram-2.1.9.jar -LatencyUtils-2.0.3.jar -ST4-4.0.8.jar accessors-smart-1.2.jar airline-0.8.jar android-json-0.0.20131108.vaadin1.jar @@ -91,7 +87,6 @@ fastparse_2.12-2.0.4.jar fastutil-8.5.9.jar findbugs-annotations-1.3.9-1.jar front-end-9.0-9.0.20190305.jar -fury-core-0.9.0-SNAPSHOT.jar gremlin-console-3.5.1.jar gremlin-core-3.5.1.jar gremlin-driver-3.5.1.jar @@ -147,6 +142,8 @@ hamcrest-2.2.jar hamcrest-core-1.3.jar hanlp-portable-1.8.3.jar hbase-shaded-endpoint-2.0.6.jar +HdrHistogram-2.1.12.jar +HdrHistogram-2.1.9.jar hessian-3.3.6.jar hessian-3.3.7.jar hg-pd-client-1.5.0.jar @@ -217,12 +214,12 @@ javassist-3.21.0-GA.jar javassist-3.24.0-GA.jar javassist-3.28.0-GA.jar javatuples-1.2.jar -javax-websocket-client-impl-9.4.46.v20220331.jar -javax-websocket-server-impl-9.4.46.v20220331.jar javax.activation-api-1.2.0.jar javax.annotation-api-1.3.2.jar javax.inject-1.jar javax.json-1.0.jar +javax-websocket-client-impl-9.4.46.v20220331.jar +javax-websocket-server-impl-9.4.46.v20220331.jar jaxb-api-2.3.1.jar jaxb-core-3.0.2.jar jaxb-impl-3.0.2.jar @@ -265,8 +262,8 @@ jetty-util-9.4.46.v20220331.jar jetty-util-ajax-9.4.46.v20220331.jar jetty-webapp-9.4.46.v20220331.jar jetty-xml-9.4.46.v20220331.jar -jffi-1.2.16-native.jar jffi-1.2.16.jar +jffi-1.2.16-native.jar jflex-1.8.2.jar jieba-analysis-1.0.2.jar jjwt-api-0.11.5.jar @@ -283,10 +280,10 @@ jraft-core-1.3.11.jar jraft-core-1.3.13.jar jraft-core-1.3.9.jar json-20210307.jar +jsonassert-1.5.0.jar json-path-2.5.0.jar json-simple-1.1.jar json-smart-2.3.jar -jsonassert-1.5.0.jar jsr305-3.0.1.jar jsr305-3.0.2.jar jul-to-slf4j-1.7.36.jar @@ -317,6 +314,7 @@ kotlin-stdlib-1.6.20.jar kotlin-stdlib-common-1.5.31.jar kotlin-stdlib-jdk7-1.6.10.jar kotlin-stdlib-jdk8-1.6.10.jar +LatencyUtils-2.0.3.jar listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar log4j-api-2.15.0.jar log4j-api-2.17.0.jar @@ -366,10 +364,10 @@ netty-buffer-4.1.52.Final.jar netty-buffer-4.1.72.Final.jar netty-codec-4.1.52.Final.jar netty-codec-4.1.72.Final.jar -netty-codec-http-4.1.52.Final.jar -netty-codec-http-4.1.72.Final.jar netty-codec-http2-4.1.52.Final.jar netty-codec-http2-4.1.72.Final.jar +netty-codec-http-4.1.52.Final.jar +netty-codec-http-4.1.72.Final.jar netty-codec-socks-4.1.52.Final.jar netty-codec-socks-4.1.72.Final.jar netty-common-4.1.52.Final.jar @@ -417,20 +415,20 @@ powermock-module-junit4-2.0.0-RC.3.jar powermock-module-junit4-common-2.0.0-RC.3.jar powermock-module-junit4-rule-2.0.0-RC.3.jar powermock-reflect-2.0.0-RC.3.jar -proto-google-common-protos-1.17.0.jar -proto-google-common-protos-2.0.1.jar protobuf-java-3.11.0.jar protobuf-java-3.17.2.jar protobuf-java-3.21.7.jar protobuf-java-3.5.1.jar protobuf-java-util-3.17.2.jar +proto-google-common-protos-1.17.0.jar +proto-google-common-protos-2.0.1.jar protostuff-api-1.6.0.jar protostuff-collectionschema-1.6.0.jar protostuff-core-1.6.0.jar protostuff-runtime-1.6.0.jar psjava-0.1.19.jar -reporter-config-base-3.0.3.jar reporter-config3-3.0.3.jar +reporter-config-base-3.0.3.jar rewriting-9.0-9.0.20190305.jar rocksdbjni-6.29.5.jar rocksdbjni-7.2.2.jar @@ -447,9 +445,9 @@ sjk-cli-0.22.jar sjk-core-0.14.jar sjk-core-0.22.jar sjk-hflame-0.22.jar -sjk-jfr-standalone-0.7.jar sjk-jfr5-0.5.jar sjk-jfr6-0.7.jar +sjk-jfr-standalone-0.7.jar sjk-json-0.14.jar sjk-json-0.22.jar sjk-nps-0.9.jar @@ -493,6 +491,7 @@ spring-expression-5.3.20.jar spring-jcl-5.3.20.jar spring-web-5.3.20.jar spring-webmvc-5.3.20.jar +ST4-4.0.8.jar stream-2.5.2.jar swagger-annotations-1.5.18.jar swagger-annotations-jakarta-2.2.18.jar From b334c61ce32539712a38d8df5bf1bea7a71b5445 Mon Sep 17 00:00:00 2001 From: Peng Junzhi <201250214@smail.nju.edu.cn> Date: Mon, 4 Nov 2024 19:49:45 +0800 Subject: [PATCH 48/48] revert duplicate known-dependencies.txt under huge-common --- .../scripts/dependency/known-dependencies.txt | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/install-dist/scripts/dependency/known-dependencies.txt b/install-dist/scripts/dependency/known-dependencies.txt index 02b5dda11a..36255a96eb 100644 --- a/install-dist/scripts/dependency/known-dependencies.txt +++ b/install-dist/scripts/dependency/known-dependencies.txt @@ -1,3 +1,7 @@ +HdrHistogram-2.1.12.jar +HdrHistogram-2.1.9.jar +LatencyUtils-2.0.3.jar +ST4-4.0.8.jar accessors-smart-1.2.jar airline-0.8.jar android-json-0.0.20131108.vaadin1.jar @@ -87,6 +91,7 @@ fastparse_2.12-2.0.4.jar fastutil-8.5.9.jar findbugs-annotations-1.3.9-1.jar front-end-9.0-9.0.20190305.jar +fury-core-0.9.0-SNAPSHOT.jar gremlin-console-3.5.1.jar gremlin-core-3.5.1.jar gremlin-driver-3.5.1.jar @@ -142,8 +147,6 @@ hamcrest-2.2.jar hamcrest-core-1.3.jar hanlp-portable-1.8.3.jar hbase-shaded-endpoint-2.0.6.jar -HdrHistogram-2.1.12.jar -HdrHistogram-2.1.9.jar hessian-3.3.6.jar hessian-3.3.7.jar hg-pd-client-1.5.0.jar @@ -214,12 +217,12 @@ javassist-3.21.0-GA.jar javassist-3.24.0-GA.jar javassist-3.28.0-GA.jar javatuples-1.2.jar +javax-websocket-client-impl-9.4.46.v20220331.jar +javax-websocket-server-impl-9.4.46.v20220331.jar javax.activation-api-1.2.0.jar javax.annotation-api-1.3.2.jar javax.inject-1.jar javax.json-1.0.jar -javax-websocket-client-impl-9.4.46.v20220331.jar -javax-websocket-server-impl-9.4.46.v20220331.jar jaxb-api-2.3.1.jar jaxb-core-3.0.2.jar jaxb-impl-3.0.2.jar @@ -262,8 +265,8 @@ jetty-util-9.4.46.v20220331.jar jetty-util-ajax-9.4.46.v20220331.jar jetty-webapp-9.4.46.v20220331.jar jetty-xml-9.4.46.v20220331.jar -jffi-1.2.16.jar jffi-1.2.16-native.jar +jffi-1.2.16.jar jflex-1.8.2.jar jieba-analysis-1.0.2.jar jjwt-api-0.11.5.jar @@ -280,10 +283,10 @@ jraft-core-1.3.11.jar jraft-core-1.3.13.jar jraft-core-1.3.9.jar json-20210307.jar -jsonassert-1.5.0.jar json-path-2.5.0.jar json-simple-1.1.jar json-smart-2.3.jar +jsonassert-1.5.0.jar jsr305-3.0.1.jar jsr305-3.0.2.jar jul-to-slf4j-1.7.36.jar @@ -314,7 +317,6 @@ kotlin-stdlib-1.6.20.jar kotlin-stdlib-common-1.5.31.jar kotlin-stdlib-jdk7-1.6.10.jar kotlin-stdlib-jdk8-1.6.10.jar -LatencyUtils-2.0.3.jar listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar log4j-api-2.15.0.jar log4j-api-2.17.0.jar @@ -364,10 +366,10 @@ netty-buffer-4.1.52.Final.jar netty-buffer-4.1.72.Final.jar netty-codec-4.1.52.Final.jar netty-codec-4.1.72.Final.jar -netty-codec-http2-4.1.52.Final.jar -netty-codec-http2-4.1.72.Final.jar netty-codec-http-4.1.52.Final.jar netty-codec-http-4.1.72.Final.jar +netty-codec-http2-4.1.52.Final.jar +netty-codec-http2-4.1.72.Final.jar netty-codec-socks-4.1.52.Final.jar netty-codec-socks-4.1.72.Final.jar netty-common-4.1.52.Final.jar @@ -415,20 +417,20 @@ powermock-module-junit4-2.0.0-RC.3.jar powermock-module-junit4-common-2.0.0-RC.3.jar powermock-module-junit4-rule-2.0.0-RC.3.jar powermock-reflect-2.0.0-RC.3.jar +proto-google-common-protos-1.17.0.jar +proto-google-common-protos-2.0.1.jar protobuf-java-3.11.0.jar protobuf-java-3.17.2.jar protobuf-java-3.21.7.jar protobuf-java-3.5.1.jar protobuf-java-util-3.17.2.jar -proto-google-common-protos-1.17.0.jar -proto-google-common-protos-2.0.1.jar protostuff-api-1.6.0.jar protostuff-collectionschema-1.6.0.jar protostuff-core-1.6.0.jar protostuff-runtime-1.6.0.jar psjava-0.1.19.jar -reporter-config3-3.0.3.jar reporter-config-base-3.0.3.jar +reporter-config3-3.0.3.jar rewriting-9.0-9.0.20190305.jar rocksdbjni-6.29.5.jar rocksdbjni-7.2.2.jar @@ -445,9 +447,9 @@ sjk-cli-0.22.jar sjk-core-0.14.jar sjk-core-0.22.jar sjk-hflame-0.22.jar +sjk-jfr-standalone-0.7.jar sjk-jfr5-0.5.jar sjk-jfr6-0.7.jar -sjk-jfr-standalone-0.7.jar sjk-json-0.14.jar sjk-json-0.22.jar sjk-nps-0.9.jar @@ -491,7 +493,6 @@ spring-expression-5.3.20.jar spring-jcl-5.3.20.jar spring-web-5.3.20.jar spring-webmvc-5.3.20.jar -ST4-4.0.8.jar stream-2.5.2.jar swagger-annotations-1.5.18.jar swagger-annotations-jakarta-2.2.18.jar