From 8cce4872d742629c76f015c903d25db50c8e571e Mon Sep 17 00:00:00 2001 From: Manoel Campos Date: Tue, 20 Oct 2026 19:37:46 -0300 Subject: [PATCH] Measure the Cloudlet memory footprint in MemoryFootprintBenchmark Adds CloudletSimple to the memory benchmark, to measure the memory saved by cloudsimplus/cloudsimplus#587: listener lists and requiredFiles starting as the shared List.of(), and the shared UtilizationModel.FULL for the CPU. ListenersMemoryBenchmark is renamed to MemoryFootprintBenchmark and moved to the benchmarks package, since it measures the whole memory footprint of each VM, Host and Cloudlet, not only the listeners. Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 2 +- .../MemoryFootprintBenchmark.java} | 45 ++++++++++++------- 2 files changed, 31 insertions(+), 16 deletions(-) rename src/main/java/org/cloudsimplus/{listeners/ListenersMemoryBenchmark.java => benchmarks/MemoryFootprintBenchmark.java} (74%) diff --git a/CLAUDE.md b/CLAUDE.md index a410410..e2712d6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -30,7 +30,7 @@ java -jar target/cloudsimplus-benchmarks-8.5.1-uber.jar -l Alternative entry points (run from the IDE or with `exec`/`java -cp`): - `org.cloudsimplus.benchmarks.Run` runs every JMH benchmark matching `org.cloudsimplus.` with preset options (1 fork, 5 warmup, 25 measurement iterations, ms, 1 thread). - `org.cloudsimplus.benchmarks.SimulationTimeBenchmark` is a plain `main` (not JMH): it runs a full simulation several times, growing Hosts/VMs/Cloudlets each run, and prints execution time. -- `org.cloudsimplus.listeners.ListenersMemoryBenchmark` is a plain `main` (not JMH): it prints the heap retained by each VM and Host (run it with `-XX:+UseSerialGC`). To compare with CloudSim Plus 8.5.1 (before issue #586), build with `./mvnw clean package -Pcloudsimplus-8`, run it, then build without the profile and run it again (see its Javadoc). +- `org.cloudsimplus.benchmarks.MemoryFootprintBenchmark` is a plain `main` (not JMH): it prints the heap retained by each VM, Host and Cloudlet, i.e., their memory footprint (run it with `-XX:+UseSerialGC`). To compare with CloudSim Plus 8.5.1 (before issues #586 and #587), build with `./mvnw clean package -Pcloudsimplus-8`, run it, then build without the profile and run it again (see its Javadoc). There are no unit tests in this project. diff --git a/src/main/java/org/cloudsimplus/listeners/ListenersMemoryBenchmark.java b/src/main/java/org/cloudsimplus/benchmarks/MemoryFootprintBenchmark.java similarity index 74% rename from src/main/java/org/cloudsimplus/listeners/ListenersMemoryBenchmark.java rename to src/main/java/org/cloudsimplus/benchmarks/MemoryFootprintBenchmark.java index 560ab48..2595b3e 100644 --- a/src/main/java/org/cloudsimplus/listeners/ListenersMemoryBenchmark.java +++ b/src/main/java/org/cloudsimplus/benchmarks/MemoryFootprintBenchmark.java @@ -21,8 +21,9 @@ * You should have received a copy of the GNU General Public License * along with CloudSim Plus. If not, see . */ -package org.cloudsimplus.listeners; +package org.cloudsimplus.benchmarks; +import org.cloudsimplus.cloudlets.CloudletSimple; import org.cloudsimplus.hosts.HostSimple; import org.cloudsimplus.resources.PeSimple; import org.cloudsimplus.vms.VmSimple; @@ -34,10 +35,16 @@ import java.util.List; import java.util.function.IntFunction; -/// Measures the heap retained by each VM and Host, to compare the memory used -/// before and after the listener lists became the shared `List.of()` (issue #586). -/// Before that, each VM created 6 empty `ArrayList`s and each Host created -/// 2 empty `ArrayList`s and 1 empty `HashSet`, even when no listener was added. +/// Measures the heap retained by each VM, Host and Cloudlet (their memory footprint), +/// to compare CloudSim Plus versions. Since it measures the whole object (with everything it references), +/// it includes all changes that affect the footprint, such as: +/// - [#586](https://github.com/cloudsimplus/cloudsimplus/issues/586): listener lists start as the shared `List.of()`. +/// Before that, each VM created 6 empty `ArrayList`s and each Host created +/// 2 empty `ArrayList`s and 1 empty `HashSet`, even when no listener was added. +/// - [#587](https://github.com/cloudsimplus/cloudsimplus/issues/587): reduces the Cloudlet footprint. +/// Before that, each Cloudlet created 3 empty listener `HashSet`s, an empty `requiredFiles` `LinkedList` +/// and a new `UtilizationModelFull` for its CPU. Now, the listener and `requiredFiles` lists start as the shared `List.of()`, +/// and the CPU uses the shared `UtilizationModel.FULL`. /// /// It's a plain `main` (not JMH), since JMH measures time and allocation rate, /// but here we need the memory that stays in the heap after the objects are created. @@ -48,20 +55,19 @@ /// The results are only accurate with a stop-the-world GC, where [System#gc()] /// does a full collection, so run it with `-XX:+UseSerialGC`. /// -/// To compare CloudSim Plus 8.5.1 (before #586) with the current version, build and run it once for each version: +/// To compare CloudSim Plus 8.5.1 (before #586 and #587) with the current version, build and run it once for each version: /// /// ```bash /// ./mvnw clean package -Pcloudsimplus-8 # CloudSim Plus 8.5.1 -/// java -XX:+UseSerialGC -cp target/cloudsimplus-benchmarks-*-uber.jar org.cloudsimplus.listeners.ListenersMemoryBenchmark 8.5.1 +/// java -XX:+UseSerialGC -cp target/cloudsimplus-benchmarks-*-uber.jar org.cloudsimplus.benchmarks.MemoryFootprintBenchmark 8.5.1 /// /// ./mvnw clean package # current CloudSim Plus version -/// java -XX:+UseSerialGC -cp target/cloudsimplus-benchmarks-*-uber.jar org.cloudsimplus.listeners.ListenersMemoryBenchmark current +/// java -XX:+UseSerialGC -cp target/cloudsimplus-benchmarks-*-uber.jar org.cloudsimplus.benchmarks.MemoryFootprintBenchmark current /// ``` /// /// @author Manoel Campos da Silva Filho -/// @see CloudSim Plus issue #586 /// @see CloudSim Plus issue #523 -public final class ListenersMemoryBenchmark { +public final class MemoryFootprintBenchmark { /// Number of objects of each type created in each round. private static final int OBJECTS = 100_000; @@ -80,20 +86,24 @@ public final class ListenersMemoryBenchmark { private static final long HOST_BW = 10_000; private static final long HOST_STORAGE = 100_000; + private static final long CLOUDLET_LENGTH = 10_000; + private static final int CLOUDLET_PES = 1; + private static final MemoryMXBean MEMORY = ManagementFactory.getMemoryMXBean(); /// A private constructor to avoid class instantiation. - private ListenersMemoryBenchmark(){} + private MemoryFootprintBenchmark(){} /// Runs the benchmark. /// @param args an optional label to identify the CloudSim Plus version being measured (e.g., "before" or "after") public static void main(final String[] args) { final String label = args.length > 0 ? args[0] : "current"; System.out.printf("%s (%s): %,d objects per round, median of %d rounds%n", - ListenersMemoryBenchmark.class.getSimpleName(), label, OBJECTS, ROUNDS); + MemoryFootprintBenchmark.class.getSimpleName(), label, OBJECTS, ROUNDS); - printResult("VmSimple", measure(ListenersMemoryBenchmark::newVm)); - printResult("HostSimple", measure(ListenersMemoryBenchmark::newHost)); + printResult("VmSimple", measure(MemoryFootprintBenchmark::newVm)); + printResult("HostSimple", measure(MemoryFootprintBenchmark::newHost)); + printResult("CloudletSimple", measure(MemoryFootprintBenchmark::newCloudlet)); } private static VmSimple newVm(final int index) { @@ -106,6 +116,11 @@ private static HostSimple newHost(final int index) { return new HostSimple(HOST_RAM, HOST_BW, HOST_STORAGE, List.of(new PeSimple(PE_MIPS))); } + /// Creates a Cloudlet with the default utilization models. + private static CloudletSimple newCloudlet(final int index) { + return new CloudletSimple(CLOUDLET_LENGTH, CLOUDLET_PES); + } + /// {@return the median heap (in bytes) retained by each object created by a given function} /// @param factory a function that creates an object for a given index private static double measure(final IntFunction factory) { @@ -148,6 +163,6 @@ private static double median(final double[] values) { } private static void printResult(final String className, final double bytesPerObject) { - System.out.printf(" %-10s %8.1f bytes per object%n", className, bytesPerObject); + System.out.printf(" %-14s %8.1f bytes per object%n", className, bytesPerObject); } }