This is an automated email from the ASF dual-hosted git repository.
adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 41048fb57a9 HDDS-12563. Cache and reuse ContainerID object (#10642)
41048fb57a9 is described below
commit 41048fb57a9fb0a12688b5bf56fc004afdccf461
Author: Tsz-Wo Nicholas Sze <[email protected]>
AuthorDate: Thu Jul 2 10:24:03 2026 -0700
HDDS-12563. Cache and reuse ContainerID object (#10642)
---
.../hadoop/hdds/scm/container/ContainerID.java | 15 ++-
.../hadoop/hdds/scm/container/TestContainerID.java | 133 +++++++++++++++++++++
.../org/apache/ratis/util/RatisUtilTestUtil.java | 30 +++++
3 files changed, 176 insertions(+), 2 deletions(-)
diff --git
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerID.java
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerID.java
index ad7dec5fc4c..61ae9517069 100644
---
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerID.java
+++
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerID.java
@@ -27,6 +27,7 @@
import org.apache.hadoop.hdds.utils.db.DelegatedCodec;
import org.apache.hadoop.hdds.utils.db.LongCodec;
import org.apache.ratis.util.MemoizedSupplier;
+import org.apache.ratis.util.WeakValueCache;
/**
* Container ID is an integer that is a value between 1..MAX_CONTAINER ID.
@@ -42,7 +43,9 @@ public final class ContainerID implements
Comparable<ContainerID> {
LongCodec.get(), ContainerID::valueOf, c -> c.id,
ContainerID.class, DelegatedCodec.CopyType.SHALLOW);
- public static final ContainerID MIN = ContainerID.valueOf(0);
+ public static final ContainerID MIN = new ContainerID(0);
+ private static final WeakValueCache<Long, ContainerID> CACHE
+ = new WeakValueCache<>("containerId", ContainerID::new);
private final long id;
private final Supplier<HddsProtos.ContainerID> proto;
@@ -71,7 +74,11 @@ private ContainerID(long id) {
* @return ContainerID.
*/
public static ContainerID valueOf(final long containerID) {
- return new ContainerID(containerID);
+ return CACHE.getOrCreate(containerID);
+ }
+
+ static WeakValueCache<Long, ContainerID> getCacheForTesting() {
+ return CACHE;
}
/**
@@ -87,6 +94,10 @@ public long getId() {
return id;
}
+ public long getIdForTesting() {
+ return id;
+ }
+
public static byte[] getBytes(long id) {
return LongCodec.get().toPersistedFormat(id);
}
diff --git
a/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerID.java
b/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerID.java
new file mode 100644
index 00000000000..73ce557bd72
--- /dev/null
+++
b/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerID.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.hadoop.hdds.scm.container;
+
+import static org.apache.hadoop.hdds.utils.db.CodecTestUtil.gc;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import org.apache.ratis.util.JavaUtils;
+import org.apache.ratis.util.RatisUtilTestUtil;
+import org.apache.ratis.util.TimeDuration;
+import org.apache.ratis.util.WeakValueCache;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Test {@link ContainerID}. */
+public final class TestContainerID {
+ private static final Logger LOG =
LoggerFactory.getLogger(TestContainerID.class);
+
+ private static final WeakValueCache<Long, ContainerID> CACHE =
ContainerID.getCacheForTesting();
+
+ static String dumpCache() {
+ final List<ContainerID> values = RatisUtilTestUtil.getValues(CACHE);
+ values.sort(Comparator.comparing(ContainerID::getIdForTesting));
+ String header = CACHE + ": " + values.size();
+ System.out.println(header);
+ System.out.println(" " + values);
+ return header;
+ }
+
+ static void assertCache(IDs expectedIDs) {
+ final List<ContainerID> computed = RatisUtilTestUtil.getValues(CACHE);
+ computed.sort(Comparator.comparing(ContainerID::getIdForTesting));
+
+ final List<ContainerID> expected = expectedIDs.getIds();
+ expected.sort(Comparator.comparing(ContainerID::getIdForTesting));
+
+ assertEquals(expected, computed, TestContainerID::dumpCache);
+ }
+
+ void assertCacheSizeWithGC(IDs expectedIDs) throws Exception {
+ JavaUtils.attempt(() -> {
+ gc();
+ assertCache(expectedIDs);
+ }, 5, TimeDuration.valueOf(100, TimeUnit.MILLISECONDS),
"assertCacheSizeWithGC", LOG);
+ }
+
+ static class IDs {
+ private final List<ContainerID> ids = new LinkedList<>();
+
+ List<ContainerID> getIds() {
+ return new ArrayList<>(ids);
+ }
+
+ int size() {
+ return ids.size();
+ }
+
+ ContainerID allocate() {
+ final ContainerID id =
ContainerID.valueOf(ThreadLocalRandom.current().nextLong(Long.MAX_VALUE));
+ LOG.info("allocate {}", id);
+ ids.add(id);
+ return id;
+ }
+
+ void release() {
+ final int r = ThreadLocalRandom.current().nextInt(size());
+ final ContainerID removed = ids.remove(r);
+ LOG.info("release {}", removed);
+ }
+ }
+
+ @Test
+ public void testCaching() throws Exception {
+ final int n = 100;
+ final IDs ids = new IDs();
+ assertEquals(0, ids.size());
+ assertCache(ids);
+
+ for (int i = 0; i < n; i++) {
+ final ContainerID id = ids.allocate();
+ assertSame(id, ContainerID.valueOf(id.getIdForTesting()));
+ assertCache(ids);
+ }
+
+ for (int i = 0; i < n / 2; i++) {
+ ids.release();
+ if (ThreadLocalRandom.current().nextInt(10) == 0) {
+ assertCacheSizeWithGC(ids);
+ }
+ }
+ assertCacheSizeWithGC(ids);
+
+ for (int i = 0; i < n / 2; i++) {
+ final ContainerID id = ids.allocate();
+ assertSame(id, ContainerID.valueOf(id.getIdForTesting()));
+ assertCache(ids);
+ }
+
+
+ for (int i = 0; i < n; i++) {
+ ids.release();
+ if (ThreadLocalRandom.current().nextInt(10) == 0) {
+ assertCacheSizeWithGC(ids);
+ }
+ }
+ assertCacheSizeWithGC(ids);
+
+ assertEquals(0, ids.size());
+ }
+}
diff --git
a/hadoop-hdds/common/src/test/java/org/apache/ratis/util/RatisUtilTestUtil.java
b/hadoop-hdds/common/src/test/java/org/apache/ratis/util/RatisUtilTestUtil.java
new file mode 100644
index 00000000000..38ac252c7d0
--- /dev/null
+++
b/hadoop-hdds/common/src/test/java/org/apache/ratis/util/RatisUtilTestUtil.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.ratis.util;
+
+import java.util.List;
+
+/** Test util for the {@link org.apache.ratis.util} package. */
+public final class RatisUtilTestUtil {
+
+ private RatisUtilTestUtil() { }
+
+ public static <K, V> List<V> getValues(WeakValueCache<K, V> cache) {
+ return cache.getValues();
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]